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

📄 3dsload.cpp

📁 这是书上的代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	return JOB_DONE;
}


/********************************************************************************************* 
 * Returns the cosine of the angle between two normals.
 * Since the normals are already normalized, we don't need to
 * divide by the product of their magnitudes. We only need
 * to return the dot product since the denominator will always
 * be 1.
 *********************************************************************************************/
//计算两个三角形的法向量夹角的余弦
//求两个三角形的法向量夹角的余弦,因为两个法向量均已单位化,故直接计算其点积即可
GLfloat cos_angle(OUTGL_SURFACE *n1, OUTGL_SURFACE *n2) {

	GLfloat dot;

	dot = n1->n0 * n2->n0 +n1->n1 * n2->n1 +n1->n2 * n2->n2;

	return dot;
}


/*
 * Returns the angle of a triangle at the specified 
 * vertex. 
 * square(c) = square(a) + square(b) + 2*a*b*cos(theta)
 * which is a general form of Pythagorean's theorem.
 */
//计算一个三角形在某个顶点处的夹角
//  
GLfloat angle(OUTGL_SURFACE *triangle, GLuint vertex) {
  
	double result;
	double a,b,c;
	//先判断是哪一个顶点
	if (triangle->p0 == vertex) {
		//计算三条边长
		a = distance(&VertexList[triangle->p0], &VertexList[triangle->p1]);
		b = distance(&VertexList[triangle->p0], &VertexList[triangle->p2]);
		c = distance(&VertexList[triangle->p1], &VertexList[triangle->p2]);
	} 
	else if (triangle->p1 == vertex) {
		a = distance(&VertexList[triangle->p1], &VertexList[triangle->p0]);
		b = distance(&VertexList[triangle->p1], &VertexList[triangle->p2]);
		c = distance(&VertexList[triangle->p2], &VertexList[triangle->p0]);
	} 
	else if (triangle->p2 == vertex) {
		a = distance(&VertexList[triangle->p2], &VertexList[triangle->p0]);
		b = distance(&VertexList[triangle->p2], &VertexList[triangle->p1]);
		c = distance(&VertexList[triangle->p0], &VertexList[triangle->p1]);
	}
  
	result = c*c - a*a - b*b;
	result /= 2*a*b;
	result = acos(result);

	return (GLfloat) result;

}

//计算两个三维点之间的距离
/* Distance between two 3D points */
double distance(OUTGL_VERTEX *v1, OUTGL_VERTEX *v2) {
  
	double dx, dy, dz;
	double result;
  
	dx = fabs((v1->x - v2->x)*(v1->x - v2->x));
	dy = fabs((v1->y - v2->y)*(v1->y - v2->y));
	dz = fabs((v1->z - v2->z)*(v1->z - v2->z));

	result = sqrt(dx + dy + dz);
	return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////* General 3DS Reader Utility Functions */
//1.一组文件操作函数//从文件中读入len字节的数据到dest指针指向的内存中/* Reads len number of bytes from the file into the memory pointed to by *dest */void dread(void *dest, int len){	char *ptr, tmp1, tmp2, tmp3, tmp4;	//Initialize add by JiangZibin	ptr=NULL;
	tmp1=tmp2=tmp3=tmp4=0;
	if(fread(dest, len, 1, InFile) != 1) {
		longjmp(EnvState, 1);	}#ifdef NONINTEL	// Endian Issues 	if (len == 2) {    // Swap a 16-bit int		ptr = (char *)dest;		tmp1 = *ptr;		*ptr = *(ptr + 1);		*(ptr + 1) = tmp1;	}
	else if (len == 4) {    // Swap a 32-bit int		ptr = (char *)dest;		tmp1 = *ptr;		tmp2 = *(ptr + 1);		tmp3 = *(ptr + 2);		tmp4 = *(ptr + 3);		*ptr = tmp4;		*(ptr + 1) = tmp3;		*(ptr + 2) = tmp2;		*(ptr + 3) = tmp1;	} #endif}//将文件指针移到指定的位置/* Sets the file pointer to a specific position */void dsetpos(dword pos){	if(fseek(InFile, (long)pos, SEEK_SET) != 0) {
		longjmp(EnvState, 1);	}}//找到文件当前位置/* Retrieves the file position */dword dgetpos(void){	long pos;	if((pos=ftell(InFile)) == -1L) {
		longjmp(EnvState, 1);	}	return (dword) pos;}///////////////////////////////////////////////////////////////////////////////////////////////
//2.内存申请和释放//扩大scene数组,以装入新的形体对象/* Enlarge the scene array to hold a new mesh object */H3dsMeshObj *EnlargeMeshArray(void) {	void *mem;	H3dsMeshObj *obj;	if((mem = realloc(Scene->meshobjlist, 		    sizeof(H3dsMeshObj)*(Scene->meshobjs+1))) == 0) {
		longjmp(EnvState, 1);	}	Scene->meshobjlist=(H3dsMeshObj *) mem;	obj=&Scene->meshobjlist[Scene->meshobjs++];	memset(obj, 0, sizeof(H3dsMeshObj));	return obj;}//扩大scene数组,以装入新的材质/* Enlarge the scene array to hold a new material */H3dsMat *EnlargeMatObjArray(void) {	void *mem;	H3dsMat *obj;	if((mem = realloc(Scene->material, 		    sizeof(H3dsMat)*(Scene->NumMaterials+1))) == 0) {
		longjmp(EnvState, 1);	}	Scene->material=(H3dsMat *) mem;	obj = &Scene->material[Scene->NumMaterials++];	memset(obj, 0, sizeof(H3dsMat));	return obj;}//扩大scene数组,以装入另一个捆绑的列表/* Enlarges the bindings array to hold another bindings list */H3dsMatList *EnlargeBindingsArray(H3dsMeshObj *meshobj) {	void *mem;	H3dsMatList *obj;	if((mem = realloc(meshobj->bindings, 		    sizeof(H3dsMatList)*(meshobj->NumBindings+1))) == 0) {		longjmp(EnvState, 1);	}	meshobj->bindings = (H3dsMatList *)mem;	obj = &meshobj->bindings[meshobj->NumBindings++];	memset(obj, 0, sizeof(H3dsMatList));    	return obj;}//安全地分配一定大小的内存/* Safely allocates a size amount of memory */void *getmem(int size){	void *mem;	if((mem=malloc(size))==0) {		longjmp(EnvState, 1);	}	return mem;}//从内存中将H3dsScene删除/* Deletes an H3dsScene from memory */void HFree3dsScene(H3dsScene * scene){	int n,m;	if(scene) {		if(scene->meshobjlist) {			for(n=scene->meshobjs-1; n>=0; n--) {				H3dsMeshObj *mobj = &scene->meshobjlist[n];				if(mobj->maplist)  					free(mobj->maplist);				if(mobj->facelist) 					free(mobj->facelist);				if(mobj->vertlist) 					free(mobj->vertlist);				if (mobj->bindings) {					for (m=0; m<mobj->NumBindings; m++) {						if (mobj->bindings[m].faces) {							free (mobj->bindings[m].faces);						}					}					free (mobj->bindings);				}			}			free(scene->meshobjlist);		}		if (scene->material)
			free (scene->material);		free(scene);	}}/******************************************************//*3. 3DS Reader Routines 将3DS文件读入到相应的数据结构中*//******************************************************///读入当前形体对象的顶点列表(4110).
//3DS文件中顶点的定义比较简单,它由一个表示顶点数目的整型
//数开始,接着是相应数目的顶点定义信息,每个顶点由3个浮点
//数分别表示其3个坐标。/* Reads in the list of vertices for the current mesh object */void ReadVertList(H3dsMeshObj *meshobj){	word nv;	int n;	dread(&nv, sizeof(nv));	meshobj->NumVerts=nv;	meshobj->vertlist=(H3dsVert *) getmem(sizeof(H3dsVert)*nv);	for(n=0; n<nv; n++)	{		dread(&meshobj->vertlist[n].x, sizeof(float32));		dread(&meshobj->vertlist[n].y, sizeof(float32));		dread(&meshobj->vertlist[n].z, sizeof(float32));	}}/**********************************************************************************************  Reads in the face list for the current mesh object.  Each face is a set of 3 indexes into the mesh object's   vertex list and a set of options.  ********************************************************************************************/
//读入当前形体对象的面列表(4120)
//由于3DS中定义的每一个面都是三角形,因此,该函数从文件中读入的面列表就是三角形列表,每个三角形
//由它的3个顶点的序号以及一个面信息(标识)组成。文件中的第一项是三角形的数目,其后跟相应数目的三
//角形定义数据(包括3个顶点的序号和标识顶点顺序的面信息),面信息包含3个顶点的顺序。word ReadFaceList(H3dsMeshObj *meshobj){	word nv;	word swap;	int n;	//先读出3DS文件中面的个数	dread(&nv, sizeof(nv));	meshobj->NumFaces=nv;	//根据面的个数申请足够的内存	meshobj->facelist=(H3dsFace *) getmem(sizeof(H3dsFace)*nv);	for(n=0; n<nv; n++)	{		dread(&meshobj->facelist[n].p0, sizeof(word));		dread(&meshobj->facelist[n].p1, sizeof(word));		dread(&meshobj->facelist[n].p2, sizeof(word));		dread(&meshobj->facelist[n].flags, sizeof(word));		/* 		 * 0x07 means that the AB, BC, and CA edges are all wound 		 * in the reverse order, so swap the last two vertices 		 */
		//面信息为0x07表示三角形是按顺时针方向定义的,而在OpenGL中要求
		//按逆时针方向给出,故需要将后面2个顶点的顺序交换		if (meshobj->facelist[n].flags == 0x07) {			swap = meshobj->facelist[n].p1;			meshobj->facelist[n].p1 = meshobj->facelist[n].p2;			meshobj->facelist[n].p2 = swap;		}	}	return (nv); /* WG */}//读入当前形体对象的纹理映射坐标(4140)
//纹理坐标列表也是由一个表示顶点数目的整型数开始,接着跟一组纹理坐标构成。
//每一组纹理坐标由u,v两个浮点值定义。/* Reads in the mapping list/texture coords. for the current mesh object */void ReadMapList(H3dsMeshObj *meshobj){	word nv;	int n;	dread(&nv, sizeof(nv));	meshobj->NumMaps=nv;	//为纹理坐标申请足够的内存	meshobj->maplist=(H3dsMap *) getmem(sizeof(H3dsMap)*nv);	for(n=0; n<nv; n++)	{		dread(&meshobj->maplist[n].u, sizeof(float32));		dread(&meshobj->maplist[n].v, sizeof(float32));	}}/**********************************************************************************************   Reads in the translation matrix for the current mesh object.  I'm not sure when this is used in a 3DS model.  ********************************************************************************************/
//读入当前形体对象的平移矩阵.(4160)
//形体对象的平移矩阵是12个浮点数组成的数组,表示一个3*4的矩阵。void ReadTraMatrix(H3dsMeshObj *meshobj){	int i;	for (i=0;i<12;i++)  		dread(&meshobj->TraMatrix[i], sizeof(float32));	meshobj->matrix=1;	}/**********************************************************************************************  Assigns the material in this chunk to the faces specified.   Each material has a list of indexes into the face array to  mark which faces use which material.  ********************************************************************************************/
//为多边形指定块中的材质(4130)
//在3DS中是根据名称索引材质的,文件中给出了每种名称的材质对应的多边形列表,以表明哪些多边形使用
//了该材质。每种材质首先给出的是它的名称,接着是与该材质相关的多边形个数,然后再给出相应数目的
//多边形在多边形列表中的下标。void ReadFaceMaterial(H3dsMeshObj *meshobj){	uword nf;	uword face;	char name[50];	H3dsMatList *binding;	int n;	binding = EnlargeBindingsArray(meshobj);	//首先是材质的名称	/* The material name is first */	n=0;	do {		dread(&name[n++], 1);	} while(name[n-1]!='\0' && n<sizeof(name));	name[n-1]='\0';	strcpy(binding->name, name);	//然后是多边形的个数	/* Then the number of faces */	dread(&nf, sizeof(nf));	binding->NumFaces = (int)nf;	binding->faces = (word *)(malloc(sizeof(face)*nf));	//将材质同用到该材质的多边形捆绑到一起	/* Bind the faces to the material */	for (n=0; n<nf; n++) {		dread(&face, sizeof(face));		binding->faces[n] = face;	}} //读默认材质
//为所有nf个多边形建立其默认材质WG_DEFAULT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -