« 忆我的第一次OpenGL一个读取3DS文件的类CLoad3DS浅析Ⅰ »

3DS文件结构的初步认识

 3DS文件的结构比想象中复杂,也可以说我之前想得太简单了.它跟可以直接查看的obj文件的复杂度完全不同。保存的信息很多很多(若这些信息在模型中存在)。虽然是一种老字号的通用格式,但是文件结构从来没被发布过,只是网路上很多高手不吝麻烦,一一尝试测试,找出其纷乱二进制下的含义,并公开让建模者和程序员得以应用3DS模型文件。这里主要记录一下我的认识(比较肤浅呵呵)。——ZwqXin.com

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

其实按我最近的理解,3DS文件格式,对数据的组织跟内存很相像。它分成很多的“chunk”(块),按顺序排列。每个chunk都包含着一些信息,比如顶点啊材质啊灯光啊等等,相应地,就被称为顶点chunk材质chunk灯光chunk等等,每个chunk都有其功用。每个chunk有其ID也有其长度和数据。如果把ID所在位置作为一个chunk的地址的话,把该“chunk地址+chunk长度”就可以找到下一个chunk的地址(ID所在位置)了。具体描述如下:

Offset  Length Name
0 2 Chunk-ID
2 4 Chunk-length = 6+n+m
n Data
6+n m Sub-chunks

因此只要知道入口地址(ID为0x4D4D,称为基本块,标识3DS文件)和所需要的chunk对于它的偏移量就能找到你想要的数据了。Chunk-length就是一个chunk的容量。Data是主数据,Sub-chunks是子块。当然,与内存的最大区别是3DS文件不依赖于硬件。内存的话总容量是固定的,地址为0长度为8的内存分配来存储某数据,如果该数据仅仅占用了开头的4个内存格子,其余4个格子什么也没有(或者说无意义)等于浪费了,但它们还是“被使用”了,没法用来干别的事。而3DS文件,哪怕一个chunk的长度多么长而被填充的数据多么少,或者根本没有相应数据,多余的那些“虚拟的数据地址”不会占用整个文件的大小。这是符合实际的:一个模型的数据量可大可小,因此对应3DS文件也跟着可大可小。至于数据量超过了长度所允许怎么办呢?据说某些chunk,如描述顶点数的chunk的“长度”也是varying,也就是说长度也跟随数据量变化,望有心人指教。另一个区别在于ID非一定按顺序的,譬如基本块ID为0x4D4D,设其地址为0,有一个chunk的ID是0x0001,明显小于0x4D4D,但其地址可能很大。所以说ID是名字,ID所在3DS文件结构种的“位置”才是地址。

顺带一提的是,3DS文件中块的内部组织更像是一种树结构(The chunk tree),因此就有了父块和子块这种概念,父块包含子块。其中ID号0x4D4D的块就是树干,其长度是“0 + sub-chunks”,而ID为0x3D3D的3D editor chunk(描述对象信息)和EDITKEYFRAME(关键帧信息)等等就是树干上的大树枝,Object block (描述对象的点与面总的信息)等等就是大树枝上的小树枝,然后还有小小树枝,小小小树枝……较小的树枝都是比它大一点的树枝的“子块sub-chunk”,且较大树枝的“长度length ”上标示的是其属下所有小树枝的“长度”总和(想起你电脑上的文件夹了吗呵呵)。资料上的树关系(其中一部分如下,左边空格的多少突显出父子关系):
0x4D4D            Main chunk
  0x3D3D          3D editor chunk
    0x4000        Object block (with name of your object)
     0x4100       Triangular mesh
       0x4110     Your vertices
       0x4120     Your faces

在实际应用中,因为某种chunk的长度固定,故偏移确定,也就能直接计算得某个块的ID所在位置了。众多高手们已经帮我们算好了(虽然还没有全部解析),给出一个chunk的ID和它存储的数据的作用和格式,也就是说我们应用的可以通过其ID访问该chunk,按照数据存储格式把数据读出来,为我们所用。例如ID号为0x4110的chunk就是用来描述对象顶点的,按照其存储数据的方式可以遍历之,保存到一种容器(实际内存)中,使用的时候就能直接从此容器中把模型顶点拿出来了。

譬如我用到的一个3DS文件读取类就用到了以下ID的chunk:

  1. // 基本块(Primary Chunk),位于文件的开始
  2. #define PRIMARY            0x4D4D
  3.  
  4. // 主块(Main Chunks)
  5. #define OBJECTINFO         0x3D3D        // 网格对象的版本号
  6. #define VERSION            0x0002        // .3ds文件的版本
  7. #define EDITKEYFRAME       0xB000        // 所有关键帧信息的头部
  8.  
  9. // 对象的次级定义(包括对象的材质和对象)
  10. #define MATERIAL           0xAFFF        // 保存纹理信息
  11. #define OBJECT             0x4000        // 保存对象的面、顶点等信息
  12.  
  13. // 材质的次级定义
  14. #define MATNAME            0xA000        // 保存材质名称
  15. #define MATDIFFUSE         0xA020        // 对象/材质的颜色
  16. #define MATMAP             0xA200        // 新材质的头部
  17. #define MATMAPFILE         0xA300        // 保存纹理的文件名
  18.  
  19. #define OBJECT_MESH        0x4100        // 新的网格对象
  20.  
  21. // OBJECT_MESH的次级定义
  22. #define OBJECT_VERTICES    0x4110      // 对象顶点
  23. #define OBJECT_FACES       0x4120      // 对象的面
  24. #define OBJECT_MATERIAL    0x4130      // 对象的材质
  25. #define OBJECT_UV          0x4140      // 对象的UV纹理坐标

明显这个类只用到了3DS文件中的一小部分(chunk):顶点信息,面信息,纹理信息,材质信息,和一些标志信息。事实上一个复杂模型对应的3DS文件中有更多的chunks。可以参看以下文档: 

3dsinfo.zip 

本文档在wotsit.org 获得,同时也为本日志参考资料。

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

  • 相关文章:
  • quote 2.xieming
  • 现在的.max文件格式好像变了啊。我去网上下了几个这样的文件二进制打开来看根本找不到0x4d4d这样的数据了
    zwqxin 于 2012-1-11 22:51:52 回复
    你确定不是*.3ds吗......
  • 2012-1-11 9:58:10 回复该留言
  • quote 3.xieming
  • 最开始的两个字节的数据都变成了d0 cf
    jiangcaiyang 于 2013-1-27 20:56:22 回复
    不过除了3DS Max以外的软件导出的3DS格式还是以4d4d为头的。
  • 2012-1-11 10:01:25 回复该留言

发表评论:

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

IE下本页面显示有问题?

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

日历

Search

网站分类

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Walle Build 100427

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