📄 3dsload.cpp
字号:
while((pc=dgetpos()) < p) { dread(&id, sizeof(id)); dread(&len, sizeof(len)); switch((unsigned int)id) { case CHUNK_OBJMESH: /*0x3D3D*/ ReadObjMeshBlocks(pc+len); break; case CHUNK_KEYFRAMER:/*0xB000*/
//此处可以加入对关键帧信息的读取函数 default:
dsetpos(pc+len); } }}//从文件中读入一个H3dsScene数据结构
//这里是3DS场景读取的主函数,函数首先从文件中读入3DS文件标识,即基本块标识,若标识不正确
//则说明不是一个合法的3DS文件。否则按3DS文件的组织,读入其主块信息。/* Reads in a H3dsScene from the disk */H3dsScene *HRead3dsScene(void *ptr, int what, dword size) { int retval = setjmp(EnvState); if(ptr==0) return 0; if(what==0) InFile=(FILE *) ptr; else return 0; /* Initialize the global var Scene & fill with zeroes */
//初始化全局数据结构Scene,并将其初值置为0 if ((Scene=(H3dsScene *) malloc(sizeof(H3dsScene)))==0) return 0; memset(Scene, 0, sizeof(H3dsScene)); Scene->material = 0; Scene->NumMaterials = 0; if(retval==0) { /* Return address set, start loading 3DS data. */
//返回地址集合,开始装入3DS数据 word id; dword len, pc; //读入3DS文件标识 pc=dgetpos(); dread(&id, sizeof(id)); dread(&len, sizeof(len));
//标识不正确,非3DS文件 if((int)id!=CHUNK_MAIN) {/*0x4D4D*/
//将分配到的空间释放 HFree3dsScene(Scene); AfxMessageBox("所打开的文件可能不是一个合法的3DS文件."); return 0; } ReadMainBlocks(pc+len); } else { /* There was an error, free the allocated mem and return NULL. */
//读取数据出错,也将分配到的空间释放。 HFree3dsScene(Scene); return 0; } return Scene;}//将内部数据结构填充到一个易于读取的数据结构中//Feed our internal data to the outgl.cpp functionsvoid Convert_to_OUTGL() { int x,y,z;
int faceindex; int current; int MaterialNum; void *ptr;
float32 *m; float32 swap; OUTGL_RGB ambient, diffuse, specular; OUTGL_VERTEX v; OUTGL_TRIANGLE tri; char *name;
MaterialNum=Scene->NumMaterials;//add by jiangzibin
ptr=NULL;
m=0; //Start with the material properties //If the model has default materials in it, substitute an all-white material
//如果模型使用默认材质,则将默认材质定义为一个全白色的材质。
if (defaultmaterialwarning) {
ambient.red = \ ambient.green = \ ambient.blue = 1.0; ambient.alpha = 1.0; diffuse.red = \ diffuse.green = \ diffuse.blue = 1.0; diffuse.alpha = 1.0; specular.red = \ specular.green = \ specular.blue = 1.0; specular.alpha = 1.0; OutGLAddMaterial(ambient, diffuse, specular, "WG_DEFAULT", "", 1); }
//将每个材质的名称及其属性填入OutGL结构中 //Feed each material and its properties to OutGL for (x=0; x<Scene->NumMaterials; x++) {
H3dsMat *mat = &Scene->material[x]; ambient.red = mat->ambient.red; ambient.green = mat->ambient.green; ambient.blue = mat->ambient.blue; ambient.alpha = 1.0; diffuse.red = mat->diffuse.red; diffuse.green = mat->diffuse.green; diffuse.blue = mat->diffuse.blue; diffuse.alpha = 1.0; specular.red = mat->specular.red; specular.green = mat->specular.green; specular.blue = mat->specular.blue; specular.alpha = 1.0; OutGLAddMaterial(ambient, diffuse, specular, mat->name, mat->texture.texturename,\
mat->doublesided); }
// AfxMessageBox("Break Here"); //再将每个顶点和多边形的信息填入OutGL结构中,需注意顶点的填入顺序 //Then do the vertices and polygons //Order is important! current = 0;
for (x=0; x<Scene->meshobjs; x++) {
H3dsMeshObj *meshobj = &Scene->meshobjlist[x]; //交换y,z坐标 //Swap y and z (.3ds wierdness) for (y=0; y<meshobj->NumVerts; y++) { swap = meshobj->vertlist[y].y; meshobj->vertlist[y].y = meshobj->vertlist[y].z; meshobj->vertlist[y].z = swap; } //将顶点信息填入OutGL结构中去 //Feed the vertices to outgl for (y=0; y<meshobj->NumVerts; y++) { v.x = meshobj->vertlist[y].x; v.y = meshobj->vertlist[y].y; v.z = meshobj->vertlist[y].z; if (meshobj->NumMaps) { v.u = meshobj->maplist[y].u; v.v = meshobj->maplist[y].v; }
else { v.u = 0; v.v = 0; }
OutGLAddVertex(v); } for (y=0; y<meshobj->NumBindings; y++) { name = meshobj->bindings[y].name; for (z=0; z<meshobj->bindings[y].NumFaces; z++) {
//将多边形反向,即三角形(0,1,2)=>(0,2,1) // Flip the polygon orientation by using points (0,2,1)
faceindex=meshobj->bindings[y].faces[z]; tri.p0 = meshobj->facelist[faceindex].p0 + current; tri.p1 = meshobj->facelist[faceindex].p2 + current; tri.p2 = meshobj->facelist[faceindex].p1 + current; OutGLAddPolygon(tri, name); } }
current += meshobj->NumVerts; } //将OutGL中所有内容包装起来 //Wrap everything up in the outgl object
OutGLFinishModel();
} /********************************************************************************************** Function to read in the .3DS file *filename and assign its contents to the polygon and object classes. This kicks the whole 3DS parsing off. *********************************************************************************************/
//读入3DS文件,并将它的所有内容赋给多边形和物体类M3DSObject* Load3DSObject(char *filename)
{ FILE *inf; H3dsScene *scene;
long size; doublesided = defaultmaterialwarning = 0; //以二进制方式打开文件 /* Open & prepare input file */ if(!(inf = fopen(filename, "rb"))) {
CString str;
str.Format("打开文件 %s 时失败了",filename);
AfxMessageBox(str); return NULL; } if(fseek(inf, 0, SEEK_END)) {
fclose(inf); return NULL; } if((size=ftell(inf)) == -1L) {
fclose(inf); return NULL; } rewind(inf); //读入文件将其内容放入scene中去 /* Read in the file and place it in *scene */ if((scene = HRead3dsScene(inf, 0, size)) == 0) {
fclose(inf); return NULL; }
fclose(inf); /* Convert our internal data structure to outgl's structure */
//将内部数据转换为OutGL的结构
if (!(Obj3DS = (M3DSObject *) malloc(sizeof(M3DSObject))))
return NULL;
Obj3DS->NumPolygon=0;
Obj3DS->NumVertex=0;
Convert_to_OUTGL();
HFree3dsScene(scene);
Obj3DS->NumVertex=NumVertex;
Obj3DS->VertexLists=VertexList;
Obj3DS->NumPolygon=NumPolyLists;
Obj3DS->strip=0;
Obj3DS->PolygonLists=PolyList;
Unitize3DSObject(Obj3DS);
//存储空间由Obj3DS释放
NumVertex=0;
VertexList=NULL;
NumPolyLists=0;
PolyList=NULL;
return Obj3DS;}
static GLfloat OutputAbs(GLfloat f){
if(f<0)
return -f;
return f;
}
static GLfloat OutputMax(GLfloat a,GLfloat b){
if(b>a)
return b;
return a;
}
static float m_center[3], m_minXYZ[3], m_maxXYZ[3], m_range[3];
static float m_scaleFactor;
//将3DS模型归一化,即将模型平移到原点,并缩放到每个坐标均在[-1,1]
//范围的立方体中。
void Unitize3DSObject(M3DSObject *object)
{
if(object==NULL)
return;
if(object->VertexLists==NULL)
return;
GLfloat maxx,minx,maxy,miny,maxz,minz;
GLfloat cx,cy,cz,w,h,d;
GLfloat scale;
minx=miny=minz=(GLfloat)1E+20;
maxx=maxy=maxz=(GLfloat)1E-20;
for(unsigned int i=0;i<object->NumVertex;i++){
if(maxx<object->VertexLists[i].x)
maxx=object->VertexLists[i].x;
if(minx>object->VertexLists[i].x)
minx=object->VertexLists[i].x;
if(maxy<object->VertexLists[i].y)
maxy=object->VertexLists[i].y;
if(miny>object->VertexLists[i].y)
miny=object->VertexLists[i].y;
if(maxz<object->VertexLists[i].z)
maxz=object->VertexLists[i].z;
if(minz>object->VertexLists[i].z)
minz=object->VertexLists[i].z;
}
//计算模型的宽度、高度和深度
w=OutputAbs(maxx)+OutputAbs(minx);
h=OutputAbs(maxy)+OutputAbs(miny);
d=OutputAbs(maxz)+OutputAbs(minz);
//计算模型的中心
cx=(maxx+minx)/2.0f;
cy=(maxy+miny)/2.0f;
cz=(maxz+minz)/2.0f;
//计算归一化所需的缩放比例
scale=2.0f/OutputMax(OutputMax(w,h),d);
m_scaleFactor=scale;
m_minXYZ[0]=-w*scale;
m_minXYZ[1]=-h*scale;
m_minXYZ[2]=-d*scale;
m_maxXYZ[0]= w*scale;
m_maxXYZ[1]= h*scale;
m_maxXYZ[2]= d*scale;
m_range[0]=2*w*scale;
m_range[1]=2*h*scale;
m_range[2]=2*d*scale;
m_center[0]=m_center[1]=m_center[2]=0;
//先平移到原点,再缩放
for(unsigned int m=0;m<object->NumVertex;m++){
object->VertexLists[m].x-=cx;
object->VertexLists[m].y-=cy;
object->VertexLists[m].z-=cz;
object->VertexLists[m].x*=scale;
object->VertexLists[m].y*=scale;
object->VertexLists[m].z*=scale;
}
}
void GetMinMax3DS(float min[3], float max[3], float *scaleFactor)
{
min[0]=m_minXYZ[0];
min[1]=m_minXYZ[1];
min[2]=m_minXYZ[2];
max[0]=m_maxXYZ[0];
max[1]=m_maxXYZ[1];
max[2]=m_maxXYZ[2];
*scaleFactor=m_scaleFactor;
}
H3dsMat *FindMaterial(char *name){
for(int i=0;i<Scene->NumMaterials;i++){
if(strcmp(Scene->material->name,name)==0){
return Scene->material;
}
}
return NULL;
}
void Draw3DSObject(M3DSObject *object)
{
/* Draw sparse triangles */
glInterleavedArrays(GL_T2F_N3F_V3F, 0,object->VertexLists);
for (unsigned int m=0; m<object->NumPolygon; m++) {
glMaterialfv(GL_FRONT, GL_AMBIENT, (GLfloat *) &object->PolygonLists[m].ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, (GLfloat *) &object->PolygonLists[m].diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, (GLfloat *) &object->PolygonLists[m].specular);
glDrawElements(GL_TRIANGLES,
object->PolygonLists[m].NumTriangles*3,
GL_UNSIGNED_INT,
object->PolygonLists[m].CrunchedTriangleIndexList);
}
}
void Free3DSObject(M3DSObject *object)
{
unsigned int i;
unsigned int nv=object->NumVertex;
free(object->VertexLists);
object->VertexLists=NULL;
for (i=0; i<object->NumPolygon; i++) {
free (object->PolygonLists[i].TriangleIndexList);
object->PolygonLists[i].TriangleIndexList=NULL;
free (object->PolygonLists[i].CrunchedTriangleIndexList);
object->PolygonLists[i].CrunchedTriangleIndexList=NULL;
}
free(object);
object=NULL;
OUTGL_TRIANGLENODE *TempPtr, *LList;
for (i=0; i<nv; i++) {
LList = CommonTriangleList[i];
while (LList) {
TempPtr = LList;
LList = LList->next;
free (TempPtr);
}
}
free (CommonTriangleList);
CommonTriangleList=NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -