The most interesting part of this file is, evidently, the Scene. Opening it up in the chunk parser, it begins like follows, and goes on for a few ten thousands of lines:

0 0x2012: (StorageContainer) [452] {
0 0x0000: (StorageContainer) [6] {
0 0x000b: (StorageRaw) {
Size: 24
String: <).Z..B0`......!........
Hex: 3c 29 06 5a 1e 0c 42 30 60 11 00 00 00 00 00 21 e0 2e 04 00 01 00 00 00 }
1 0x000e: (StorageRaw) {
Size: 19
String: ..............@....
Hex: 00 00 04 00 00 00 00 00 82 00 00 00 00 00 40 00 00 00 00 }
2 0x000e: (StorageRaw) {
Size: 19
String: ..............@....
Hex: 01 00 01 00 00 00 00 00 82 00 00 00 00 00 40 00 00 00 00 }

Inside the Scene stream, we can find a single chunk container. In this case the id of this chunk is 0x2012, and is apparently related to which version, 2010, the file was saved with. This container contains a large number of objects, 452 in this case, with ids that are all very low in value. So, we go look for something we recognize.

While scrolling through the file, I found a short string that I recognized, "no fx", which is part of the NeL node properties plugin. It appears in the file under the following section:

        389 0x001a: (StorageContainer) [25] {
0 0x2150: (StorageContainer) [84] {
0 0x0100: (StorageRaw) {
Size: 4
String: S...
Hex: 53 00 00 00
Int: 83
Float: 1.16308e-43 }
...
18 0x0110: (StorageContainer) [2] {
0 0x0120: (StorageRaw) {
Size: 20
String: XH...u.. ....'......
Hex: 58 48 d6 04 1d 75 d1 16 20 10 00 00 2e 27 0c 05 09 00 00 00 }
1 0x0130: (StorageRaw) {
Size: 9
String: no sound. } }
19 0x0110: (StorageContainer) [2] {
0 0x0120: (StorageRaw) {
Size: 20
String: XH...u.. .../'......
Hex: 58 48 d6 04 1d 75 d1 16 20 10 00 00 2f 27 0c 05 06 00 00 00 }
1 0x0130: (StorageRaw) {
Size: 6
String: no fx. } }
20 0x0110: (StorageContainer) [2] {
0 0x0120: (StorageRaw) {
Size: 20
String: XH...u.. ...........
Hex: 58 48 d6 04 1d 75 d1 16 20 10 00 00 b2 07 00 00 01 00 00 00 }
1 0x0130: (StorageRaw) {
Size: 1
String: .
Hex: 00 } }
...

The 0x2150 chunk seems to exclusively contain 0x0110 entries, preceeded one 0x0100 header entry stating the number of 0x0110 entries. Every entry has a 0x0130 binary blob which is the value of some property, and a 0x0120 binary blob which would likely be some sort of identifier header of this value. Now we should find out how our own nel plugin code puts this value in there, to see if we can make sense of this header.

CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_ENV_FX, "no fx");

This is the line of code that reads the environment fx property from a node. The value of NEL3D_APPDATA_ENV_FX is defined as:

#define NEL3D_APPDATA_ENV_FX (84682543)

Which should appear as 2f 27 0c 05 in the hex output. And it can indeed be found at byte index 12, followed by another integer 6 which happens to match with the length of the value in the value chunk. There's that redundancy showing up again. Looking deeper into the function to figure out the rest of the bytes, we can find this in the getScriptAppData function

AppDataChunk *ap=node->GetAppDataChunk (MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id);

Where the class id MAXSCRIPT_UTILITY_CLASS_ID matches with the first 8 bytes of the header, and the super class id UTILITY_CLASS_ID matches with the following 4 bytes. In short:

58 48 d6 04 1d 75 d1 16 // MAXSCRIPT_UTILITY_CLASS_ID
20 10 00 00 // UTILITY_CLASS_ID
2f 27 0c 05 // NEL3D_APPDATA_ENV_FX
06 00 00 00 // SIZE

We can now be quite sure that the 0x2150 block contains all of the AppData entries. According to the public SDK documentation, the AppData functionality is part of the Animatable base class. Which means that the chunk which contains this block is either an instance of this Animatable class, or more likely a subclass of it. It is of course very likely that the class is somehow identified by the chunk id, which in this case is 0x001a, or 26 in decimal.

Now, the reason why you shouldn't have skipped part 1 and part 2 of this series, is because the data in the DllDirectory and ClassDirectory3 streams is needed to make sense of the Scene stream. Similar to how the ClassDirectory3 references a dll in the DllDirectory by index, the Scene is here referencing a class by index in the ClassDirectory3. This allows to get hold of the ClassId, needed to instantiate the class from the associated class description instance, or to provide a fallback mechanism when the class is part of a missing plugin, and be able to provide the user with the name and description of what is missing from his installation.

At index 26 of the ClassDirectory3 in this file, I can find the following entry:

Entries[26]: (ClassEntry) [2] PARSED {
Header: (ClassEntryHeader) {
DllIndex: -1
ClassId: (0x00000001, 0x00000000)
SuperClassId: 1 }
Name: Node}

Which is the builtin class Node, which probably implements the INode interface that ends up deriving from the Animatable base class.

To confirm this theory, I go the other way, and look for a class I know about.

Entries[13]: (ClassEntry) [2] PARSED {
Header: (ClassEntryHeader) {
DllIndex: -2
ClassId: (0x64c75fec, 0x222b9eb9)
SuperClassId: 3072 }
Name: NeL Material}

At index 13 I find the NeL material script class, which would then be found as a chunk in the file with id 0x000d. And there exists one.

        134 0x000d: (StorageContainer) [8] {
0 0x2034: (StorageRaw) {
Size: 40
String: |.......~...............................
Hex: 7c 00 00 00 7d 00 00 00 7e 00 00 00 7f 00 00 00 80 00 00 00 81 00 00 00 82 00 00 00 83 00 00 00 84 00 00 00 85 00 00 00 }
1 0x204b: (StorageRaw) {
Size: 1
String: .
Hex: 2e }
2 0x21b0: (StorageContainer) [1] {
0 0x1020: (StorageRaw) {
Size: 4
String: ^...
Hex: 5e 00 00 00
Int: 94
Float: 1.31722e-43 } }
3 0x0010: (StorageRaw) {
Size: 8
String: ........
Hex: 0e 00 00 00 09 00 00 00 }
4 0x4001: (StorageRaw) {
Size: 50
String: M.T.R.L._.G.E._.A.c.c._.M.i.k.o.t.o.B.a.n.i.e.r.e. }
5 0x4003: (StorageRaw) {
Size: 4
String: ....
Hex: 0a 02 00 00
Int: 522
Float: 7.31478e-43 }
6 0x4020: (StorageRaw) {
Size: 4
String: ....
Hex: 00 00 00 00
Int: 0
Float: 0 }
7 0x4030: (StorageRaw) {
Size: 16
String: ...............?
Hex: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3f } }

Which, as entry 0x4001 helpfully lets us know by the UTF-16 name MTRL_GE_Acc_MikotoBaniere, is indeed a NeL Material.

So, using this knowledge, we can parse the scene container in a smarter way. Here I provide for you the output at this point.

http://dl.kaetemi.be/blog/maxfile_dump_4.txt

Now that we have figured out which chunks are contained in the Scene streams, and we know how and where some of the data inside it is formatted, how does it all link together? That will be the next subject.

【转】http://blog.kaetemi.be/post/2012/08/20/3ds-Max-File-Format-%28Part-4%29

3ds Max File Format (Part 4: The first useful data; Scene, AppData, Animatable)的更多相关文章

  1. 3ds Max File Format (Part 1: The outer file format; OLE2)

    The 3ds Max file format, not too much documentation to be found about it. There are some hints here ...

  2. 3ds Max File Format (Part 5: How it all links together; ReferenceMaker, INode)

    At this point, you should start to familiarize yourself a bit with the publicly available 3ds Max AP ...

  3. 3ds Max File Format (Part 3: The department of redundancy department; Config)

    Now we'll have a look at the Config stream. It begins like follows, and goes on forever with various ...

  4. 3ds Max File Format (Part 2: The first inner structures; DllDirectory, ClassDirectory3)

    Now that we understand the outer structure of the file, it's time to look closer to what's inside. T ...

  5. 3ds Max File Format (Part 6: We get signal)

    Let's see what we can do now. INode *node = scene.container()->scene()->rootNode()->find(uc ...

  6. AVEVA PDMS to 3ds Max - RvmTranslator6.0beta

    AVEVA PDMS to 3ds Max - RvmTranslator6.0beta eryar@163.com RvmTranslato6.0 translate PDMS RVM to 3ds ...

  7. VRay 2.0 SP1 2.10.01 for 3ds max 9/2008/2009/2010/2011/2012 32/64位 顶渲简体中文版+英文版[中国室内设计论坛-室内人]

    VRay 2.0 SP1 2.10.01 for 3ds max 9/2008/2009/2010/2011/2012 32/64位 顶渲简体中文版+英文版[中国室内设计论坛-室内人] 对最新版本的V ...

  8. 万圣节福利:红孩儿3D引擎开发课程《3ds max导出插件初步》

    ds max文件夹,插件文件夹以及3ds max的可执行程序文件夹: 位的,这里要改成x64,否则启动程序后3ds max会提示"不是有效的win32程序"之类的对话框. 然后要将 ...

  9. 【Unity】3.3 用3ds Max 2015制作模型并将其导入到Unity

    分类:Unity.C#.VS2015 创建日期:2016-04-05 一.常用三维软件简介 由于游戏引擎本身的建模功能相对较弱,无论是专业性还是自由度都无法同专业的三维软件相比,所以大多数游戏中的模型 ...

随机推荐

  1. cf936B

    题意简述:给出一个有向图,问从s出发是否能找到一条长度为奇数的路径并且路径的端点出度为0,存在就输出路径,如果不存在判断图中是否存在环,存在输出Draw,否则输出lose 题解:类似于DP,将每一个点 ...

  2. Excel_单元格格式_查找替换、定位

    不重复! 显示格式:Ctrl+1 1,合并后居中,填充颜色,设置单元格边框,划斜线,格式刷(单击,双击) 2,单元格数字格式,格式不会改变值!自定义(编码规则) 4个 a :只显示星期:周+aaa:周 ...

  3. Vue中echarts的使用

    1.安装 npm install echarts --save 2. 导入并挂载 <template>   <!-- 1. 为ECharts准备一个具备大小(宽高)的Dom --&g ...

  4. PHP0010:PHP操作mysql

    cmd中清除之前的记录 cmd操作数据库的步骤: php 到 mysql的并发数 15个左右 for循环是要知道起点和终点 foreach是从结果集中取数据 而while可遍历自然结果集

  5. Codeforces Round #622(Div 2) C1. Skyscrapers (easy version)

    题目链接: C1. Skyscrapers (easy version) 题目描述: 有一行数,使得整个序列满足 先递增在递减(或者只递增,或者只递减) ,每个位置上的数可以改变,但是最大不能超过原来 ...

  6. mysql修改密码、创建用户、开放远程

    创建密码: MariaDB [(none)]> use mysql; MariaDB [mysql]> UPDATE user SET password=password('newpass ...

  7. css中content-box和border-box当宽度为百分比时的位置区别,vw和%区别

    盒模型 参考代码 // CSS 部分 <style> .box1,.box2{ width: 200px; height: 200px; padding: 20px; margin: 20 ...

  8. 回味Ubuntu10.10致敬Gnome桌面

    目录 Ubuntu10.10可用源 Ubuntu10.10更新语言包 输入法支持 浏览器选择 文件下载 压缩文件中文乱码的处理 视频播放 科学计算 搭建Lamp环境 实现文件分享 主题美化 Ubunt ...

  9. 用友UAP NC 单据新增时业务单元不能带出问题处理

    用户需求新建一个主子表单据,由于刚从63环境升级到65环境,所以对于 65环境走单据流程生成节 点出的错误不了解. 直接建了集团级的主子表单据后,实施说需要的是业务单元级的主子表单据,跟用友开发沟通后 ...

  10. PHP自定义函数+系统函数库

    全局变量 $n = 5; //全局变量 function fun1(){ global $n; $n++; } fun1(); echo '<hr>'; $n = 6; function ...