首页 > 学院 > 开发设计 > 正文

一个读取3DS文件的类CLoad3DS浅析Ⅱ

2019-11-06 09:03:36
字体:
来源:转载
供稿:网友

文章来源:http://www.zwqxin.com/archives/opengl/3ds-cload3ds-view-2.html

CLoad3DS类是Sourceforge中的一个开源项目,作用在于帮助开发者学会简单的对3DS文件的载入(OpenGL)程序。虽然有更成熟更强大的3dslib库,但是平时写写Demo中,对模型载入的要求一般比较低,这时候只把CLoad3DS类包含到程序就够了。——ZwqXin.com  本文承接上篇文章:一个读取3DS文件的类CLoad3DS浅析Ⅰ 。

本文来源于 ZwqXin (http://www.zwqxin.com/),

上文提到,PRocessNextChunk(&Model3DS, m_CurrentChunk)这个函数做了模型载入部分最重要的东西。

// 下面的函数读出3ds文件的主要部分//注意传入的后一个参数是刚被ReadChunk过的m_CurrentChunk,也就是说它从0x4D4D块(树干)后开始继续处理,并把0x4D4D块作为pPreviousChunk(前一个块)//处理树结构的常用手法就是递归void CLoad3DS::ProcessNextChunk(t3DModel *pModel, tChunk *pPreviousChunk){  ..........  m_CurrentChunk = new tChunk;        // 为新的块分配空间     //因为父块的length是子块length总和,而又由0x4D4D块开始,故这个while会遍历整个3DS文件数据 //然后我们在“case OBJECTINFO”中找到了递归,因为OBJECTINFO(0x3D3D,3D editor chunk)就是父块0x4D4D的最直接子块,这次递归中的ProcessNextChunk函数中,while中的pPreviousChunk是递归前(上一层)的m_CurrentChunk,因此switch中寻觅的将是上一层所进入的这个OBJECTINFO块下的子块(找到MATERIAL或OBJECT来处理直至该OBJECTINFO的递归完结,回来继续0x4D4D下的寻觅)。 //总觉得说着说着自己也蒙蒙的(这就是递归!),事实上EDITKEYFRAME跟OBJECTINFO是同级的,不过我们本来就没用到EDITKEYFRAME这种块,故遇到它只是略过(单纯用它所“拥有”的length来增加0x4D4D的bytesRead)//总之呢,你打开某杀毒软件从“我的电脑”开始杀一次毒,观察一下查杀顺序能加深理解恩   while (pPreviousChunk->bytesRead < pPreviousChunk->length)  {        ReadChunk(m_CurrentChunk);// 读入下一个块     switch (m_CurrentChunk->ID)    {    case VERSION:       ...     // 文件版本号      break;    case OBJECTINFO:     .... // 网格对象信息(3D editor chunk)     ProcessNextChunk(pModel, m_CurrentChunk);//!!!      break;    case MATERIAL:      ....        // 材质信息       break;    case OBJECT:        ....      // 对象的名称       break;    case EDITKEYFRAME: .....      break;    default:          // 跳过所有忽略的块的内容的读入,增加需要读入的字节数      m_CurrentChunk->bytesRead += fread(buffer, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_FilePointer);      break;    }    // 增加从最后块读入的字节数    pPreviousChunk->bytesRead += m_CurrentChunk->bytesRead;  }   // 释放当前块的内存空间  delete m_CurrentChunk;  m_CurrentChunk = pPreviousChunk;}

case语句中的处理函数随chunk的ID(种类)不同而不同,但这些处理函数多少也是递归函数。分配存储空间后,从文件读入后存入相应的数据结构中,并增加该chunk的bytesRead。最需要注意的是,一般由3DS MAX导出的3ds文件的模型坐标跟OPENGL中不同,在读入顶点时要处理(swap)一下。

// 读下一个块 void ProcessNextChunk(t3DModel *pModel, tChunk *); // 读下一个对象块 void ProcessNextObjectChunk(t3DModel *pModel, t3DObject *pObject, tChunk *); // 读下一个材质块 void ProcessNextMaterialChunk(t3DModel *pModel, tChunk *); // 读对象颜色的RGB值 void ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk); // 读对象的顶点 void ReadVertices(t3DObject *pObject, tChunk *); // 读对象的面信息 void ReadVertexIndices(t3DObject *pObject, tChunk *); // 读对象的纹理坐标 void ReadUVCoordinates(t3DObject *pObject, tChunk *); // 读赋予对象的材质名称 void ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk); 
另外还有读入字符串,各种向量等通用计算函数等等,就不介绍了。在ImportModel的第4步中,要计算顶点法向量(把以该点为顶点的各个面的法向量取均值),貌似3DS文件中没有保存法向量信息的chunk吧。因此这里导入的模型要重新(粗略地)计算面和顶点法向量。

最后是DrawModel绘制模型(集齐了顶点,纹理或材质[难道有了纹理就不能用材质吗,汗一个],顶点法向量,用三角面片方式按索引绘制),并在RenderModel中调用并作移转缩等处理。总结一下:CLoad3DS类最核心的就是递归思想,以及它与3DS文件树型结构的对应。   CLoad3DS类下载:点此。

本文来源于 ZwqXin (http://www.zwqxin.com/),


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表