现在是时候向我们就亲爱的立方体说再见的时候了!在本篇教程中,我们将创建一个程序来加载3ds物体,一个在Internet上非常流行的文件格式,并被许多不同的3d建模器所支持。一个3D建模器允许你以一种更加直观和人性化的方式创建任何类型的物体,而不是手工定义顶点的坐标,即使对于比一个立方体稍微复杂一点的简单物体,这将是一个不可能完成的任务。实际上,我不情愿放弃立方体,这样一个简单而又完美的形状。无论如何,除非是被证明不是,宇宙飞船,行星,导弹和任何与空间模拟器有关的东西看起来和立方体完全不同。
在写代码之前,有必要分析一下3ds文件的结构。
好的,放上你写程序时最喜欢喝的饮料并准备开始吧...
l 3DS文件结构
一个3ds文件包含一系列的信息用于描述由一个或多个物体组成的3D场景的所有细节。一个3ds文件包含了一系列的块,称之为chunks。那么在这些块中又包含了什么了?是需要描述场景的所有信息:每个物体的名称,顶点坐标,映射坐标,多边形列表,表面的颜,动画关键帧等等...
这些chunks没有一个线性的结构。这意味着一些chunks依赖于其他的chunks,并只有在它们的父chunks被读入后才能读入。没有必要读入所有的chunks,我们在此只考虑最为重要的。我对3ds文件格式的描述基于包含在中的信息,此由Jochen Wjlhelmy所写,详细地解释了所有chunks的结构。
一个Chunk包含4个字段:
-Identifier:一个两个字节长的16进制的数字以标识chunk。这个信息立即地告诉我们对于我们的意图此chunk是否有用。如果我们需要这个chunk,我们可以提取(extrapolate)包含在这个chunk和可能的子chunk中的信息。如果我们不需要这个chunk,我们使用一下信息来跳过它...
-Length of the chunk:一个4字节数字,表示chunk长度和其所有子chunk长度的总和。
-Chunk data:这个字段有一个变量长度并包含场景的所有数据。
下表显示了在一个典型的chunk中各字段的偏移和长度(以字节为单位)。
Offset | Length | |
0 | 2 | Chunk identifier |
2 | 4 | Chunk length: chunk data + sub-chunks(6+n+m) |
6 | n | Data |
6+n | m | Sub-chunks |
我们可以从表的最后一行清楚地看到一些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
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
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
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
3D EDITOR CHUNK 0x3D3D
OBJECT BLOCK 0x4000
TRIANGULAR MESH 0x4100
VERTICES LIST 0x4110
FACES DESCRIPTION 0x4120
MAPPING COORDINATES LIST 0x4140
下面是chunks的详细描述:
MAIN CHUNK | |
Identifier | 0x4d4d |
Length | 0 + sub-chunks length |
Chunk father | None |
Sub chunks | 3D EDITOR CHUNK |
Data | None |
3D EDITOR CHUNK | |
Identifier | 0x3D3D |
Length | 0 + sub-chunks length |
Chunk father | MAIN CHUNK |
Sub chunks | OBJECT BLOCK, MATERIAL BLOCK, KEYFRAMER CHUNK |
Data | None |
OBJECT BLOCK | |
Identifier | 0x4000 |
Length | Object name length + sub-chunks length |
Chunk father | 3D EDITOR CHUNK |
Sub chunks | TRIANGULAR MESH, LIGHT, CAMERA |
Data | Object name |
TRIANGULAR MESH | |
Identifier | 0x4100 |
Length | 0 + sub-chunks length |
Chunk father | OBJECT BLOCK |
Sub chunks | VERTICES LIST, FACES DESCRIPTION, MAPPING COORDINATES LIST |
Data | None |
VERTICES LIST | |
Identifier | 0x4110 | 电脑软件editor
Length | varying + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | None |
Data | Vertices number (unsigned short) Vertices list: x1,y1,z1,x2,y2,z2 etc. (for each vertex: 3*float) |
FACES DESCRIPTION | |
Identifier | 0x4120 |
Length | varying + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | FACES MATERIAL |
Data | Polygons number (unsigned short) Polygons list: a1,b1,c1,a2,b2,c2 etc. (for each point: 3*unsigned short) Face flag: face options, sides visibility etc. (unsigned short) |
MAPPING COORDINATES LIST | |
Identifier | 0x4140 |
Length | varying + sub-chunks length |
Chunk father | TRIANGULAR MESH |
Sub chunks | SMOOTHING GROUP LIST |
Data | Vertices number (unsigned short) Mapping coordinates list: u1,v1,u2,v2 etc. (for each vertex: 2*float) |
现在3ds文件格式相当清楚了,我们现在看看本篇教程的代码。什么?你已经完全迷惑了?让我们继续吧,随着本篇教程的讲述,对你来说,”chunk”的结构将会变得越来越清晰。毕竟,我们是程序员,我们能更好地理解C,而不是喋喋不休的讲述。
l 简短的摘要
我们加载3ds物体并保存到我们的引擎所定义的格式需要的步骤是:
-实现一个”while”循环(正如我们为纹理加载器所做的),不断地执行直到到达文件的结束。
-每个循环的反复读入chunk id和chunk length。
-使用一个switch分析chunk id的内容。
-如果chunk是我们不需要读入的树的一部分,我们移动文件指针到一个新的位置来跳过那个chunk长度,即通过将当前位置加上当前chunk的长度。这使得我们可以跳过任何我们不需要读入的chunk和子chunk。换句话说:让我们跳到另外一个树枝!你是否有自己是猴子的感觉?:)
-如果chunk允许到达我们需要的其他chunk,或是包含了我们需要的数据,那么我们就根据需要来读取数据,然后我们移动到下一个chunk。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论