Materials (Metroid Prime)

The format for materials is seen in both the CMDL and MREA formats, and is identical in both. This particular material format appears in both Metroid Prime and Metroid Prime 2, with minor differences.

GX Explanation
The materials system in Metroid Prime is heavily dependent on the GameCube and Wii's graphics system, GX. GX is a fixed-function graphics pipeline, similar to old versions of OpenGL. In GX, rendering is done through a series of steps called Texture EnVironment Stages, or or TEV stages for short.

Prior to TEV stages, per-vertex calculations are performed. Lighting calculations are performed, and passed to GX as a rasterized vertex color; texture coordinate generation (texgen) is also performed and made available to TEV.

How TEV stages actually work: Each TEV stage takes in four color (RGB) inputs, and four alpha inputs, from one of eight sources. Then these four input colors are combined into one output color, and the output is saved into one of four registers, which can subsequently be used as input in the next TEV stages. The final stage must always save its output into the "previous TEV stage" register; that register is used as the final pixel color that gets displayed onscreen.

Material Set Format
Materials come as part of a set; often there will only be one set per file, but many CMDLs can have more than one. The set begins with a short header before the actual material data begins.

General Settings
Each material begins with a flags value, followed by a list of texture indices:

Flags
These are the known flag settings:

Vertex Attribute Flags
These flags are generally toggled in pairs, with each pair corresponding to a vertex attribute; if a pair is set, then vertices using this material will have the corresponding attribute. This is vital for reading geometry.

An important note is that while the leftmost byte is not used in Prime 1, in Echoes there's occasionally a value there that toggles an extra vertex attribute preceding position. This needs research to determine what the new attribute actually is. Also, GX supports up to 8 texture coords per vertex, but the game doesn't seem to allow you to assign more than 7 (though this could do with some double-checking).

These are the possible attributes:

Konst Colors
These values are only present when flag 0x8 is enabled. These allow you to set Konstant values, which can subsequently be used as inputs in TEV stages. The maximum number of Konst values you can set on one material is 4. The colors themselves are simply 32-bit RGBA values.

Blend Mode
The two blend factors set the blending mode used. The most common values you'll see are 0/1, which is used on opaque materials; transparent materials will usually have either 1/1, for additive blending, or 5/4, for alpha blending. Here's the full range of possible settings for each value:

Color Channels
There's an odd quirk with how these values work; although there's a count value listed, the game will only actually read the first value listed, and then skip the rest. There's no reason to ever have more than one flag value. Aside from that, how this works is unknown and needs research.

TEV Stages
There'll be one of these structures per TEV stage:

After looping through each TEV stage, there will be one of these structures per stage:

Color Input Flags
These flags set the four color inputs that are used by the TEV stage. Each color is allocated 5 bits, even though only 4 are actually used; the lower bits correspond to the lower input numbers (eg. the bottom 5 bits refer to the first input).

There are 16 possible color sources:

Alpha Input Flags
Similar to the color input flags, these set the four alpha inputs used by the TEV stage. Each value is allocated 5 bits, although only 3 are used. The main difference with alpha is there's only 8 possible sources instead of 16:

Color Combine Flags
These flags specify how the operation that combines the four input colors into one output color is performed.

This is the combiner function:

tevrigid = (d (tevop) ((1.0-c)*a + c*b) + tevbias) * tevscale;

The values set in the color operation flags correspond to the parameters passed to GX_SetTevColorOp. These are the settings:

Note that the vast majority of materials in the game, if not all of them, don't really bother with any of this; they enable clamping, set an output register, and leave everything else at their defaults of 0.

Alpha Combine Flags
This is exactly the same as the color combine flags; the only difference is it operates on alpha instead of color.

Texgen
After the TEV stages comes a sequence of flags determining how texgen is executed. Texgen is the process of taking input values and using them to generate texture coordinates (or UV coordinates), which can then be used by the TEV stages. It's important to note that any vertex attribute can be used as a texgen input; in fact, it's rather common for materials to use the vertex normal as an input to simulate reflections. That means the number of texture coords present on each vertex is not the same as the number of texture coords available to TEV.

The flags largely correspond to arguments passed to GX_SetTexCoordGen2. These are the settings:

Material Animations
The material animations section immediately follows the texgen flags. It starts with this short header:

The structure of the animations themselves is somewhat simple. Each animation has a 32-bit mode setting, followed by a number of float parameters. The number and usage of these float parameters varies depending on what mode is set. There are 7 possible modes, but only modes 2 through 5 are known.

For all of the following modes, let s be equal to seconds mod 900.

Mode 2: UV Offset
This mode is used to scroll both U and V at the same time. It has four float parameters: offsetA, offsetB, scaleA, and scaleB.

uOffset = (s * scaleA) + offsetA; vOffset = (s * scaleB) + offsetB;

Mode 3: Rotation
This mode rotates the material. It has two float parameters: offset and scale.

angle = (s * scale) + offset;

The material is then rotated by angle degrees.

Mode 4/5: U/V Offset
This mode can be used to scroll U and V independently from each other. It has four float parameters. The offset calculation for these modes is unknown; however, the same code is used for both modes, with the only difference being whether the calculated offset is applied to U or V.