Autodesk has never published the .max layout. What follows is what public
reverse engineering has established, mainly the notes the developer Kaetemi wrote while
building a reader for the Ryzom Core tools, which he describes as worked out partly by
guesswork. It is enough to walk a file and list its parts, not to rebuild a scene:
the meaning of most chunks, and how geometry is stored, is not publicly known.
The compound file
A .max file is a Microsoft compound file (OLE2 structured storage),
starting D0 CF 11 E0 A1 B1 1A E1, which holds named streams like files
in a small file system. The streams seen in a 3ds Max 2010 file:
| Stream | Format | Holds |
|---|---|---|
Scene | chunks | the scene itself: every object, modifier, material, controller and node, usually the largest stream |
ClassDirectory3 | chunks | the classes used in the scene; objects in Scene refer to them by index |
DllDirectory | chunks | the plug-in files that provide those classes |
ClassData | chunks | not described in public sources |
Config | chunks | scene settings, including script parameter definitions |
VideoPostQueue | chunks | the Video Post queue |
FileAssetMetaData2 | its own, not chunks | the files the scene uses (textures and so on); added in 3ds Max 2010 |
SummaryInformation, DocumentSummaryInformation | standard Windows property sets | title, author, thumbnail and other document properties |
Stream names are prefixed in the compound file the usual way for property sets
(the summary streams begin with the byte 05).
Chunks
The chunked streams are trees of chunks, much like the older 3DS format. Numbers are little-endian.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | u16 | id | what the chunk is; ids are only meaningful within their parent |
| 2 | 4 | u32 | size | bits 0–30: the size of the chunk including this header; bit 31: set when the chunk contains other chunks rather than data |
| 6 | 8 | u64 | large size | only when the 32-bit size is 0: the size, with the container flag in its top bit |
Because every chunk carries its size, 3ds Max can skip, keep or drop chunks from plug-ins that are not installed.
50 00 0A 00 00 00 01 00 00 00
VideoPostQueue: id 0x0050, size
10 (six bytes of header and four of data), holding 1DllDirectory
A container with one entry per plug-in file. Chunks seen:
| Id | Holds |
|---|---|
| 0x21C0 | a 4-byte value whose meaning is not known |
| 0x2038 | container: one plug-in entry |
| 0x2039 | string: the plug-in’s description, such as “Viewport Manager for DirectX (Autodesk)” |
| 0x2037 | string: the plug-in’s file name, such as a .dlo or .gup |
Strings here are stored without a terminator and the chunk size gives their length; the lengths match the character counts and the reader treats them as Unicode.
ClassDirectory3
A list of class entries, each holding a DLL index (a position in
DllDirectory; −1 for classes built into 3ds Max), a class id (two
32-bit numbers), a superclass id (the kind of thing: geometry, material, controller
and so on) and the class name. Examples from Kaetemi’s file: the scene
Node class has class id (0x00000001, 0x00000000) and
superclass id 1; a plug-in material had class id
(0x64C75FEC, 0x222B9EB9) and superclass id 3072
(0x0C00).
Config
A container of blocks whose first chunk ids (0x2090,
0x20E0, 0x20A0, 0x2180 and others) each name a
group of settings; their contents are mostly not understood. In
0x2180, script parameter definitions use small typed chunks:
| Id | Holds |
|---|---|
| 0x0001 | a boolean, 4 bytes |
| 0x0003 | a 32-bit integer |
| 0x0004 | a float |
| 0x0005 | a string |
| 0x0006 | a string with a size in front and a zero byte after |
| 0x0007 | container: an array |
| 0x0008 | a colour, three floats with 255 as full |
| 0x0060 | an integer: how many chunks follow, as an array size |
Scene
The stream is one container (id 0x2012 in a 3ds Max 2010 file, thought
to depend on the version) whose children are the scene’s objects, one after another.
Each child’s id appears to be the index of its class in
ClassDirectory3 (in Kaetemi’s file, chunk 0x001A held a node,
class 26, and 0x000D a material, class 13), so the same id means
different things in different files. Inside an object, chunks seen
include:
| Id | Holds |
|---|---|
| 0x2150 | application data (AppData): a 0x0100 count, then 0x0110 entries, each a 20-byte 0x0120 header (8-byte class id, 4-byte superclass id, 4-byte property id, 4-byte size) and a 0x0130 value |
| 0x4001 | a name, in UTF-16 (seen on a material) |
How objects refer to one another, and how meshes, modifiers and animation are stored, is not described in public sources.