3DS文件结构

摘要:
0x3D3D子块:ID描述0100配置部分1100unknown1200背景颜色1201unknown1300 unknown1400 unknown1420unknown1450 unknown1500 unknown2100环境颜色2200雾?材质名称是以0x00结尾的ASCLL字符。通常我们使用由漫反射属性定义的纹理MAIN3DS |+--EDIT3DS | | |+--DIT _ material |+--0xA000材质名称。这是一个以NULL结尾的字符串。它在该文件中是唯一的,可用于标记材质对象+---0xA010Ambiet块+---0xA000漫反射块+---0XA030镜面反射块+---0xA040光泽块+---xA100定义材质的类型+---0xA200纹理块1。漫反射定义的纹理存储在该块+--0xA300和另一个NullTerminatedString中--纹理的文件名。|请注意,此处的文件名不包含路径。即使此块丢失,3DS仍然可以正确加载文件。

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),接下来的一个浮点数表示了摄像机的旋转角(译者:不知道什么用……),最后一个浮点数表示了摄像机的镜头角度(译者:就是视角)。

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

引自网易流光如梦博客。

免责声明:文章转载自《3DS文件结构》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇管理ONS(Oracle Notification Service)python调用windows下的应用程序的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python之tkinter使用-简单对话框

1 # 简单对话框,包括字符、整数和浮点数 2 import tkinter as tk 3 from tkinter import simpledialog 4 5 6 def input_str(): 7 r = simpledialog.askstring('字符录入', '请输入字符', initialvalu...

Java动手实验及课后程序

课后作业 一、编写程序,消息框显示计算结果 设计思想:导入Scanner包,使用JOptionPane类来实现消息框的输入和结果的显示。 程序代码: package com; import java.util.Scanner; //导入Scanner包 import javax.swing.JOptionPane; public class Manner ...

win32下的OpenGL绘图环境框架

Win32下OpenGL入门 主要的步骤包括:添加opengl头文件,库文件,键盘鼠标响应,像素格式设置,opengl环境初始化,绘图变量设置,创建窗口,窗口大小改变时响应,绘制场景,源文件 1,新建一个win32项目(注意,不是console程序),在添加过程中,创建一个空的项目,然后,在解决方案资源管理器的源文件树目录下,添加一个cpp文件,文件可以命...

JavaScript数字精度丢失问题总结

  本文分为三个部分: 1、JS 数字精度丢失的一些典型问题(前端遇小数计算概率大,要有这个精度丢失的意识) 2、JS 数字精度丢失的原因(计算机用二进制存储数据,由于存储位置的限制有时会存在“舍去”。当模仿十进制进行四舍五入时,0舍1入,造成误差) 3、解决方案(一个对象+一个函数)(解决方案:把小数乘以倍数变成整数计算,再除以倍数变成原来的数。其中根据...

JAVA浮点数的范围 和精度

本篇先介绍IEEE754标准中针对浮点数的规范,然后以问答形式补充有关浮点数的知识点。   (一)IEEE754标准 IEEE 754 标准即IEEE浮点数算术标准,由美国电气电子工程师学会(IEEE)计算机学会旗下的微处理器标准委员会发布。   以32位float数据为例,在内存中的存储形式是1bit的符号位(S),8bit表示指数部分(Exp),23表...

Unity3d Shader

Unity3d Shader 预览Surface Shader主要用来实现光照相关处理,可能更简洁。Vertex and Fragment Shader如果不与光照交互, 则可以用这个shader,更录活fixed function shaders固定shader主要用于老旧卡ShaderLab不管写哪种shader,最终通过shaderLab实现,其组织结...