blitz3d/blitz3d/meshutil.cpp

230 lines
5.7 KiB
C++

#include "std.h"
#include "meshutil.h"
MeshModel *MeshUtil::createCube( const Brush &b ){
static Vector norms[]={
Vector(0,0,-1),Vector(1,0,0),Vector(0,0,1),
Vector(-1,0,0),Vector(0,1,0),Vector(0,-1,0)
};
static Vector tex_coords[]={
Vector(0,0,1),Vector(1,0,1),Vector(1,1,1),Vector(0,1,1)
};
static int verts[]={
2,3,1,0,3,7,5,1,7,6,4,5,6,2,0,4,6,7,3,2,0,1,5,4
};
static Box box( Vector(-1,-1,-1),Vector(1,1,1) );
MeshModel *m=d_new MeshModel();
Surface *s=m->createSurface( b );
Surface::Vertex v;
Surface::Triangle t;
for( int k=0;k<24;k+=4 ){
const Vector &normal=norms[k/4];
for( int j=0;j<4;++j ){
v.coords=box.corner( verts[k+j] );
v.normal=normal;
v.tex_coords[0][0]=v.tex_coords[1][0]=tex_coords[j].x;
v.tex_coords[0][1]=v.tex_coords[1][1]=tex_coords[j].y;
s->addVertex( v );
}
t.verts[0]=k;t.verts[1]=k+1;t.verts[2]=k+2;s->addTriangle(t);
t.verts[1]=k+2;t.verts[2]=k+3;s->addTriangle(t);
}
return m;
}
MeshModel *MeshUtil::createSphere( const Brush &b,int segs ){
int h_segs=segs*2,v_segs=segs;
MeshModel *m=d_new MeshModel();
Surface *s=m->createSurface( b );
Surface::Vertex v;
Surface::Triangle t;
v.coords=v.normal=Vector(0,1,0);
int k;
for( k=0;k<h_segs;++k ){
v.tex_coords[0][0]=v.tex_coords[1][0]=(k+.5f)/h_segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=0;
s->addVertex( v );
}
for( k=1;k<v_segs;++k ){
float pitch=k*PI/v_segs-HALFPI;
for( int j=0;j<=h_segs;++j ){
float yaw=(j%h_segs)*TWOPI/h_segs;
v.coords=v.normal=rotationMatrix( pitch,yaw,0 ).k;
v.tex_coords[0][0]=v.tex_coords[1][0]=float(j)/float(h_segs);
v.tex_coords[0][1]=v.tex_coords[1][1]=float(k)/float(v_segs);
s->addVertex( v );
}
}
v.coords=v.normal=Vector(0,-1,0);
for( k=0;k<h_segs;++k ){
v.tex_coords[0][0]=v.tex_coords[1][0]=(k+.5f)/h_segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=1;
s->addVertex( v );
}
for( k=0;k<h_segs;++k ){
t.verts[0]=k;
t.verts[1]=t.verts[0]+h_segs+1;
t.verts[2]=t.verts[1]-1;
s->addTriangle( t );
}
for( k=1;k<v_segs-1;++k ){
for( int j=0;j<h_segs;++j ){
t.verts[0]=k*(h_segs+1)+j-1;
t.verts[1]=t.verts[0]+1;
t.verts[2]=t.verts[1]+h_segs+1;
s->addTriangle( t );
t.verts[1]=t.verts[2];
t.verts[2]=t.verts[1]-1;
s->addTriangle( t );
}
}
for( k=0;k<h_segs;++k ){
t.verts[0]=(h_segs+1)*(v_segs-1)+k-1;
t.verts[1]=t.verts[0]+1;
t.verts[2]=t.verts[1]+h_segs;
s->addTriangle( t );
}
return m;
}
MeshModel *MeshUtil::createCylinder( const Brush &b,int segs,bool solid ){
MeshModel *m=d_new MeshModel();
Surface::Vertex v;
Surface::Triangle t;
Surface *s=m->createSurface( b );
int k;
for( k=0;k<=segs;++k ){
float yaw=(k%segs)*TWOPI/segs;
v.coords=rotationMatrix( 0,yaw,0 ).k;
v.coords.y=1;
v.normal=Vector(v.coords.x,0,v.coords.z);
v.tex_coords[0][0]=v.tex_coords[1][0]=float(k)/segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=0;
s->addVertex( v );
v.coords.y=-1;
v.tex_coords[0][0]=v.tex_coords[1][0]=float(k)/segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=1;
s->addVertex( v );
}
for( k=0;k<segs;++k ){
t.verts[0]=k*2;
t.verts[1]=t.verts[0]+2;
t.verts[2]=t.verts[1]+1;
s->addTriangle( t );
t.verts[1]=t.verts[2];
t.verts[2]=t.verts[1]-2;
s->addTriangle( t );
}
if( !solid ) return m;
s=m->createSurface( b );
for( k=0;k<segs;++k ){
float yaw=k*TWOPI/segs;
v.coords=rotationMatrix( 0,yaw,0 ).k;
v.coords.y=1;v.normal=Vector(0,1,0);
v.tex_coords[0][0]=v.tex_coords[1][0]=v.coords.x*.5f+.5f;
v.tex_coords[0][1]=v.tex_coords[1][1]=v.coords.z*.5f+.5f;
s->addVertex(v);
v.coords.y=-1;v.normal=Vector( 0,-1,0 );
s->addVertex(v);
}
for( k=2;k<segs;++k ){
t.verts[0]=0;
t.verts[1]=k*2;
t.verts[2]=(k-1)*2;
s->addTriangle( t );
t.verts[0]=1;
t.verts[1]=(k-1)*2+1;
t.verts[2]=k*2+1;
s->addTriangle( t );
}
return m;
}
MeshModel *MeshUtil::createCone( const Brush &b,int segs,bool solid ){
MeshModel *m=d_new MeshModel();
Surface::Vertex v;
Surface::Triangle t;
Surface *s;
s=m->createSurface( b );
int k;
v.coords=v.normal=Vector(0,1,0);
for( k=0;k<segs;++k ){
v.tex_coords[0][0]=v.tex_coords[1][0]=(k+.5f)/segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=0;
s->addVertex( v );
}
for( k=0;k<=segs;++k ){
float yaw=(k%segs)*TWOPI/segs;
v.coords=yawMatrix( yaw ).k;v.coords.y=-1;
v.normal=Vector( v.coords.x,0,v.coords.z );
v.tex_coords[0][0]=v.tex_coords[1][0]=float(k)/segs;
v.tex_coords[0][1]=v.tex_coords[1][1]=1;
s->addVertex( v );
}
for( k=0;k<segs;++k ){
t.verts[0]=k;
t.verts[1]=k+segs+1;
t.verts[2]=k+segs;
s->addTriangle( t );
}
if( !solid ) return m;
s=m->createSurface( b );
for( k=0;k<segs;++k ){
float yaw=k*TWOPI/segs;
v.coords=yawMatrix( yaw ).k;v.coords.y=-1;
v.normal=Vector( v.coords.x,0,v.coords.z );
v.tex_coords[0][0]=v.tex_coords[1][0]=v.coords.x*.5f+.5f;
v.tex_coords[0][1]=v.tex_coords[1][1]=v.coords.z*.5f+.5f;
s->addVertex( v );
}
t.verts[0]=0;
for( k=2;k<segs;++k ){
t.verts[1]=k-1;
t.verts[2]=k;
s->addTriangle( t );
}
return m;
}
void MeshUtil::lightMesh( MeshModel *m,const Vector &pos,const Vector &rgb,float range ){
if( range ){
float att=1.0f/range;
const MeshModel::SurfaceList &surfs=m->getSurfaces();
for( int k=0;k<surfs.size();++k ){
Surface *s=surfs[k];
for( int j=0;j<s->numVertices();++j ){
const Surface::Vertex &v=s->getVertex( j );
Vector lv=pos-v.coords;
float dp=v.normal.normalized().dot( lv );
if( dp<=0 ) continue;
float d=lv.length();
float i=1/(d*att)*(dp/d);
s->setColor( j,s->getColor(j)+rgb*i );
}
}
}else{
const MeshModel::SurfaceList &surfs=m->getSurfaces();
for( int k=0;k<surfs.size();++k ){
Surface *s=surfs[k];
for( int j=0;j<s->numVertices();++j ){
const Surface::Vertex &v=s->getVertex( j );
s->setColor( j,s->getColor(j)+rgb );
}
}
}
}