http://hi.baidu.com/yiyibeibei/item/928b2660bea9652669105b82
0x4D4D是文件头,他的大小就是整个文件的大小。
另外还有两个主要块,他们是3D编辑块和关键帧块:
0x3D3D:3D编辑块,描述了3D对象的数据。3D对象就在这个地方。
0xB000:关键帧块,描述了关键帧数据。
在某个主要块之后有一些数据块。这些应该是其他一些允许在主要块之内的数据(请参见图表)。
0x3D3D的子块:
ID 描述
0100 配置部分
1100 unknown
1200 背景色
1201 unknown
1300 unknown
1400 unknown
1420 unknown
1450 unknown
1500 unknown
2100 环境色
2200 雾?
2201 雾 ?
2210 雾 ?
2300 unknown
3000 unknown
3D3E 配置编辑块
4000 对象数据块
AFFF 材质列表
3D3E配置编辑块:
ID 描述
7001 视口指示器
7011 视口定义( 类型 2 )
7012 视口定义( 类型 1 )
7020 视口定义( 类型 3 )
3D3E块中有很多变态的数据,其中只有7020块比较重要,这个块定义了4个活动的视口。假设在编辑程序中使用了4个视口,编辑程序配置中包含5个7020块和 5个7011块。但是事实上只有开始的4个7020块对用户的视口外观有影响,其他的里面只包含一些附加信息。该块的第6,7字节表明了视图的类型,合法的ID以及其对应的视图如下所示:
ID 描述
0001 顶
0002 底
0003 左
0004 右
0005 前
0006 后
0007 用户
FFFF 摄象机
0009 光源
0010 无效
AFFF材质块
定义了材质。其子块A000定义了材质名称。材质名称是ASCLL字符,以0x00为结束符。
通常我们使用的都是Diffuse属性定义的纹理
MAIN3DS (0x4D4D)
|
+--EDIT3DS (0x3D3D)
| |
| +--EDIT_MATERIAL (0xAFFF)
| +--0xA000 材质的名称,这是一个以NULL结尾的字符串,在该文件中是唯一
| 的,可以用它标志材质对象。
+--0xA010 Ambiet块
+--0xA020 Diffuse块
+--0xA030 Specular块
+--0xA040 Shininess块
+--0xA100 定义了该材质的类型(比如Phong、Flat等等)
+--0xA200 纹理块1,Diffuse定义的纹理就存储在这个块中
+-- 0xA300 (String)又一个Null Terminated String——该纹理的文件名,
| 注意,这里的文件名不包含路径。
+-- 0xA351 (WORD)纹理选项块,按Mli文档的说法1-9位有意义,分
| 别表示几个纹理的属性(比如是否tiling,是否Mirror等等)
| 这部分只要建模的时候稍微注意一下,就可以忽略这个块。
| 比如Mirror就可以用把两个Tiling换成负数的方法解决。
+-- 0xA353 (float)不太清楚这个分量的含义。
+-- 0xA354 (float)U方向的Tiling值
+-- 0xA356 (float)V方向的Tiling值
+-- 0xA358 (float)U方向的Offset值
+-- 0xA35A (float)V方向的Offset值,注意,这里读到的Voffset的值跟3ds
| 里面看到的值相差一个符号。
+-- 0xA35C (float 4Bytes)W方向的rotate值,同样的也相差一个符号。
4000是一个对象描述块。
该块的开始是一个由0结尾的字符串,描述了该对象的名称。要记住,对象不仅仅是一个物体,也可能是一个光源或者是一个摄象机:
ID 描述
4010 unknown
4012 阴影?
4100 三角形列表
4600 光源
4700 摄象机
4100三角形列表的子块:网格模型信息
MAIN3DS (0x4D4D)
|
+-EDIT3DS (0x3D3D)
| |
| +--EDIT_OBJECT (0x4000)
| | |
| | +--OBJ_TRIMESH (0x4100)
| | | | (字节数) 2 3 3 3 3 3 3
| | | +--TRI_VERTEXL (0x4110) 顶点列表[num,x,y,z,x,y,z.......]
| | | +--TRI_VERTEXOPTIONS (0x4111) 顶点选项
| | | |
| | | +--TRI_MAPPINGCOORS (0x4140) 纹理坐标[num,U,V,U,V...........]
| | | +--TRI_MAPPINGSTANDARD (0x4170) 标准映射
| | | +--TRI_FACEL1 (0x4120) 面列表
| | | +--TRI_SMOOTH (0x4150) 面平滑组
| | | +--TRI_MATERIAL (0x4130) 面材质
| | | +--TRI_TRMATRIX (0x4160) 平移矩阵
| | | +--TRI_VISIBLE (0x4165) 物体可见性
其中4110顶点列表块的数据:
数据类型 大小 名称
Ushort 2字节 顶点数目
float 4字节 X坐标
float 4字节 Y坐标
float 4字节 Z坐标
其中X,Y,Z一直重复顶点数目次,这样就得到了所有的顶点。
4111顶点选项块:
该块由一些整数组成,第一个整数表明了顶点的个数,然后对每个顶点用一个整数表示一些位信息。其中0~7,11~12位影响物体的可见性,8~10位是随机信息,13~15位表明该顶点是否在某个选择集中被选中。该块不很重要。即使丢失此块,3DS仍旧能够将文件正确的载入。
4120面列表块:
数据类型 大小 名称
Unsigned short 2字节 面数量
Unsigned short 2字节 顶点A的索引
Unsigned short 2字节 顶点B的索引
Unsigned short 2字节 顶点C的索引
Unsigned short 2字节 面信息
其中顶点A,B,C和面信息重复面数量次就得到了所有的面。面信息的各位意义如下:
位数 意义
1 AC边的顺序。若是A->C的话为1。
2 BC边的顺序。若是B->C的话为1。
3 AB边的顺序。若是A->B的话为1。
4 映射
5 未使用
6 同上
7 同上
8 同上
9 同上
10 混乱
11 混乱
12 0
13 0
14 是否在选择集3被选中
15 是否在选择集2被选中
16 是否在选择集1被选中
4130面材质块:
每一个面材质块均以一个Null Terminated String开始,接着由一个数字表示使用该材质的面的数量(2个字节)。接下来存放的是这些面的索引,每个索引2个字节
4140纹理映射块:
开始的两个字节表示了顶点的数量,然后为每个顶点定义2个浮点数的纹理坐标。也就是说,如果一个顶点的纹理映射在纹理的中心,那么其坐标就是(0.5,0.5)。
4150面平滑组块(译者:至今本人不知道这个块的用处……):
面的数量乘上4个字节,即每个数据是一个4字节的整数,第N个数字表示该面是否属于第N个平滑组。
4160平移矩阵块:
开始的3个浮点数定义了物体局部坐标在绝对坐标中的位置,最后3个浮点数定义了物体的局部中心。
4170标准映射块(译者:至今本人不知道这个块的用处……):
开始的2个字节表示了映射类型:0表示平面映射或者是指定映射;1:圆柱映射;2:球映射。接着用21个浮点数描述该映射。
4600光源块:
开始用3个浮点数(共12字节)描述了该光源的X,Y,Z坐标位置,接下来是如下数据块:
ID 描述
0010 RGB色
0011 24位色块
4610 该光源是个聚光灯
4620 布尔值,表示该光源的有效性
其中,4610块的数据:
开始的3个浮点数表示了聚光灯指向的方向(X,Y,Z)。接下来的一个浮点数表示了热点。最后一个浮点数表示了发散(译者:好像就是聚光的角度)。
0010 RGB色块:
用3个浮点数表示了物体的R,G,B色。
0011 24位色块:
用3个字节描述了物体的R,G,B色(译者:即每分色一字节)。
4700摄像机块:
开始的3个浮点数表示了摄像机的位置(X,Y,Z),中间的3个浮点数表示了摄像机指向的位置(X,Y,Z),接下来的一个浮点数表示了摄像机的旋转角(译者:不知道什么用……),最后一个浮点数表示了摄像机的镜头角度(译者:就是视角)。
l 3DS文件结构
一个3ds文件包含一系列的信息用于描述由一个或多个物体组成的3D场景的所有细节。一个3ds文件包含了一系列的块,称之为chunks。那么在这些块中又包含了什么了?是需要描述场景的所有信息:每个物体的名称,顶点坐标,映射坐标,多边形列表,表面的颜色,动画关键帧等等...
这些chunks没有一个线性的结构。这意味着一些chunks依赖于其他的chunks,并只有在它们的父chunks被读入后才能读入。没有必要读入所有的chunks,我们在此只考虑最为重要的。我对3ds文件格式的描述基于包含在3dsinfo.txt中的信息,此由Jochen Wjlhelmy所写,详细地解释了所有chunks的结构。
一个Chunk包含4个字段:
-Identifier:一个两个字节长的16进制的数字以标识chunk。这个信息立即地告诉我们对于我们的意图此chunk是否有用。如果我们需要这个chunk,我们可以提取(extrapolate)包含在这个chunk和可能的子chunk中的信息。如果我们不需要这个chunk,我们使用一下信息来跳过它...
-Length of the chunk:一个4字节数字,表示chunk长度和其所有子chunk长度的总和。
-Chunk data:这个字段有一个变量长度并包含场景的所有数据。
下表显示了在一个典型的chunk中各字段的偏移和长度(以字节为单位)。
我们可以从表的最后一行清楚地看到一些chunks是如何依赖于其他chunks的:每个子chunk实际上是包含在父chunk的”Sub-chunks”字段。
以下是在一个3ds文件中最为重要的chunks。请注意不同元素间的层次关系:
MAIN CHUNK 0x4D4D
3D EDITOR CHUNK 0x3D3D
OBJECT BLOCK 0x4000
TRIANGULAR MESH 0x4100
VERTICES LIST 0x4110
FACES DESCRIPTION 0x4120
FACES MATERIAL 0x4130
MAPPING COORDINATES LIST 0x4140
SMOOTHING GROUP LIST 0x4150
LOCAL COORDINATES SYSTEM 0x4160
LIGHT 0x4600
SPOTLIGHT 0x4610
CAMERA 0x4700
MATERIAL BLOCK 0xAFFF
MATERIAL NAME 0xA000
AMBIENT COLOR 0xA010
DIFFUSE COLOR 0xA020
SPECULAR COLOR 0xA030
TEXTURE MAP 1 0xA200
BUMP MAP 0xA230
REFLECTION MAP 0xA220
[SUB CHUNKS FOR EACH MAP]
MAPPING FILENAME 0xA300
MAPPING PARAMETERS 0xA351
KEYFRAMER CHUNK 0xB000
MESH INFORMATION BLOCK 0xB002
SPOT LIGHT INFORMATION BLOCK 0xB007
FRAMES (START AND END) 0xB008
OBJECT NAME 0xB010
OBJECT PIVOT POINT 0xB013
POSITION TRACK 0xB020
ROTATION TRACK 0xB021
SCALE TRACK 0xB022
HIERARCHY POSITION 0xB030
如前所述,如果我们想读取一个特殊的chunk,我们必须要先读取它的父chunk。想象一下3ds文件是一棵树,我们要读取的chunk是一片叶子(并且我们是地面上的一个小蚂蚁)。为了达到叶子,我们需要从树干开始,并穿过通向叶子的所有树枝。例如,如果我们想到达chunk VERTICES LIST,我们必须先读取MAIN CHUNK,然后是3D EDITOR CHUNK,OBJECT BLOCK,最后是chunk TRIANGULAR MESH。其他的chunks可以安全地跳过。
现在让我们剪除树,只剩下将在本教程中使用的树枝:”vertices”, “faces”, “mapping coordinates” 和它们的父chunks。
MAIN CHUNK 0x4D4D
3D EDITOR CHUNK 0x3D3D
OBJECT BLOCK 0x4000
TRIANGULAR MESH 0x4100
VERTICES LIST 0x4110
FACES DESCRIPTION 0x4120
MAPPING COORDINATES LIST 0x4140
引自网易流光如梦博客。