📄 flymesh.cpp
字号:
#include "../Fly3D.h"
#define INCHE_TO_DECIMETER 0.254f
class import_3ds_mesh : private import3ds
{
mesh *obj;
int v,f,t,basev,basef;
float *tx;
void object3d(char *name,int nv,int nf,int ntc,float *local_axis);
void vertex3(float *vec);
void text_coord(float *uv);
void face3(unsigned short *fa);
void face_material(material *mat,int nf,unsigned short *faces);
public:
import_3ds_mesh(char *file,mesh *m);
};
void mesh::reset()
{
if (vert)
delete vert;
if (vertnorm)
delete vertnorm;
if (faces)
delete faces;
if (localfaces)
delete localfaces;
if (edges)
delete edges;
vert=0;
vertnorm=0;
faces=0;
nv=0;
nf=0;
localfaces=0;
edges=0;
nedges=0;
color.vec(0.0f,0.0f,0.0f);
}
mesh *mesh::clone()
{
mesh *m=new mesh;
*m=*this;
m->vert=new vector[nv];
m->vertnorm=new vector[nv];
m->edges=new int[nedges*4];
memcpy(m->vert,vert,sizeof(vector)*nv);
memcpy(m->vertnorm,vertnorm,sizeof(vector)*nv);
memcpy(m->edges,edges,sizeof(int)*nedges*4);
m->faces=new face *[nf];
m->localfaces=new face[nf];
for( int i=0;i<nf;i++ )
{
m->faces[i]=&m->localfaces[i];
m->localfaces[i]=localfaces[i];
m->localfaces[i].vert[0]=&m->vert[localfaces[i].vert[0]-vert];
m->localfaces[i].vert[1]=&m->vert[localfaces[i].vert[1]-vert];
m->localfaces[i].vert[2]=&m->vert[localfaces[i].vert[2]-vert];
}
return m;
}
int mesh::get_edge(int v1,int v2)
{
int i,j;
for( i=j=0;i<nedges;i++,j+=4 )
if ((v1==edges[j] && v2==edges[j+1]) ||
(v1==edges[j+1] && v2==edges[j]))
return i;
return -1;
}
void mesh::compute_normals(int flag)
{
int i,j;
vector v1,v2;
if (flag&MESH_IMPLODE)
implode();
if (flag&MESH_FACENORM)
for( i=0;i<nf;i++ )
{
v1=*faces[i]->vert[1]-*faces[i]->vert[0];
v2=*faces[i]->vert[2]-*faces[i]->vert[0];
faces[i]->normal.cross(v1,v2);
faces[i]->normal.normalize();
faces[i]->d0=-vec_dot(faces[i]->normal,*faces[i]->vert[0]);
for( j=0;j<3;j++ )
{
faces[i]->edgenormal[j].cross(
*faces[i]->vert[(j+1)%3]-*faces[i]->vert[j],
faces[i]->normal);
faces[i]->edgenormal[j].normalize();
}
}
if ((flag&MESH_VERTNORM) && vert)
{
if (vertnorm)
delete vertnorm;
vertnorm=new vector[nv];
memset(vertnorm,0,sizeof(vector)*nv);
for( j=0;j<nf;j++ )
{
vertnorm[faces[j]->vert[0]-vert]+=faces[j]->normal;
vertnorm[faces[j]->vert[1]-vert]+=faces[j]->normal;
vertnorm[faces[j]->vert[2]-vert]+=faces[j]->normal;
}
for( j=0;j<nv;j++ )
vertnorm[j].normalize();
for( i=0;i<nf;i++ )
for( j=0;j<3;j++ )
faces[i]->vertnormal[j]=vertnorm[faces[i]->vert[j]-vert];
}
if (flag&MESH_BBOX)
{
bbox.reset();
for( i=0;i<nf;i++ )
for( j=0;j<3;j++ )
bbox.add_point(*faces[i]->vert[j]);
}
if (flag&MESH_EDGES)
{
if (edges)
delete edges;
edges=new int[nf*3*4];
nedges=0;
int e,i1,i2;
// for each face
for( i=0;i<nf;i++ )
// for each face edge
for( j=0;j<3;j++ )
{
i1=faces[i]->vert[j]-vert;
i2=faces[i]->vert[(j+1)%3]-vert;
e=get_edge(i1,i2);
// if edge is not in edge list
if (e==-1)
{
// add a new edge to the list
edges[nedges*4]=i1;
edges[nedges*4+1]=i2;
edges[nedges*4+2]=i;
edges[nedges*4+3]=-1;
nedges++;
}
else
if ((faces[i]->color-faces[edges[e*4+2]]->color).length()<0.1f)
edges[e*4+3]=i;
}
}
}
int mesh::load_3ds(char *name)
{
import_3ds_mesh i(name,this);
compute_normals(MESH_IMPLODE|MESH_FACENORM|MESH_VERTNORM|MESH_BBOX);
return nf>0;
}
import_3ds_mesh::import_3ds_mesh(char *file,mesh *m)
{
obj=m;
basev=0;
basef=0;
tx=0;
t=0;
if (obj && file && file[0])
import(file,INCHE_TO_DECIMETER);
int i;
for( i=0;i<obj->nf;i++ )
{
obj->faces[i]->vert[0]=&obj->vert[(int)obj->faces[i]->vert[0]];
obj->faces[i]->vert[1]=&obj->vert[(int)obj->faces[i]->vert[1]];
obj->faces[i]->vert[2]=&obj->vert[(int)obj->faces[i]->vert[2]];
}
if (tx) delete tx;
}
void import_3ds_mesh::object3d(char *name,int nv,int nf,int ntc,float *local_axis)
{
v=f=0;
basev=obj->nv;
basef=obj->nf;
obj->pivotpos.x=local_axis[9];
obj->pivotpos.y=local_axis[10];
obj->pivotpos.z=local_axis[11];
face *tf;
tf=new face[nf+obj->nf];
if (obj->localfaces)
{
memcpy(tf,obj->localfaces,sizeof(face)*obj->nf);
delete obj->localfaces;
}
obj->localfaces=tf;
vector *tv=new vector[nv+obj->nv];
if (obj->vert)
{
memcpy(tv,obj->vert,sizeof(vector)*obj->nv);
delete obj->vert;
}
obj->vert=tv;
float *ttx=new float[2*(obj->nv+nv)];
if (tx)
{
memcpy(ttx,tx,sizeof(float)*2*obj->nv);
delete tx;
}
tx=ttx;
obj->nv+=nv;
obj->nf+=nf;
if (obj->faces)
delete obj->faces;
obj->faces=new face *[obj->nf];
int i;
for( i=0;i<obj->nf;i++ )
obj->faces[i]=&obj->localfaces[i];
}
void import_3ds_mesh::vertex3(float *vec)
{
obj->vert[basev+v].x=vec[0];
obj->vert[basev+v].y=vec[1];
obj->vert[basev+v].z=vec[2];
v++;
}
void import_3ds_mesh::text_coord(float *uv)
{
tx[t*2]=uv[0];
tx[t*2+1]=uv[1];
t++;
}
void import_3ds_mesh::face3(unsigned short *fa)
{
obj->faces[basef+f]->vert[0]=((vector *)(fa[0]+basev));
obj->faces[basef+f]->vert[1]=((vector *)(fa[1]+basev));
obj->faces[basef+f]->vert[2]=((vector *)(fa[2]+basev));
obj->faces[basef+f]->uv[0][0]=tx[(fa[0]+basev)*2];
obj->faces[basef+f]->uv[0][1]=tx[(fa[0]+basev)*2+1];
obj->faces[basef+f]->uv[1][0]=tx[(fa[1]+basev)*2];
obj->faces[basef+f]->uv[1][1]=tx[(fa[1]+basev)*2+1];
obj->faces[basef+f]->uv[2][0]=tx[(fa[2]+basev)*2];
obj->faces[basef+f]->uv[2][1]=tx[(fa[2]+basev)*2+1];
obj->faces[basef+f]->texpic=-1;
obj->faces[basef+f]->lm=-1;
obj->faces[basef+f]->color.vec(0.5f,0.5f,0.5f,0.5f);
obj->faces[basef+f]->emmradius=0.0f;
obj->faces[basef+f]->lastdraw=0;
f++;
}
void import_3ds_mesh::face_material(material *mat,int nf,unsigned short *faces)
{
int i,pic;
if (mat->map_texture1.filename[0])
pic=flyengine->get_picture(mat->map_texture1.filename);
else pic=-1;
for( i=0;i<nf;i++ )
{
obj->faces[faces[i]+basef]->texpic=pic;
obj->faces[faces[i]+basef]->color.x=mat->diffuse[0];
obj->faces[faces[i]+basef]->color.y=mat->diffuse[1];
obj->faces[faces[i]+basef]->color.z=mat->diffuse[2];
obj->faces[faces[i]+basef]->color.w=1-mat->transparency;
}
}
int face::ray_intersect(vector& ro,vector& rd,vector& ip,float& dist,float rad)
{
if (rad==0.0f)
{
float x=vec_dot(normal,rd);
if (x>-SMALL || *((int *)&color.w)==0)
return 0;
dist=(vec_dot(normal,*vert[0])-vec_dot(normal,ro))/x;
if (dist<0)
return 0;
ip.x=ro.x+rd.x*dist;
ip.y=ro.y+rd.y*dist;
ip.z=ro.z+rd.z*dist;
int i;
for( i=0;i<3;i++ )
if ((ip.x-vert[i]->x)*edgenormal[i].x+
(ip.y-vert[i]->y)*edgenormal[i].y+
(ip.z-vert[i]->z)*edgenormal[i].z > 0)
return 0;
return 1;
}
else
{
static vector v[3],n;
v[0].x=vert[0]->x+vertnormal[0].x*rad;
v[0].y=vert[0]->y+vertnormal[0].y*rad;
v[0].z=vert[0]->z+vertnormal[0].z*rad;
v[1].x=vert[1]->x+vertnormal[1].x*rad;
v[1].y=vert[1]->y+vertnormal[1].y*rad;
v[1].z=vert[1]->z+vertnormal[1].z*rad;
v[2].x=vert[2]->x+vertnormal[2].x*rad;
v[2].y=vert[2]->y+vertnormal[2].y*rad;
v[2].z=vert[2]->z+vertnormal[2].z*rad;
n.cross(v[1]-v[0],v[2]-v[0]);
n.normalize();
float x=vec_dot(n,rd);
if (x>-SMALL || *((int *)&color.w)==0)
return 0;
dist=(vec_dot(n,v[0])-vec_dot(n,ro))/x;
if (dist<0)
return 0;
ip.x=ro.x+rd.x*dist;
ip.y=ro.y+rd.y*dist;
ip.z=ro.z+rd.z*dist;
int i,j,crossings=0,u0,u1;
n.x=(float)fabs(n.x);
n.y=(float)fabs(n.y);
n.z=(float)fabs(n.z);
if (n.x>n.y && n.x>n.z)
{ u0=1; u1=2; }
else
if (n.y>n.x && n.y>n.z)
{ u0=0; u1=2; }
else
{ u0=0; u1=1; }
v[0][u0]-=ip[u0];
v[1][u0]-=ip[u0];
v[2][u0]-=ip[u0];
v[0][u1]-=ip[u1];
v[1][u1]-=ip[u1];
v[2][u1]-=ip[u1];
for( i=0; i<3; i++ )
{
j=(i+1) % 3;
if(((v[i][u1]<-SMALL) && (v[j][u1]>=0)) || ((v[j][u1]<-SMALL) && (v[i][u1]>=0.0)))
if((v[i][u0]>=0.0) && (v[j][u0]>=0.0))
++crossings;
else
if((v[i][u0]>=0.0) || (v[j][u0]>=0.0))
if((v[i][u0]-v[i][u1]*(v[j][u0]-v[i][u0])/(v[j][u1]-v[i][u1]))>SMALL)
++crossings;
}
if((crossings%2)==0)
return 0;
else
return 1;
}
}
int mesh::ray_intersect(vector& ro,vector& rd,vector& ip,float& dist,float rad)
{
static vector tmp_ip;
static float tmp_dist;
int i,f=-1;
dist=BIG;
for( i=0;i<nf;i++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -