GMDC Data Structure

From SimsWiki
Jump to: navigation, search

A Datacentric View of the GMDC

There are six major divisions used in building a GMDC: Header, Elements, Linkages, Groups, Model and Subset.

The general structure of the file is the header followed by each of the other blocks. Each block begins with a count of the component parts (which have various sizes) that enable it to be read as a stream. One common technique is the use of a modified ‘pascal’ style string for names. This string has the first byte, in the range of 0 to 128, indicating the number of characters to follow, followed by that many characters.

The Header is built from standard DBPF RCOL package identifier properties. Instead of discussing the RCOL layout, we will describe it as it applies to the GMDC below:

       short   Language;               // 1
       short   StringStyle;            // 0xffff
       long    RepeatValue;            // 0
       long    IndexValue;             // 1 (or larger if more than one GMDC)
       long    FileType;               // 0xAC4F8687 (GMDC identifier)
       char    NameLen;                // bytes (0 – 128) in following name
       char    Name[NameLen];          // ‘cGeometryDataContainer’
       long    BlockID;                // 0xAC4F8687
       long    Version;                // 1, 2 or 4 used
       char    NameLen;                // bytes (0 – 128) in following name
       char    Name[NameLen];          // ‘cSGResource’
       long    ResourceID;             // 0
       long    ResourceVersion;        // 2
       char    NameLen;                // bytes (0 – 128) in following name
       char    FileName[NameLen];      // ex: ‘afBodyNaked_tslocator_gmdc’

Some possibilities exist in the RCOL definition for the start of the header to differ. Generally, to load a GMDC you check the values against this list for a sanity check, and then retain the Version (1, 2 or 4) and the FileName. The size of the header is 67 bytes plus the number of characters in the filename plus one.

When creating a GMDC, building the header is as simple as writing out the 67 bytes before the filename, writing out a one-byte filename length, and the writing out the filename. Most of the meshes use Version = 4 in the game files, so consistently outputting a version 4 will simplify the job.

The Elements section is a collection of typed data arrays, the basic mesh elements, that will be referenced later when the face structure is defined.

       long    NumRecs;                // count of total elements
       long    Identity;               // typing value, detailed later
       long    RepeatCount;            // count of repeats for the same type
       long    BlockFormat;            // data element sizes (detailed below)
       long    SetGroup;               // elements formats (detailed below)
       long    BlockSize;              // number of bytes that follow (calculate)
       char    Block[BlockSize];       // these may be sets of floats or bytes
       long    ItemCount;              // number of 2 or 4 byte elements to follow
       Only one of the following two apply (per version value):
       short   Array2[ItemCount];      // used when version == 4
       long    Array4[ItemCount];      // used for versions 1 and 2

The Identity field is a value from the following list:

       0x1C4AFC56    Blend Indices 
       0x5C4AFC5C    Blend Weights 
       0x7C4DEE82    Target Indices 
       0xCB6F3A6A    Morph Normal Deltas
       0xCB7206A1    Colour 
       0xEB720693    Colour Deltas 
       0x3B83078B    Normals List 
       0x5B830781    Vertices 
       0xBB8307AB    UV Coordinates 
       0xDB830795    UV Coordinate Deltas 
       0x9BB38AFB    Binormals 
       0x3BD70105    Skin (Bone) Weights 
       0xFBD70111    Bone Assignments 
       0x89D92BA0    Bump Map Normals 
       0x69D92B93    Bump Map Normal Deltas 
       0x5CF2CFE1    Morph Vertex Deltas 
       0xDCF2CFDC    Morph Vertex Map 
       0x114113C3    (EP4) VertexID 
       0x114113CD    (EP4) RegionMask

The BlockFormat is one of these four values:

       0x00          single float (4 byte length)
       0x01          paired floats (8 total bytes)
       0x02          triple floats (12 bytes total)
       0x04          unsigned long or bytes (4 bytes)

The SetGroups are one of the following values:

       0x00           Main
       0x01           Norms
       0x02           UV
       0x03           Secondary

The elements are generally collects of vertices, normals, UVs, morph values, bone assignments and skin weights that are tied together by the face references to build a 3D object.

Elements appear ordered in sets. There is usually an empty set of each used Identity that comes first, followed by one or more referenced sets. The empty sets appears necessary, perhaps to allocate storage space.

A set of Identities will be built as matched arrays, that is, one of the basic size units (per BlockFormat) of each set will align with the vertex of the same index. While many elements appear only when mesh features are used, the first and each subsequent vertex will have a corresponding element in each included set. What we mean here is that the first vertex will correspond with the first normal, the first UV, the first bone assignment and so on.

The following discussion lists the main types used in Sims2 meshes in the order they are normally found (all but the first two are essentially optional, being present only when needed to support a mesh property):

Vertices (0x5B830781 [format 0x02]) – These are the main building elements, and are a set of coordinates in local 3D space for a point, normally one corner of a triangle. Each vertex has three floats of four bytes each (IEEE single-precision floating point number).

Normals (0x3B83078B [format 0x02]) – These are standard vertex normals. Like the vertices, they are three floats, but represent a vector in space, and thus are normalized (all values are smaller than 1.0).

UV Coordinates (0xBB8307AB [format 0x01]) – These are paired floats that represent the fractional distance from the upper-left corner to map the vertex into the texture map.

UV Coordinate Deltas (0xDB830795 [format 0x04]) – The purpose of these is undetermined, and may be misnamed. They are normally empty occurring only in the initial set of elements, but sometimes are found in the regular sets.

Target Indices (0x7C4DEE82 [format 0x02]) – These only appear in the empty initial set of elements. They have an ordinal relationship with the morph names, but do not appear to be needed by the loader. The contents, when present, have both vertices and vertex indices that are believed to be offsets to the Subset (Bounding Mesh) group when the corresponding morph is active. This is usually the only element that has a set of items after the Block.

Bone Assignments (0xFBD70111 [format 0x04]) – There are four bytes here. If this element is present, the first byte (lsb if read as a long) is the main bone assignment. A value of 255 (-1) means no bone is assigned, otherwise the value is the bone index (defined later). So, up to four bone assignments are available per-vertex.

Skin (Bone) Weights (0x3BD70105 [format 0x00, 0x01 or 0x02]) – This element is present if the Bone Assignments element is present. While there are four slots to assign bones, the usage is determined by the Skin Weights. A single weight section will normally always contain values of 1.0, indicating that all the influence on the skin will be obtained from the first bone assignment. A dual weight section will have two weights per vertex that should total exactly 1.0. Depending on the animation needs, this may be all weighted on one assignment or spread between two. A three weight section will support three or four bone assignments. Three is the simple one-to-one correspondence with the bone assignments, and the total weighting should add up to 1.0 (failing to total 1.0 will result in animation and other display issues). Three weights may also be made to work with four bone assignments by implying the fourth weight. This is done by adding the three weights up and subtracting the sum from 1.0. The difference is the weight to be applied to the fourth assignment. For example, spreading four assignments equally would have weights of 0.25, 0.25 and 0.25, these total 0.75 and thus leave 0.25 when subtracted, which is the weighting to be applied to the fourth assignment.

Morph Vertex Deltas (0x5CF2CFE1 [format 0x02]) -

If there are morphs present in the GMDC, then there will be at least one Morph Vertex Deltas (MVD) section, optionally a matching Morph Normal Delta (MND) plus a Morph Vertex Map (MVM). There can be up to four MVD sections per Vertex element. Each of the MVD elements is not a complete morph, but rather a data repository that holds values that are to be added to a vertex (a delta value) when a morph is triggered. How these are keyed is through the MVM element.

Morph Normal Deltas (0xCB6F3A6A [format 0x02]) -

When these are used, they are deltas to adjust the normals for a morph. If they are used, they are aligned with the MVD because the same morph map is used for both types.

Morph Vertex Map (0xDCF2CFDC [format 0x04]) -

The Morph Vertex Map is a collection of 4-byte morph name index values that map the MVD and MND to a vertex for a particular morph. The limit of 4-bytes to the format means that any one vertex can have no more than four morphs. How this map works is that in a section we haven’t reviewed yet there is a set of morph (blend) name pairs. Each of these has an implied index value based on its position on the list (starting at zero). Every legal value to be used in a morph map should have a morph name pair. The first of each 4-byte set maps an index value to the first MVD that is grouped with the vertices. The next byte maps to the second MVD, and so on, to the third and fourth sets (if used). The end result is that when a specific target value, e.g. 1, is present in the first byte, when the morph is triggered the game will add the delta values from the first MVD to the vertex coordinates to alter the mesh shape. If the ‘1’ had been in the second byte instead, the delta values used would have been from the second MVD element.

Bump Map Normals (0x89D92BA0) – These are also known as Tangent Normals, and are used to define a ray that would lie on plane tangent to the vertex. This is used for allowing bump maps to alter the apparent height of the surface. While it would have been possible for the game to calculate these at run time, by pre-calculating these values at mesh creation time the loading time is reduced.


The linkages section groups elements into sets. Although their position in the elements section is generally ordered by groupings, it is through this part that they are linked to the face definitions.

       long    Count;                  // count of total sets
       for each Count:
       long    IndexCount;             // number of indexes in block A
       one of the following, per version
       short   Indices[IndexCount];    // for version == 4
       long    Indices[IndexCount];    // for versions 1 and 2
       Repeat above for Blocks B, C and D (generally zeroed out).

The values for Indices are the applicable index value for an element block from the previous section. Generally, there will be at least two values here, Vertices and Normals, likely a third, UVs, sometimes Target Indices, and then (if used) Bone Assignments, Skin Weights, Morph Vertex Deltas(s), Morph Normal Deltas and a Morph Map, and maybe the Bump Map Normals.

The sets from this section are indexed, and may be referenced by more than one set of triangles (group), or there may be a one-to-one relationship between groups and sets, or the two may be mixed.

This section is where the triangle sets, or groups, are defined and stored. Each group will have a link index, which indicates the sets grouping definition from the Linkages section, and each triangle consists of three vertex indices, each of which then indicates which vertex and all associated elements are to be used.

       long    Count;                     // count of total groups

For each group:

       long    PrimitiveType;             // default = 2
       long    LinkIndex;                 // Index of set from Linkages section
       char    NameLen;                   // bytes (0 – 128) in following name
       char    Name[NameLen];             // group name
       long    FaceCt;                    // faces*3 (number of triangle points)

One of the following two, per version:

       short   VertexIndex[FaceCt];       // version == 4
       long    VertexIndex[FaceCt];       // versions 1 and 2
       long    Opacity;                   // alpha value. 0xffffffff for opaque.
       long    SubsetCount;               // versions 2 and 4 only
       short   SubsetIndices[SubsetCount];// version 4 only
       long    SubsetIndices[SubsetCount];// version 2 only

The SubsetIndices map the standard bone values, as defined in the CRES, to the values used in the GMDC Bone Assignment elements. The mapping works by using the Bone Assignment value as the index, and retrieving the Standard Bone Value from the array. The SubsetCount should be equal to the number of bones actually referenced in the group, or animation difficulties will be encountered.


This contains the joint definitions, expressed as sets of 7 float values known as Quaternions, the morph names and for non-IK animated meshes a model of the entire entity, consisting of only vertices and faces, which is used as a bounding mesh for the game to use to determine intersection on mouse-clicks.

       long    Count                  // number of transform blocks
       float   Quaternion[Count][7];  // ordered: x,y,z,w rotation; x,y,z transform
       long    PairCt;                // number of morph name pairs
       PairCount number of:
       char    NameLen1;              // bytes (0 – 128) in following name
       char    Name[NameLen1];        // blend group name
       char    NameLen2;              // bytes (0 – 128) in following name
       char    Name[NameLen2];        // assigned element name
       long    VCount;                // number of vertices in Model
       If VertexCount == 0, then skip the next items
       long    FCount;                // number of faces(*3) in model
       float   Vertices[VCount][3];   // XYZ for each vertex
       Use one of the following two items, per version:
       short   Faces[FCount];         // version == 4	
       long    Faces[FCount];         // versions 1 and 2

The transform blocks are values used to translate and then rotate a point from 0,0,0 to the joint position via a Quaternion. The name pairs are the morph names. The paired index position indicates the target value (one or more of these names may be empty) that is used in the Morph Map(s).

The Model is used where there is no IK animation (essentially models that are not hair, body, clothing, face or pet meshes). It can be built by placing all the vertices from all the groups into the single Vertices array and then putting all the faces together in the Faces array, making sure to add the number of previous group vertices to each point vertex index. A more sophisticated algorithm would eliminate all duplicate vertices as it built the Vertices and Faces arrays. This is more computationally intensive at mesh creation time, but creates a smaller output file and will reduce the memory and computation time required at run time.

Essentially, the Subset section replaces the Model portion of the Model section. It serves the same purpose, but the Subset is defined bone-by-bone, and the vertex position values have been reverse-rotated and then translated using the transform blocks from the Model section.

       long    SubCount;               // number of subsets (one per transform)
       One of each for each SubCount:
       long    VCount;                 // number of vertices for this bone
       The rest of the items only if VCount is not zero:
       long    FCount;                 // number of faces(*3)

float Vertices[VCount][3]; // XYZ (transformed) for each vertex

       One of the following two, per version:
       short   Faces[FCount];          // version == 4
       long    Faces[FCount];          // versions 1 and 2

This transformed bounding mesh, sorted by bone, is used in IK animated models so that the bounding mesh can be reshaped to fit the model by using the transforms that represent the bone positions at the time it is needed.

Personal tools

game select