BMD/BDL (File Format): Difference between revisions
Super Hackio (talk | contribs) (Added JNT1) |
Super Hackio (talk | contribs) m (Added note about how INF1 counts "Verticies") |
||
Line 47: | Line 47: | ||
| 0x0C || Int32 || Matrix Group Count | | 0x0C || Int32 || Matrix Group Count | ||
|- | |- | ||
| 0x10 || Int32 || Vertex Count | | 0x10 || Int32 || Vertex Count<br/>Always equals the number of entries in the "POSITION" [[#Buffer%20Formats|data buffer]] | ||
|} | |} | ||
Revision as of 23:35, 1 March 2025
This page is in progress and may contain incomplete information or editor's notes. |
---|
BMD (Binary Model) and BDL (Binary Display List) are two 3D model formats used in Super Mario Galaxy and Super Mario Galaxy 2, among a few other Wii and GameCube games, such as Super Mario Sunshine.
These two formats hold the same data, except BDL contains an additional set of data which is used for faster rendering speeds.
Super Mario Galaxy & Super Mario Galaxy 2 contain J3DLoader versions 21 and 26.
File Header
Offset | Type | Description |
---|---|---|
0x00 | String | The magic that tells the game which format this file is. (ASCII) J3D2bmd2 for BMD (J3DLoader V21) J3D2bmd3 for BMD (J3DLoader v26) J3D2bdl4 for BDL (J3DLoader v26) |
0x08 | Int32 | The total size of the file |
0x0C | Int32 | The number of chunks present in this file. 8 for BMD 9 for BDL |
Subversion Header
This part of the header is not used, and can be anything.
Offset | Type | Description |
---|---|---|
0x00 | String | A 4 character value representing the Subversion. Usually SVR3 for SMG/2. |
0x04 | Byte[12] | Twelve bytes of padding. Usually these are 0xFF |
INF1 - Scene Information
The Information section hosts a hierarchy of Joints, Materials, and Shapes, which are used to render the model.
Offset | Type | Description |
---|---|---|
0x00 | String | Always INF1 (ASCII) |
0x04 | Int32 | The total size of this chunk |
0x08 | Int16 | J3DLoader Flags |
0x0A | Int16 | Padding (0xFFFF) |
0x0C | Int32 | Matrix Group Count |
0x10 | Int32 | Vertex Count Always equals the number of entries in the "POSITION" data buffer |
J3DLoader Flags
The J3DLoader contains several flags which affect how models are handled. There are more than what are shown here, however, those must be applied by the game itself in the code.
Value | Description |
---|---|
0b0000000000000000 | No flags applied (TODO: Check if this defaults to basic matrix calculation) |
0b0000000000000001 | Use Autodesk Softimage matrix calculation |
0b0000000000000010 | Use Autodesk Maya matrix calculation |
0b0000000000000100 | Use Basic matrix calculation |
0b0000000000001000 | UNKNOWN |
0b0000000000010000 | UseImmidiateMtx (needs research) |
0b0000000000100000 | UsePostTexMtx (needs research) |
0b0000000001000000 | UNKNOWN |
0b0000000010000000 | UNKNOWN |
0b0000000100000000 | NoMatrixTransform (needs research) |
0b0000001000000000 | UNKNOWN |
0b0000010000000000 | UNKNOWN |
0b0000100000000000 | UNKNOWN |
0b0001000000000000 | UNKNOWN |
0b0010000000000000 | DoBdlMaterialCalc |
0b0100000000000000 | NoBdlMaterialPatch - If set, skips the call to J3DModelLoader::readPatchedMaterial. |
0b1000000000000000 | UNKNOWN |
For all BMD files, the game always includes load flags Material_PE_Full, Material_UseIndirect, UseUniqueMaterials, and UNKNOWN_21.
For all BDL files, the game always includes load flags Material_UseIndirect, and UseUniqueMaterials.
> Note: Changing the load flags by changing the code doesn't seem to do much.
VTX1 - Vertex Data
The Vertex Data section contains the actual number values used for the properties of the geometry. It also includes the information on how the values are formatted.
Offset | Type | Description |
---|---|---|
0x00 | String | Always VTX1 (ASCII) |
0x04 | Int32 | The total size of this chunk |
0x08 | Int32 | Buffer Format list offset |
0x0C | Int32 | "POSITION" data buffer offset 0 if not used. |
0x10 | Int32 | "NORMAL" data buffer offset 0 if not used. |
0x14 | Int32 | "TANGENT" data buffer offset 0 if not used. |
0x18 | Int32 | "COLOR_0" data buffer offset 0 if not used. |
0x1C | Int32 | "COLOR_1" data buffer offset 0 if not used. |
0x20 | Int32 | "TEXCOORD_0" data buffer offset 0 if not used. |
0x24 | Int32 | "TEXCOORD_1" data buffer offset 0 if not used. |
0x28 | Int32 | "TEXCOORD_2" data buffer offset 0 if not used. |
0x2C | Int32 | "TEXCOORD_3" data buffer offset 0 if not used. |
0x30 | Int32 | "TEXCOORD_4" data buffer offset 0 if not used. |
0x34 | Int32 | "TEXCOORD_5" data buffer offset 0 if not used. |
0x38 | Int32 | "TEXCOORD_6" data buffer offset 0 if not used. |
0x3C | Int32 | "TEXCOORD_7" data buffer offset 0 if not used. |
Buffer Formats
Each of the Buffers in this section have a format descriptor. This allows different types of data storage, allowing for smaller files.
Each format descriptor contains an Attribute Target, a Component Count, a Data Type, and a Mantissa shifter (to allow floats to be stored as smaller datatypes compared to FLOAT).
Only one descriptor can exist for each attribute.
The Attribute Target tells the game what this buffer is used for.
Value | Name | Description |
---|---|---|
0x00000009 | POSITION | This buffer represents the positions of vertices in the model. Basically required for all visual models. |
0x0000000A | NORMAL | This buffer represents vertex normals, used for the engine's vertex shading. Not needed if no material requires it. |
0x0000000B | COLOR_0 | This buffer is available for Vertex Colors. |
0x0000000C | COLOR_1 | This buffer is available for Vertex Colors. |
0x0000000D | TEXCOORD_0 | This buffer is available for Texture Coordinates. |
0x0000000E | TEXCOORD_1 | This buffer is available for Texture Coordinates. |
0x0000000F | TEXCOORD_2 | This buffer is available for Texture Coordinates. |
0x00000010 | TEXCOORD_3 | This buffer is available for Texture Coordinates. |
0x00000011 | TEXCOORD_4 | This buffer is available for Texture Coordinates. |
0x00000012 | TEXCOORD_5 | This buffer is available for Texture Coordinates. |
0x00000013 | TEXCOORD_6 | This buffer is available for Texture Coordinates. |
0x00000014 | TEXCOORD_7 | This buffer is available for Texture Coordinates. |
0x00000019 | TANGENT | Currently unknown exactly what goes in here. |
0x000000FF | List End | A buffer using this target will end the descriptor list. |
The component count tells the game how many parts of the component that there are. Note that the values are considered based on the attribute target they're assigned to.
Value | Name | Description |
---|---|---|
0x00000000 | POSITION_XY | Unknown |
0x00000001 | POSITION_XYZ | Represents a position in 3D space with 3 values: X, Y, and Z. |
0x00000000 | NORMAL_XYZ | Represents a normal vector in 3D space with 3 values: X, Y, and Z. |
0x00000001 | NORMAL_NBT | Unknown |
0x00000002 | NORMAL_NBT3 | Unknown |
0x00000000 | COLOR_RGB | Represents a color value with only Red, Green, and Blue values. |
0x00000001 | COLOR_RGBA | Represents a color value with Red, Green, Blue, and Alpha values. |
0x00000000 | TEXCOORD_S | Unknown |
0x00000001 | TEXCOORD_ST | Represents a UV texture coordinate with 2 values: X and Y. |
The Data Type tells the game how many bytes each value is, in the sense that an Int32 is 4 bytes, a Int16 is 2 bytes, a Float is 4 bytes, etc.
Note that the Color values have a different set of options.
Value | Name | Description |
---|---|---|
0x00000000 | UInt8 | 1 byte per value (0 to 255) |
0x00000001 | Int8 | 1 byte per value (-128 to 127) |
0x00000002 | UInt16 | 2 bytes per value (0 to 65535) |
0x00000003 | Int16 | 2 bytes per value (-32,768 to 32,767) |
0x00000004 | Float | 4 bytes per value |
0x00000000 | RGB565 | 2 bytes per color |
0x00000001 | RGB8 | 3 bytes per color |
0x00000002 | RGBX8 | 3 bytes per color |
0x00000003 | RGBA4 | 2 bytes per color |
0x00000004 | RGBA6 | 4 bytes per color |
0x00000005 | RGBA8 | 4 bytes per color |
> Note: Both games require colors to be 4 bytes wide at all times, so changing from RGBA8 is worthless.
EVP1 - Skinning Envelopes
Offset | Type | Description |
---|---|---|
0x00 | String | Always EVP1 (ASCII) |
0x04 | Int32 | The total size of this chunk |
0x08 | Int16 | The number of Envelopes stored. |
0x0A | Int16 | Padding (0xFFFF) |
0x0C | Int32 | "Joint Count" list offset |
0x10 | Int32 | "'Joint Count' list index" list offset |
0x14 | Int32 | "Joint Weight" list offset |
0x18 | Int32 | "Inverse Bind Matrices" list offset |
DRW1 - Skinning Assignments
JNT1 - Joint Hierarchy
The Joint Hierarchy section defines the rigging skeleton of a model. There can only be one skeleton per model.
Offset | Type | Description |
---|---|---|
0x00 | String | Always JNT1 (ASCII) |
0x04 | Int32 | The total size of this chunk |
0x08 | Int16 | The number of Joints stored. |
0x0A | Int16 | Padding (0xFFFF) |
0x0C | Int32 | Joint Data table offset |
0x10 | Int32 | Remap table offset |
0x14 | Int32 | Name table offset |
Joint Data
Each joint includes positional data and a bounding box which is used by the game for determining rendering range automatically.
Offset | Type | Description |
---|---|---|
0x00 | Int16 | Matrix Type |
0x01 | UInt8 | Parent Scale inheritance 0 = Follow parent joint's scale 1 = Ignore parent joint's scale |
0x02 | UInt8 | Padding (0xFF) |
0x04 | Float | Scale X |
0x08 | Float | Scale Y |
0x0C | Float | Scale Z |
0x10 | Int16 | Rotation X |
0x12 | Int16 | Rotation Y |
0x14 | Int16 | Rotation Z |
0x16 | Int16 | Padding (0xFFFF) |
0x18 | Float | Translation X |
0x1C | Float | Translation Y |
0x20 | Float | Translation Z |
0x24 | Float | Bounding Sphere Should encapsulate all vertices that the joint affects |
0x28 | Float | Bounding Box Minimum X |
0x2C | Float | Bounding Box Minimum Y |
0x30 | Float | Bounding Box Minimum Z |
0x34 | Float | Bounding Box Maximum X |
0x38 | Float | Bounding Box Maximum Y |
0x3C | Float | Bounding Box Maximum Z |
Rotation is stored between -0x7FFF and 0x7FFF, which ranges -180 degrees and 180 degrees.
SHP1 - Shape Information
The Shape Information section determines how to use the data in the VTX1 section to create shapes.
Offset | Type | Description |
---|---|---|
0x00 | String | Always SHP1 (ASCII) |
0x04 | Int32 | The total size of this chunk |
0x08 | Int16 | The number of Shapes stored. |
0x0A | Int16 | Padding (0xFFFF) |
0x0C | Int32 | Shape Data table offset |
0x10 | Int32 | Remap table offset |
0x14 | Int32 | Name table offset (Generally not used, and thus set to 0) |
0x18 | Int32 | "Vertex Attribute table" offset |
0x1C | Int32 | "Weight Matrix data table" offset |
0x20 | Int32 | "GXDisplayList data buffer" offset |
0x24 | Int32 | "Weight Matrix group table" offset (entry count must equal the entry count of the GXDisplayList group table) |
0x28 | Int32 | "GXDisplayList group table" offset |
Shape Data
Each shape denotes a Matrix Calculation type, which is used for Billboarding, as well as multi-joint skinning.
A shape also contains a group of GXDisplayList primitives, and can have multiple groups if the geometry needs to be weighted to more than 10 DRW1 matrices.
TODO: Figure out what happens in the event that more than 10 are needed. Is it just straight up not allowed?
Offset | Type | Description |
---|---|---|
0x00 | UInt8 | Matrix Type |
0x01 | UInt8 | Padding (0xFF) |
0x02 | Int16 | "GXDisplayList group" count |
0x04 | Int16 | Vertex Attribute offset |
0x06 | Int16 | First "Weight Matrix group table" index |
0x08 | Int16 | First "GXDisplayList group" index |
0x0A | Int16 | Padding (0xFFFF) |
0x0C | Float | Bounding Sphere |
0x10 | Float | Bounding Box Minimum X |
0x14 | Float | Bounding Box Minimum Y |
0x18 | Float | Bounding Box Minimum Z |
0x1C | Float | Bounding Box Maximum X |
0x20 | Float | Bounding Box Maximum Y |
0x24 | Float | Bounding Box Maximum Z |
MAT2 - Material List (Old)
Technically supported by the game, but not known to be used by any model.