📄 3dsload.cpp
字号:
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 + -