⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flymesh.cpp

📁 <B>《Realtime Rendering》的随书源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -