您的位置:首页 > 运维架构

OpenGL日记——3ds文件结构

2012-03-02 16:16 204 查看
本文来源于ZwqXin http://www.zwqxin.com/ , 转载请注明

原文地址:http://www.zwqxin.com/archives/opengl/3ds-structure-simple.html

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

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

因此只要知道入口地址(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:

// 基本块(Primary
Chunk),位于文件的开始

#define PRIMARY 0x4D4D

// 主块(Main
Chunks)

#define OBJECTINFO 0x3D3D // 网格对象的版本号

#define VERSION 0x0002 //
.3ds文件的版本

#define EDITKEYFRAME 0xB000 // 所有关键帧信息的头部

// 对象的次级定义(包括对象的材质和对象)

#define MATERIAL 0xAFFF // 保存纹理信息

#define OBJECT 0x4000 // 保存对象的面、顶点等信息

// 材质的次级定义

#define MATNAME 0xA000 // 保存材质名称

#define MATDIFFUSE 0xA020 // 对象/材质的颜色

#define MATMAP 0xA200 // 新材质的头部

#define MATMAPFILE 0xA300 // 保存纹理的文件名

#define OBJECT_MESH 0x4100 // 新的网格对象

// OBJECT_MESH的次级定义

#define OBJECT_VERTICES 0x4110 // 对象顶点

#define OBJECT_FACES 0x4120 // 对象的面

#define OBJECT_MATERIAL 0x4130 // 对象的材质

#define OBJECT_UV 0x4140 // 对象的UV纹理坐标

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

本文来源于ZwqXin http://www.zwqxin.com/ , 转载请注明

原文地址:http://www.zwqxin.com/archives/opengl/3ds-structure-simple.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: