« 一个读取3DS文件的类CLoad3DS浅析ⅠShadow Volume 阴影锥技术之探Ⅱ »

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

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

本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/3ds-cload3ds-view-2.html

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

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

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

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

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

本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/3ds-cload3ds-view-2.html

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

IE下本页面显示有问题?

→点击地址栏右侧【兼容视图】←

日历

Search

网站分类

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Walle Build 100427

Copyright 2008-2013 ZwqXin. All Rights Reserved. Theme edited from ipati.