1、3DS读取在OpenGL中读取3DS模型文件这里要解决的一个关键问题是: 如何在OpenGL中读取3DS模型文件。在这部分介绍了3DS文件的存储格式,给出了OpenGL与3DS的接口编程,这对三维模型的创建提供了极大的方便,还综合运用其他的技术和算法来完成三维动画。6.1 3ds文件格式简介3DS文件由许多块组成,每个块首先描述其信息类别,即该块是如何组成的。块的信息类别用ID来标识,块还包含了下一个块的相对位置信息。因此,即使不理解一个块的含义,也可以很容易地跳过它,因为该块中指出了下一个块的相对于该块起始位置的偏移字节数。与许多文件格式一样,3DS二进制文件中的数据也是按低位在前、高位在后
2、的方式组织的,例如,2个十六进制字节,4A 5C组成的整型数,表明5C是高位字节,4A是低位字节;对于长整型数,如:4A 5C 3B 8F表明 5C4A是低位字,而 8F3B是高位字。下面描述块的具体定义。块的前两项信息分别是:块的ID和块的长度(下一个块相对于该块的字节偏移量),块的ID是一个整型数,而块的长度是一个长整型数。每个块实际上是一个层次结构,不同类型的块,其层次结构也不相同。3DS文件中有一个基本块,其ID是4D4D,每一个3DS文件的开头都是由这样一个块构成。基本块内的块称为主块。为了对块的层次结构有一个初步的认识,下面给出一个图表来说明不同类型(ID)的块及其各自在文件中的位
3、置。如下图所示给每一个块都起了一个名字,这样更便于理解或直接转换为源程序。图6.1 3DS文件结构图颜色块是文件中自始至终都能见到的一种块类型,颜色块总共有3种类型,它们是COL_ RGB,COL_ TRU和COL_ UNK。6.2 存储3ds文件的数据结构本节将对程序中所用到的一些重要数据结构进行简单说明,以便使读者更进一步了解3ds文件所存储的数据。1t3Dmodel:struct t3DModel int numOfObjects; / object的数量(总数) int numOfMaterials; / materials 的数量(总数) vector pMaterials; / 存
4、贮materials 信息的列表 vector pObject; / 存贮object信息的列表;2tMaterialInfo:struct tMaterialInfo char strName255; / 材质的名字 char strFile255; / 材质的文件名(真正存在harddisk的bmp) BYTE color3; / object 的颜色(RGB) (0255) Int texureId; / 材质的ID33DObject:struct t3DObject int numOfVerts; / object 的顶点数 int numOfFaces; / object 的面数 i
5、nt numTexVertex; / 材质坐标的个数 int materialID; / 材质ID ,正是材质数组中的索引 bool bHasTexture; /有材质就为真 char strName255; / object的名字 CVector3 *pVerts; / object 的顶点,将会指向一个数组CVector3 *pNormals; / object 的法线(只是一个近似的法线)将会指向一个数组 CVector3 *pFaceNorm; / 面的法线,将会指向一个数组 CVector3 *pFaceVert1; / 面的顶点x,将会指向一个数组 CVector3 *pFaceV
6、ert2; / 面的顶点y,将会指向一个数组 CVector3 *pFaceVert3; / 面的顶点z,将会指向一个数组 CVector2 *pTexVerts; / 材质的坐标(二维)将会指向一个数组 tFace *pFaces; / 面的结构(在后面有注解)将会指向一个数组;其中:struct tFace int vertIndex3; / 组成面三角形顶点的索引(整型) int coordIndex3; / 组成面三角形材质的索引(整型);6.3 3D动画的实现读取3DS文件的全部操作封装在了CLoad3DS类中,有关CLoad3DS类的具体定义所附光盘中的源程序3ds.cpp and
7、 3ds.h。/ IMPORT 3DS */ This is called by the client to open the .3ds file, read it, then clean up/ *bool CLoad3DS:Import3DS(t3DModel *pModel, char *strFileName) char strMessage255 = 0; / Open the 3DS file m_FilePointer = fopen(strFileName, rb); / Make sure we have a valid file pointer (we found the
8、file) if(!m_FilePointer) sprintf(strMessage, Unable to find the file: %s!, strFileName); MessageBox(NULL, strMessage, Error, MB_OK); return false; / Once we have the file open, we need to read the very first data chunk / to see if its a 3DS file. That way we dont read an invalid file. / If it is a 3
9、DS file, then the first chunk ID will be equal to PRIMARY (some hex num) / Read the first chuck of the file to see if its a 3DS file ReadChunk(m_CurrentChunk); / Make sure this is a 3DS file if (m_CurrentChunk-ID != PRIMARY) sprintf(strMessage, Unable to load PRIMARY chuck from file: %s!, strFileNam
10、e); MessageBox(NULL, strMessage, Error, MB_OK); return false; / Now we actually start reading in the data. ProcessNextChunk() is recursive / Begin loading objects, by calling this recursive function ProcessNextChunk(pModel, m_CurrentChunk); / After we have read the whole 3DS file, we want to calcula
11、te our own vertex normals. ComputeNormals(pModel); / Clean up after everything CleanUp(); return true;See光盘中的源程序StepinGlView.cpp/ StepinGlView.cpp : implementation of the CStepinGlView class/ #include main.h / This includes our header file#include 3ds.h / Include the 3DS header file. #define FILE_NA
12、ME moon.3ds / This is the 3D file we will load.UINT g_TextureMAX_TEXTURES = 0; / This holds the texture info, referenced by an IDCLoad3DS g_Load3ds; / This is 3DS class. This should go in a good model class.t3DModel g_3DModel; / This holds the 3D Model info that we load inint g_ViewMode = GL_TRIANGL
13、ES; / We want the default drawing mode to be normalbool g_bLighting = true; / Turn lighting on initiallyfloat g_RotateX = 0.0f; / This is the current value at which the model is rotatedfloat g_RotationSpeed = 0.8f; / This is the speed that our model rotates. (-speed rotates left) / CStepinGlView mes
14、sage handlersvoid CStepinGlView:Init() PIXELFORMATDESCRIPTOR pfd; int n; HGLRC hrc; m_pDC = new CClientDC(this); ASSERT(m_pDC != NULL); if (!bSetupPixelFormat() return; n =:GetPixelFormat(m_pDC-GetSafeHdc(); :DescribePixelFormat(m_pDC-GetSafeHdc(), n, sizeof(pfd), &pfd); hrc = wglCreateContext(m_pDC
15、-GetSafeHdc(); wglMakeCurrent(m_pDC-GetSafeHdc(), hrc); GetClientRect(&m_oldRect); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST);/ glMatrixMode(GL_MODELVIEW);/ glLoadIdentity(); g_Load3ds.Import3DS(&g_3DModel, FILE_NAME); / Load our .3DS file into our model structure / Depending on how many textures w
16、e found, load each one (Assuming .BMP) / If you want to load other files than bitmaps, you will need to adjust CreateTexture(). / Below, we go through all of the materials and check if they have a texture map to load. / Otherwise, the material just holds the color information and we dont need to loa
17、d a texture. / Go through all the materials for(int i = 0; i 0) / Use the name of the texture file to load the bitmap, with a texture ID (i). / We pass in our global texture array, the name of the texture, and an ID to reference it. CreateTexture(g_Texture, g_3DModel.pMaterialsi.strFile, i); / Set t
18、he texture ID for this material g_3DModel.pMaterialsi.texureId = i; glLightfv(GL_LIGHT0,GL_AMBIENT,m_lightAmb); glLightfv(GL_LIGHT0,GL_DIFFUSE,m_lightDif); glLightfv(GL_LIGHT0,GL_SPECULAR,m_lightSpe); glLightfv(GL_LIGHT0,GL_POSITION,m_lightPos); glEnable(GL_LIGHT0); / Turn on a light with defaults s
19、et glEnable(GL_LIGHTING); / Turn on lighting glEnable(GL_COLOR_MATERIAL); / Allow colorvoid CStepinGlView:DrawScene() glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(m_posx,m_posy,-5.0f); glRotatef(m
20、_fAngleY, 0.0f, 1.0f, 0.0f); glRotatef(m_fAngleZ, 0.0f, 0.0f, 1.0f); for(int i = 0; i g_3DModel.numOfObjects; i+) / Make sure we have valid objects just in case. (size() is in the vector class) if(g_3DModel.pObject.size() bHasTexture) / Turn on texture mapping and turn off color glEnable(GL_TEXTURE_
21、2D); / Reset the color to normal again glColor3ub(255, 255, 255); / Bind the texture map to the object by its materialID glBindTexture(GL_TEXTURE_2D, g_TexturepObject-materialID); else / Turn off texture mapping and turn on color glDisable(GL_TEXTURE_2D); / Reset the color to normal again glColor3ub
22、(255, 255, 255); / This determines if we are in wireframe or normal mode glBegin(g_ViewMode); / Begin drawing with our selected mode (triangles or lines) / Go through all of the faces (polygons) of the object and draw them for(int j = 0; j numOfFaces; j+) / Go through each corner of the triangle and
23、 draw it. for(int whichVertex = 0; whichVertex pFacesj.vertIndexwhichVertex; / Give OpenGL the normal for this vertex. glNormal3f(pObject-pNormals index .x, pObject-pNormals index .y, pObject-pNormals index .z); / If the object has a texture associated with it, give it a texture coordinate. if(pObje
24、ct-bHasTexture) / Make sure there was a UVW map applied to the object or else it wont have tex coords. if(pObject-pTexVerts) glTexCoord2f(pObject-pTexVerts index .x, pObject-pTexVerts index .y); else / Make sure there is a valid material/color assigned to this object. / You should always at least as
25、sign a material color to an object, / but just in case we want to check the size of the material list. / if the size is at least one, and the material ID != -1, / then we have a valid material. if(g_3DModel.pMaterials.size() & pObject-materialID = 0) / Get and set the color that the object is, since
26、 it must not have a texture BYTE *pColor = g_3DModel.pMaterialspObject-materialID.color; / Assign the current color to this model glColor3ub(pColor0, pColor1, pColor2); / Pass in the current vertex of the object (Corner of current face) glVertex3f(pObject-pVerts index .x, pObject-pVerts index .y, pObject-pVerts index .z); glEnd(); / End the drawing glFinish(); SwapBuffers(wglGetCurrentDC();
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1