At this point, you should start to familiarize yourself a bit with the publicly available 3ds Max API documentation. The contents of the file map practically 1:1 with how the system is built up internally. Most important is the inheritance of the classes, as we need to be aware of all the parent classes, and preferably structure our parser classes in a similar way.

As a reminder, check out the output that we got out of the file in the last part. Turn on some good music, and scroll away. The file starts with a ParamBlock2, and ends with a Scene, which is interesting, isn't it? ParamBlock2 is one of the lowest classes in power, while Scene stands basically at the top of the entire system. It means that the deepest structures, or rather the structures on which everything depends, are serialized out first, followed by the higher classes, which are very likely to refer to them in some way. Chances are high that the second class that is serialized directly refers to the first one; and, as you can easily spot, the class with index 1 has two values that equal 0.

        1 0x0001: (SceneClassUnknown: ViewportManager, (0x5a06293c, 0x30420c1e), ViewportManager.gup) [3] {
0 0x2034: (StorageRaw) {
Size: 8
String: ........
Hex: 00 00 00 00 ff ff ff ff }
1 0x204b: (StorageRaw) {
Size: 1
String: .
Hex: 2e }
2 0x1000: (StorageRaw) {
Size: 4
String: ....
Hex: 00 00 00 00
Int: 0
Float: 0 } }

Unfortunately, 0 is not much of a trustworthy value (which reminds me that you should search for Float: 1 values appearing in the scene, those tend to reveal a lot). But, we do have at least two potential chunks, 0x2034 or 0x1000, that may possibly refer to the first class. Moving on to the next class, at index 2 there's another ParamBlock2; which is unlikely to refer to something else, and at index three we can find another class which happens to have a reference to index 2 in one of it's values, 0x2034, which, as it will appear by examining more data, is no coincidence.

        3 0x0002: (SceneClassUnknown: mental ray: material custom attribute, (0x218ab459, 0x25dc8980), mrMaterialAttribs.gup) [2] {
0 0x2034: (StorageRaw) {
Size: 4
String: ....
Hex: 02 00 00 00
Int: 2
Float: 2.8026e-45 }
1 0x204b: (StorageRaw) {
Size: 1
String: .
Hex: 2e } }

As we saw in the previous part, the first chunk that could be found in many of the class instances in the scene, was related to AppData, which is implemented in the Animatable class. The chunks containing the references appear either first, or after this AppData chunk. They are handled by the ReferenceMaker class, a subclass of Animatable, which is one of the base classes that all of the scene classes derive from. Given this, we can fairly assume that the chunks are written in order of inheritance. This is fairly logical. And it also allows us to guess more accurately at which level chunks are implemented that we have not encountered before.

The references, however, are not related to the more user-centric scene graph. Consultation of the documentation will clarify that the scene graph itself is stored in Node classes, which then reference the objects that they represent in the scene, and that the objects normally have no need for knowledge of their position or rank in the scene. In the file, we can find two node entries. After improving our parser to better show the references, these appear as follows.

        380 0x0012: (NodeUnknown: RootNode, (0x00000002, 0x00000000), Builtin) [0] {
References 0x2035: (StorageArray) {
0: 16 }
0x204B Equals 0x2E (46): (CStorageValue) { 46 }
Orphan[0] 0x0120: (StorageRaw) {
Size: 0
String:
Hex: } }

and

        389 0x001a: (NodeImpl: Node, (0x00000001, 0x00000000), Builtin) [0] {
AppData: (AppData) [83] PARSED {
... etc ... }
References 0x2035: (StorageArray) {
0: 16
1: 0
2: 384
3: 1
4: 387
5: 3
6: 134
7: 6
8: 388 }
0x204B Equals 0x2E (46): (CStorageValue) { 46 }
Orphan[0] 0x09ce: (StorageRaw) {
Size: 4
String: ....
Hex: bc 02 00 00
Int: 700
Float: 9.80909e-43 }
Orphan[1] 0x0960: (StorageRaw) {
Size: 8
String: |.......
Hex: 7c 01 00 00 00 08 00 00 }
Orphan[2] 0x0962: (StorageRaw) {
Size: 40
String: G.E._.A.c.c._.M.i.k.o.t.o.B.a.n.i.e.r.e. }
Orphan[3] 0x09ba: (StorageRaw) {
Size: 0
String:
Hex: }
... etc ....

The RootNode appears before the Node, which is opposite to how the Scene stores the classes. This would mean that a node holds a reference to it's parent somewhere. It does not seem to be in the references block, though. The index of the parent, 380, would be found in the hex print as 7c 01. Easily spotted. The first four bytes of 0x0960 refer to the parent index, the four bytes after that suspicously look like flags of some sort. The chunk before it, 0x09ce, is constant across the file, and is different in different file versions, and I would expect it to be a version number. The chunk with the name after that speaks for itself, and the empty one doesn't seem to interesting right now, because it's empty. Empty chunks tend to contain strings or arrays, that's all you can guess.

But, this node is just some metadata, and it does not actually contain the mesh. It must point to the mesh somehow. In the file there's an Editable Poly at index 387.

387 0x0018: (SceneClassUnknown: Editable Poly, (0x1bf8338d, 0x192f6098), EPoly.dlo) [12] {

Which happens to be refered to at index 4 in the 0x2035 block. The chunk refers to more, so we look up those as well.

384 0x0016: (SceneClassUnknown: Position/Rotation/Scale, (0x00002005, 0x00000000), Builtin) [5] {
134 0x000d: (SceneClassUnknown: NeL Material, (0x64c75fec, 0x222b9eb9), Script) [8] {
388 0x0019: (SceneClassUnknown: Base Layer, (0x7e9858fe, 0x1dba1df0), Builtin) [9] {

There are other values in this 0x2035 chunk, but they are not references. Two different chunks are used for storing references to other classes, 0x2034 and 0x2035, either one of them and never both of them in the same class. The 0x2034 block simply is an array of all references directly, where -1 indices map to pointer NULL. Here, however, we see the block 0x2035 in use. Cross referencing with different files reveals that the object appears after the number 1, a controller after 0, a material after 3, and a layer after 6. It would appear that this chunk stores the both the class's index and the reference's index as a map instead, preceeded by some other integer value that probably contains flags of some sort.

At this point, we can parse the scene graph. That's very nice, but we're not geting any actual 3d data yet, which, for curiosity's sake would be totally fun to get out of all this, right? Even though my initial plan was just to parse the file to change some filepath strings inside there.

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

3ds Max File Format (Part 5: How it all links together; ReferenceMaker, INode)的更多相关文章

  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 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 ...

  3. 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 ...

  4. 3ds Max File Format (Part 4: The first useful data; Scene, AppData, Animatable)

    The most interesting part of this file is, evidently, the Scene. Opening it up in the chunk parser, ...

  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. 《自拍教程22》wget_文件下载工具

    wget用途介绍 日常测试过程中,我们可以用wget命令,来下载一些资源文件. wget是一个很好文件下载命令, Linux操作系统下,自带wget命令. Windows操作系统下,需要自己去下载并配 ...

  2. java面向对象入门(3)-java构造方法

    Java构造函数是特殊的方法(没有返回类型),使您可以在应用程序内部的其他类使用对象之前完全初始化对象状态.Java中的构造方法是使用new关键字调用的.下面让我们更深入地了解构造函数. 1.什么是j ...

  3. myeclipse 2018 intaslled jars JREs 选项区别,及注意事项

    Standard 1.1.x VM与Standard VM的区别 在Eclipse或MyEclipse中要设置Installed JREs时,有三个选择: - Execution Environmen ...

  4. 小白的linux笔记11:放弃gitbook,转战Sphinx

    gitbook生成的html目录不折叠且链接失效 装好了gitbook和nodejs,本以为可以安心的做电子书了. 谁想到gitbook慢的一P,而且导出来的html目录不折叠,最关键的是链接有问题, ...

  5. POSIX简介

    POSIX:Potable Operating System Interface of UNIX (可移植操作系统接口),是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的 ...

  6. centos安装gitlab及汉化

    GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.今天,就记录一下centos部署gitlab及其汉化的操作方法. 1.下载安装 下载地址: ...

  7. JavaScript自学笔记(2)---function a(){} 和 var a = function(){}的区别(javascript)

    function a(){} 和 var a = function(){}的区别: 学习做浮窗,看到别人的代码里有: window.onresize = function(){ chroX = doc ...

  8. hdu6162

    这题一开始把我看愣了.难道是线段树套树状数组?空间根本开不下好不好!!! 后来想到维护区间极值,从而排除不必要情况,降低复杂度. 无需修改,码量顿减…… 注意,同一组数据放一行,注意行末空格. #in ...

  9. H5_0025:css3自适应布局单位vw,vh

    视口单位(Viewport units) 什么是视口? 在桌面端,视口指的是在桌面端,指的是浏览器的可视区域:而在移动端,它涉及3个视口:Layout Viewport(布局视口),Visual Vi ...

  10. 新建Microsoft Word文档

    问题描述 L正在出题,新建了一个word文档,想不好取什么名字,身旁一人惊问:“你出的题目叫<新建Microsoft Word文档>吗?”,L大喜,一拍桌子,说:“好,就叫这个名字了.” ...