Geometry (Metroid Prime): Difference between revisions

From Retro Modding Wiki
Jump to navigation Jump to search
>Aruki
>Aruki
(Changing "submesh" to "surface" because that's what Retro called them)
Line 1: Line 1:
The format for '''geometry''' appears in both the [[CMDL (File Format)|CMDL]] and [[MREA (File Format)|MREA]] formats, and is identical between both. This format is used in all three Prime games, and is largely unchanged between all of them (with the exception of an extra vertex attribute that was added in Echoes and Corruption).
The format for '''geometry''' appears in both the [[CMDL (File Format)|CMDL]] and [[MREA (File Format)|MREA]] formats, and is identical between both. This format is used in all three Prime games, and is largely unchanged between all of them (with the exception of an extra vertex attribute that was added in Echoes and Corruption).


{{research|1|There's a couple unknowns in the submesh headers.}}
{{research|1|There's a couple unknowns in the surface headers, although they're likely unused values.}}


__TOC__
__TOC__
Line 7: Line 7:
== Format ==
== Format ==


An important thing to note off the bat is that both CMDL and MREA files are split up into a number of 32-byte-aligned ''sections''; their respective headers both declare a section count, and list the sizes of each section contained in the file. This is required to navigate to different parts of the file, and is required in order to read the geometry data correctly. Sections are generally split based on the type of data contained in them, so one section might contain vertex coordinates, while another contains a submesh definition. For the purposes of this article, each subheader will mark the start of a new section; use that as your cue to advance to the next one. Check the CMDL or MREA pages for more info on how the sections work.
An important thing to note off the bat is that both CMDL and MREA files are split up into a number of 32-byte-aligned ''sections''; their respective headers both declare a section count, and list the sizes of each section contained in the file. This is required to navigate to different parts of the file, and is required in order to read the geometry data correctly. Sections are generally split based on the type of data contained in them, so one section might contain vertex coordinates, while another contains a surface (submesh) definition. For the purposes of this article, each subheader will mark the start of a new section; use that as your cue to advance to the next one. Check the CMDL or MREA pages for more info on how the sections work.


For vertex attributes, note that there's no count value present anywhere. If you want a rough count, you can divide the size of that attribute's section by the attribute's size.
For vertex attributes, note that there's no count value present anywhere. If you want a rough count, you can divide the size of that attribute's section by the attribute's size.
Line 17: Line 17:
=== Normals ===
=== Normals ===


Normals can appear as either floats or shorts. In CMDL, this usually corresponds to the 0x2 bit in the flags value, and in MREA they will always appear as shorts; this is technically supposed to be set by the vertex format flag in the primitive data, though. If they appear as shorts, they should be divided by the mantissa value that appears on each submesh (that value is almost always 0x8000).
Normals can appear as either floats or shorts. In CMDL, this usually corresponds to the 0x2 bit in the flags value, and in MREA they will always appear as shorts; this is technically supposed to be set by the vertex format flag in the primitive data, though. If they appear as shorts, they should be divided by the mantissa value that appears on each surface (that value is almost always 0x8000).


=== Vertex Color ===
=== Vertex Color ===
Line 29: Line 29:
=== Short UV Coordinates ===
=== Short UV Coordinates ===


These are stored as a sequence of two shorts. Like normals, these should be divided by the submesh's mantissa value. The short UV array is generally only used by terrain lightmaps, and as such this section always appears completely empty (listed with a size of 0) on CMDL. This array can only be used by the first UV coordinate on a given vertex, and whether it's used or not depends on one of the flags on the material. The rest will use the float array.
These are stored as a sequence of two shorts. Like normals, these should be divided by the surface's mantissa value. The short UV array is generally only used by terrain lightmaps, and as such this section always appears completely empty (listed with a size of 0) on CMDL. This array can only be used by the first UV coordinate on a given vertex, and whether it's used or not depends on one of the flags on the material. The rest will use the float array.


=== Submesh Definitions ===
=== Surface Offsets ===


This section is very small and simple; it simply declares a submesh count and then lists the offsets to the end of each submesh. Following this section, there'll be one additional section per submesh.
This section is very small and simple; it simply declares a surface count and then lists the offsets to the end of each surface. Following this section, there'll be one additional section per surface.


{| class="wikitable"
{| class="wikitable"
Line 42: Line 42:
| 0x0
| 0x0
| 4
| 4
| '''Submesh count''' (SC)
| '''Surface count''' (SC)
|-
|-
| 0x4
| 0x4
| 4 × SC
| 4 × SC
| '''Submesh offsets''' (relative to the start of the first submesh)
| '''Surface offsets''' (relative to the start of the first surface)
|-
|-
| colspan=3 {{unknown|Submesh sections begin}}
| colspan=3 {{unknown|Surface sections begin}}
|}
|}


=== Submesh ===
=== Surface ===


There will be one of these sections per submesh. Each submesh starts with a small header; following the end of the header, the file is padded with 0s to the next 32-byte boundary, then the primitive data begins.
There will be one of these sections per surface. Each surface starts with a small header; following the end of the header, the file is padded with 0s to the next 32-byte boundary, then the primitive data begins.


{| class="wikitable"
{| class="wikitable"
Line 104: Line 104:
| Extra data; empty on CMDL, contains a bounding box used for depth sorting on MREA
| Extra data; empty on CMDL, contains a bounding box used for depth sorting on MREA
|-
|-
| colspan=3 {{unknown|End of submesh header; pad to multiple of 32 before primitive data starts}}
| colspan=3 {{unknown|End of surface header; pad to multiple of 32 before primitive data starts}}
|}
|}


The primitive data is a standard GX display list. Each primitive begins with a byte that contains the primitive type in the upper 5 bits, and the vertex format setting in the lower 3; see below for possible settings. After that is a 16-bit vertex count, followed by a series of 16-bit vertex attribute indices.
The primitive data is a standard GX display list. Each primitive begins with a byte that contains the primitive type in the upper 5 bits, and the vertex format setting in the lower 3; see below for possible settings. After that is a 16-bit vertex count, followed by a series of 16-bit vertex attribute indices.


Note that you'll need to check some settings on the material to read the primitive data properly; the material determines which vertex attributes are present. The material also determines whether the submesh is using lightmaps; if it is, then the first UV coordinate will be read out of the short UV array instead of the float one.
Note that you'll need to check some settings on the material to read the primitive data properly; the material determines which vertex attributes are present. The material also determines whether the surface is using lightmaps; if it is, then the first UV coordinate will be read out of the short UV array instead of the float one.


There is no primitive count value; you'll need to continue reading data until you hit the end of the primitive table. There are a couple values you can use for reference; either the submesh's section size, or the submesh's end offset. '''Do not use the primitive table size setting from the submesh header, though'''; it's usually accurate, but on some models it will give you a size smaller than the table actually is, and you'll miss a bunch of data. See Metroid3/4a11192a.CMDL from Prime 1 (icicle Ridley) or Metroid1/05778239.CMDL from Echoes (Samus's gunship) for an example of this.
There is no primitive count value; you'll need to continue reading data until you hit the end of the primitive table. There are a couple values you can use for reference; either the surface's section size, or the surface's end offset. '''Do not use the primitive table size setting from the surface header, though'''; it's usually accurate, but on some models it will give you a size smaller than the table actually is, and you'll miss a bunch of data. See Metroid3/4a11192a.CMDL from Prime 1 (icicle Ridley) or Metroid1/05778239.CMDL from Echoes (Samus's gunship) for an example of this.


There are 7 primitive types supported by GX, indicated in the upper 5 bits of the flag value. Note that the game only ever actually uses triangles, triangle strips, and triangle fans; however, all of these primitives are supported by GX and are therefore supported by the game, and so they could be used in custom model files.
There are 7 primitive types supported by GX, indicated in the upper 5 bits of the flag value. Note that the game only ever actually uses triangles, triangle strips, and triangle fans; however, all of these primitives are supported by GX and are therefore supported by the game, and so they could be used in custom model files.

Revision as of 03:19, 5 April 2015

The format for geometry appears in both the CMDL and MREA formats, and is identical between both. This format is used in all three Prime games, and is largely unchanged between all of them (with the exception of an extra vertex attribute that was added in Echoes and Corruption).


This file format is almost completely documented
There's a couple unknowns in the surface headers, although they're likely unused values.


Format

An important thing to note off the bat is that both CMDL and MREA files are split up into a number of 32-byte-aligned sections; their respective headers both declare a section count, and list the sizes of each section contained in the file. This is required to navigate to different parts of the file, and is required in order to read the geometry data correctly. Sections are generally split based on the type of data contained in them, so one section might contain vertex coordinates, while another contains a surface (submesh) definition. For the purposes of this article, each subheader will mark the start of a new section; use that as your cue to advance to the next one. Check the CMDL or MREA pages for more info on how the sections work.

For vertex attributes, note that there's no count value present anywhere. If you want a rough count, you can divide the size of that attribute's section by the attribute's size.

Vertex Coordinates

These are stored as a sequence of three floats.

Normals

Normals can appear as either floats or shorts. In CMDL, this usually corresponds to the 0x2 bit in the flags value, and in MREA they will always appear as shorts; this is technically supposed to be set by the vertex format flag in the primitive data, though. If they appear as shorts, they should be divided by the mantissa value that appears on each surface (that value is almost always 0x8000).

Vertex Color

These are theoretically stored as 32-bit RGBA values, but vertex color isn't actually used by any mesh in any Retro games, so this section usually appears completely empty.

Float UV Coordinates

These are stored as a sequence of two floats.

Short UV Coordinates

These are stored as a sequence of two shorts. Like normals, these should be divided by the surface's mantissa value. The short UV array is generally only used by terrain lightmaps, and as such this section always appears completely empty (listed with a size of 0) on CMDL. This array can only be used by the first UV coordinate on a given vertex, and whether it's used or not depends on one of the flags on the material. The rest will use the float array.

Surface Offsets

This section is very small and simple; it simply declares a surface count and then lists the offsets to the end of each surface. Following this section, there'll be one additional section per surface.

Offset Size Description
0x0 4 Surface count (SC)
0x4 4 × SC Surface offsets (relative to the start of the first surface)
Surface sections begin

Surface

There will be one of these sections per surface. Each surface starts with a small header; following the end of the header, the file is padded with 0s to the next 32-byte boundary, then the primitive data begins.

Offset Size Description
0x0 0xC Position; used for depth sorting on CMDL and used as the eye position for reflections
0xC 4 Material ID
0x10 2 Mantissa - divide short normals/UVs by this value; always 0x8000
0x12 2 Primitive table size (important note: this value is not always reliable)
0x14 4 Unknown - always 0?
0x18 4 Unknown - always 0?
0x1C 4 Extra data size (ES); this isn't 100%, but seems to be correct
0x20 0xC Reflection eye direction
0x2C 2 Unknown (note: not in Prime 1)
0x2E 2 Unknown (note: not in Prime 1)
0x30 ES Extra data; empty on CMDL, contains a bounding box used for depth sorting on MREA
End of surface header; pad to multiple of 32 before primitive data starts

The primitive data is a standard GX display list. Each primitive begins with a byte that contains the primitive type in the upper 5 bits, and the vertex format setting in the lower 3; see below for possible settings. After that is a 16-bit vertex count, followed by a series of 16-bit vertex attribute indices.

Note that you'll need to check some settings on the material to read the primitive data properly; the material determines which vertex attributes are present. The material also determines whether the surface is using lightmaps; if it is, then the first UV coordinate will be read out of the short UV array instead of the float one.

There is no primitive count value; you'll need to continue reading data until you hit the end of the primitive table. There are a couple values you can use for reference; either the surface's section size, or the surface's end offset. Do not use the primitive table size setting from the surface header, though; it's usually accurate, but on some models it will give you a size smaller than the table actually is, and you'll miss a bunch of data. See Metroid3/4a11192a.CMDL from Prime 1 (icicle Ridley) or Metroid1/05778239.CMDL from Echoes (Samus's gunship) for an example of this.

There are 7 primitive types supported by GX, indicated in the upper 5 bits of the flag value. Note that the game only ever actually uses triangles, triangle strips, and triangle fans; however, all of these primitives are supported by GX and are therefore supported by the game, and so they could be used in custom model files.

Value Primitive
0x80 Quads
0x90 Triangles
0x98 Triangle strip
0xA0 Triangle fan
0xA8 Lines
0xB0 Line strip
0xB8 Points

In addition, the game uses three vertex formats, indicated in the lower 3 bits of the flag value (0x7). The only attributes that change between formats are nrm and tex0, so those are the only ones listed in the table below.

Format GX_VA_NRM type/size GX_VA_TEX0 type/size
0 GX_NRM_XYZ / GX_F32 GX_TEX_ST / GX_F32
1 GX_NRM_XYZ / GX_S16 GX_TEX_ST / GX_F32
2 GX_NRM_XYZ / GX_S16 GX_TEX_ST / GX_S16