FBX binary file format specification
FBX是一种流行的3D文件格式,最初由Kaydara为MotionBuilder开发,于2006年被Autodesk公司收购。它现在是许多3D工具使用的主要3D交换格式之一。尽管Autodesk为FBX发布了“免费”SDK,但其许可证和软件本身仍然完全关闭。FBX有一个基于文本(ascii)和二进制版本。
由于没有关于二进制FBX格式的公开文档,Blender Foundation要求亚历山大写下他已经弄清楚了什么。我们希望这将导致更好的3D应用程序的互操作性。Blender的下一个版本(2.69)也将支持二进制FBX文件读取。
2013年8月,由Alexander Gessler,Campbell Barton审阅。由Blender Foundation发布,作为公共领域信息。
这是二进制FBX文件格式的不完整规范。
它已经过2011年开始的文件版本测试,但它也适用于早期版本。
本文档仅描述二进制FBX文件的编码,而不是对正在编码的数据的解释。
它应该使您能够将二进制FBX文件转换为ASCII文本格式(或其内存表示形式)。
基于文本的文件结构
对基于文本的格式的了解与本文档相关,因此这里有一个快速的文章。基于文本的FBX文档的核心层次结构块(节点)是
NodeType:SomeProperty0a,SomeProperty0b,...,{
NestedNodeType1:SomeProperty1a,...
NestedNodeType2:SomeProperty2a,...,{
......Sub-scope
}
...
}
换句话说,文档本质上是嵌套的节点列表。每个节点都有…………
- NodeType标识符(class类名)
- 与之关联的属性元组tuple,元组tuple元素是通常的原始数据类型POC:
float,integer,string 等。
- 包含相同格式(递归)节点的列表。
在全局级别,有一个“implicit list隐式列表”(即花括号{},属性列表和名称被省略),并定义了一些标准节点。这些标准项中的每一项仅包含嵌套列表,因此文件可能如下所示
FBXHeaderExtension:{...}
GlobalSettings: {...}
Documents:{...}
Definitions:{...}
Connections:{...}
...
应用程序必须解析这些内容才能访问FBX几何体。
Binary 二进制文件结构
前27个字节包含标题。
- Bytes
0 - 20 :Kaydara FBX Binary \x00 (file - magic,最后有2个空格,然后是一个NULL终止符)。
- Bytes
21 - 22 :[0x1A,0x00] (未知但所有观察到的文件都显示这些字节)。
- Bytes
23 - 26 :unsigned int,版本号。例如,版本7.3为7300。
在头数据之后,接下来是top-level对象记录。vs Text文本文件格式不同,不会省略 - 写入具有空名称和空属性列表的完整节点记录。
在该记录(递归地包含整个文件信息)之后,存在具有未知内容的页脚。
Node记录格式
命名Node记录具有以下内存布局:
大小(字节) |
数据类型 |
名称 |
4 |
UINT32 |
EndOffset |
4 |
UINT32 |
NumProperties |
4 |
UINT32 |
PropertyListLen |
1 |
Uint8 |
NameLen |
NameLen |
char |
Name |
? |
? |
Property [n],n中的n:PropertyListLen |
Optional |
|
|
? |
? |
NestedList |
13 |
UINT8 [] |
NULL记录 |
解释如下…
EndOffset 是从文件开头到节点记录结尾的距离(即接下来的任何内容的第一个字节)。这可以用于轻松跳过未知或不需要的记录。
NumProperties 是与节点关联的值元组tuple中的属性数。作为最后一个元素的嵌套列表不计为属性。
PropertyListLen 是属性列表的长度。这是存储NumProperties 属性所需的大小,这取决于属性的数据类型。
NameLen 是对象名称的长度,以字符为单位。唯一情况是当值为0代表列表顶级top-level。
Name 是对象的名称。没有零终止 \0。
Property [n] 是第n 个属性。有关格式,请参阅 property 记录格式部分。属性按顺序连续写入,没有间隔。
NestedList 是嵌套列表,保留NULL 表示- 最后的记录。
读取包含属性的Node节点记录非常简单。要确定是否存在嵌套列表条目,请检查是否有剩余字节,直到达到EndOffset 。如果是这样,则直接在最后一个属性之后递归读取对象记录。在该对象记录后面,有13个零字节,然后应该与EndOffset匹配。(注意:为什么需要NULL条目并不完全清楚。这强烈暗示了本文档作者所不知道的某些FBX细微或格式特征…………)
Property记录格式
Property 记录具有以下内存布局:
大小(字节) |
数据类型 |
名称 |
1 |
char |
TypeCode |
? |
? |
Data |
其中TypeCode 可以是以下字符代码之一,它们按需要类似处理的组排序。
**i)**原始类型
Y :2字节符号整数
C :1位布尔值(1:真 ,0:假 )编码为1字节值的LSB(最低有效位)。
I :4字节签名整数
F :4字节单精度IEEE 754 number
D :8字节双精度IEEE 754 number
L :8字节符号整数
对于原始标量类型,记录中的数据 正是值的二进制表示,以little-endian(所有数字的低位组放在最前面)字节顺序排列。
**ii)**数组类型
f :4字节单精度IEEE 754数字的数组
d :8字节双精度IEEE 754数字的数组
l :8字节有符号整数的数组
i :4字节有符号整数的数组
b :1字节布尔值的数组(总是0或1)
对于数组类型,Data 更复杂:
大小(字节) |
数据类型 |
名称 |
4 |
UINT32 |
ArrayLength |
4 |
UINT32 |
Encoding |
4 |
UINT32 |
CompressedLength |
? |
? |
Contents |
如果Encoding 为0,则Contents 只是ArrayLength x ArrayType 。如果Encoding 为1,则Contents 是一个长度为CompressedLength 字节的deflate / zip压缩缓冲区。例如,可以使用zlib对缓冲区进行解码。
忽略Encoding 0,1以外的值。
**iii)**特殊类型
这两个都有以下解释:
大小(字节) |
数据类型 |
名称 |
4 |
UINT32 |
Length |
Length |
byte/char |
Data |
该字符串不是以0结尾的,并且可能包含\0 字符(这实际上在某些FBX属性中使用)。 |