Difference between revisions of "GMDC"

From SimsWiki
Jump to: navigation, search
(Auto-inserted from WakkaWikki)
 
(Changed to redirect to AC4F8687. AC4F8687 seems to be more complete)
Line 1: Line 1:
{{OldWikiEntry}} ===GMDC Model Data File Specs===
+
#REDIRECT [[AC4F8687]]
  
These are most likely the actual 3D models since they tend to be the largest files (besides textures and animations).
+
[[Category:Modding]]
 
+
[[Category:InternalFormats]]
==this file type uses the Resource Collection format [[RCOL]].==
+
[[Category:FormatsByName]]
 
+
Examples found in ""The Sims 2\TSData\Res\Sims3D\sims03.package""
+
 
+
 
+
This file type uses the standard RCOL header, generally having no file links and only 1 block.
+
 
+
The simplified header looks like this but a program should probably use the more general form.
+
4 new ID flag: This may or may not be there(see [[RCOL]])
+
4 file link count (0)
+
4 index itemcount (1)
+
4 block id (0xAC4F8687)
+
 
+
followed by the GMDC block
+
[[AC4F8687]]
+
[[cGeometryDataContainer]]
+
 
+
cGeometryDataContainer (GMDC) written 6-jan-2005 (WesHowe)
+
latest update: 03-Feb-2005
+
 
+
The GMDC contains the actual shape (mesh) data that defines an object in the game. It uses the standard RCOL format, described elsewhere. What this page will describe is the data model it follows and the known usage of these elements within TS2.
+
 
+
There are three top-level structures; the General Header, Block Header and the Contents Section. The first two relate closely to the general RCOL format. The Content section was designed to support 3D object data.
+
 
+
+
 
+
<pre>
+
struct GeneralHeader {
+
  short        ghLang;                '' =1, a default value Note: some files do not have this or the next item
+
  short        ghStringStyle;          ''=0xffff, default value
+
  long          ghRepVal;              ''=0, default value - One some files, this is the first item
+
  long          ghIndexValue;          ''=1. This could mean more than one GMDC, but not verified.
+
+
  }
+
struct BlockHeader {
+
  char          bhNameLen;              '' this byte will tell how many text characters follow
+
  char          bhName[bhNameLen]
+
+
  long          bhVersion;              '' =1||2||4
+
  char          bhResNameLen;          '' This value indicates how many chars follow
+
  char          bhResName[bhResNameLen]
+
  long          bhResID;                '' =0 (always this)
+
  long          bhResVersion;          '' =2 (seems to always be this)
+
  char          bhFilenameLen;          '' shows how many characters of name follow
+
  char          bhFilename[bhFilenameLen]; ''the internal filename
+
  }
+
struct Contents {
+
  long      ElemCt;                    '' how many copies of struct
+
                                    '' Elements follow
+
  struct    Elements[ElemCt];          '' just appended end-to-end
+
  long      LinkCt;                    '' how many Links
+
  struct    Linkage[LinkCt];          '' and then the Linkage copies
+
  long      GroupCt;                  '' how many are coming
+
  struct    Group[GroupCt];            '' placed one after the other
+
  struct    ModelData;                '' only one of these
+
  long      SubsetCt;                  '' how many subsets are appended
+
                                    '' (0=none)
+
  struct  Subset[SubsetCt];            '' appended to here
+
  }
+
</pre>
+
Almost all of the first two structures, except for the version and the filename, seem to be invariant in TS2. When I create a GMDC I just copy a fixed block of everything up to the filename length in one fwrite() [I only output as version 4].
+
The remainder here is a data definition and values discussion, up to the limits of what I know.
+
<pre>
+
struct Elements {                  '' P1 - this holds the vertices,
+
                                '' normals and UV values
+
  long          NumRecs;          '' # of records (item count)
+
  long          Identity;          '' a typing value, discussed
+
                                '' later
+
  long          RepeatCt;          '' how many times type was used
+
+
  long          Mod1;              '' related to the type, but what
+
                                '' it means is unknown
+
  long          Mod2;              '' also related to type (these
+
                                '' are discussed later)
+
  long          BlockSz;          '' This is NumRecs times two
+
                                '' or three times item size (float=4 bytes)
+
  float        Block[NumRecs][x]; '' Vertices, etc., depending
+
                                '' on type (P1Identity)
+
  long          ExItemCt;          '' either 2 or 4 bytes times
+
                                '' this to follow (per version)
+
  short        ExtensionArray;    '' if (version==4)
+
  long          ExtensionArray;    '' if
+
                                '' ((version==1)||(version==2))
+
  }
+
</pre>
+
+
0x1c4afc56 :mod1=2 mod2=0
+
0x3b83078b :mod1=2 mod2=1,3 - Normals list (3 x float)
+
0x3bd70105 :mod1=0,1,2 mod2=0,3 - Bone weights (1, 2 or 3 floats per vertice)
+
0x5b830781 :mod1=2 mod2=0,3 - Vertices list (3 x float)
+
0x5c4afc5c :mod1=0 mod2=0
+
0x5cf2cfe1 :mod1=2 mod2=3 - Morph Vertex Deltas
+
0x7c4dee82 :mod1=2 mod2=1
+
0x89d92ba0 :mod1=2 mod2=3 - Bump map normals (3 x float)
+
0xcb6f3a6a :mod1=2 mod2=3 - Morph normal deltas
+
0xbb8307ab :mod1=1 mod2=2,3 - UV coordinates (2 x float)
+
0xdb830795 :mod1=4 mod2=2,3
+
0xdcf2cfdc :mod1=4 mod2=3 - Morph vertex map
+
+
 
+
Identities are used to identify data list type
+
 
+
Mod1 and Mod2 - valid values are 0,1,2 or 4.
+
Mod 1 values 0,1,2 mean floats 1, 2 or 3 times #records, 4 means dword 1 time # records (credit darkmatter)
+
If identity=0x7c4dee82 mod1 will be 2 and mod2 will be 1 but the above rules sometimes don't apply
+
 
+
+
+
+
+
0x3bd70105 :mod1=0,1,2 mod2=0,3 - Bone weights (1, 2 or 3 floats per vertice) (matching above assignments)
+
0xdcf2cfdc maps each vertex to a small int, which then keys into the morph vertex and normal data lists (1 for first pair, 2 for second, etc.) to find float values to be added to the original vertices and normals to modify the mesh for fatbelly, pregnant, etc.
+
 
+
It also appears that most of these types must be there, even if empty, to satisfy the game loader.
+
<pre>
+
struct Linkage {                          '' P2
+
  long          LkIndexCt;                '' # of entries to follow
+
  short        LkIndexData[LkIndexPtrCt]; ''  if (version==4)
+
  long          LkIndexData[LkIndexPtrCt]; ''  if
+
                                      '' ((version==1)||(version==2))
+
  long          LkVerticeCt;            '' number of vertices in the model
+
  long          LkActiveCt;              '' This seems to be the same as P2IndexCt
+
  long          LkBlockBCt;              '' number of entries that follow
+
  short        LkBlockB[LkBlockBCt];    '' if (version==4)
+
  long          LkBlockB[LkBlockBCt];    '' if ((version==1)||(version==2))
+
  long          LkBlockCCt;              '' number of entries that follow
+
  short        LkBlockC[LkBlockCCt];    '' if (version==4)
+
  long          LkBlockC[LkBlockCCt];    '' if ((version==1)||(version==2))
+
  long          LkBlockDCt;              '' number of entries that follow
+
  short        LkBlockD[LkBlockDCt];    '' if (version==4)
+
  long          LkBlockD[LkBlockDCt];    '' if ((version==1)||(version==2))
+
  }
+
</pre>
+
+
<pre>
+
struct Group {                            ''  P3 - the group/face definition data is in here
+
  long        Whatzit;                  ''  =2, seems to be invariant
+
  long        LinkIndex;                '' use this value to index into LkIndexData for
+
                                      '' vertices and other parts
+
  char        NameLen;                  '' number of name chars to follow
+
  char        GroupName[NameLen];      '' the name of our model group (e.g. body)
+
  long        FaceCt;                  '' number of faces (triangles), times 3
+
  short        FaceData[FaceCt];        '' if (version==4)
+
  long        FaceData[FaceCt]          ''  if ((version==1)||(version==2))
+
  long        Opacity;                  '' 0xffffffff for solid, much smaller values
+
                                      '' for shadows
+
if(version!=1) {
+
+
                                      '' are indices to ModelSubset
+
  short        SubsetIndices[SubsetCt];  ''  if (version==4)
+
  long        SubsetIndices[SubsetCt];  ''  if (version==2)
+
  } '' if()
+
  }
+
</pre>
+
+
<pre>
+
struct ModelData {                      '' P4 - this is a composite or subset model
+
  long        TransformCt;            '' number of 28-byte values that follow
+
  char        Transform[TransformCt][28]; '' set of 7 floats, see below
+
  long        mdNamePairsCt;          '' number of len+name pairs that follow
+
  char        mdNameALen;            '' length of first name
+
  char        mdNameA[mdNameACt];    '' first name
+
  char        mdNameBLen;            '' length of second name
+
+
  long        mdVerticeCt;            '' if zero, end, else number of vertices (12
+
                                    '' bytes each)
+
  long        mdFaceCt;              '' number of faces times 3
+
  float        mdVertices[mdVerticeCt][3]; '' list of all the vertices in the model
+
  short        mdFaces[mdFaceCt];      ''  if (version==4)
+
  long        mdFaces[mdFaceCt];      ''  if ((version==1)||(version==2))
+
  }
+
</pre>
+
+
The Transform count, if present, matches the total number of Subset structures. Each is a set of 7 floats. The first 4 are a quaternion (X,Y,Z,W) and the last 3 are translation values (X,Y,Z). Usage discussed in the Subset section below.
+
<pre>
+
struct Subset {                        '' P5 - structured following bone assignments
+
  long        VerticeCt;              '' if zero, empty Subset
+
  long        FaceCt;                '' number of subset faces times 3
+
  float        Vertices[VerticeCt][3]; '' data block
+
  short        Faces[FaceCt];          '' if (version==4)
+
  long        Faces[FaceCt];          '' if ((version==1)||(version==2))
+
  }
+
</pre>
+
This section contains subsets of vertices and faces for the model for animated models. When this section is used, the ModelData section may or may not contain a full or partial set of name pairs, but seems to be empty of Vertices and Faces. It will contain a set of transforms, to relocate each subset to match the main model. To apply the transform, you subtract the X,Y,Z values (last 3 floats) from each vertice, then use the quaternion to build a matrix and apply a rotation to the vertex.
+
 
+
I have found that you can build a usable non-animated object GMDC by using Vertices, Normals, UVs, faces and building a composite model. Animated models can be built by adding in Bone assignments and bone weights, adding the appropriate ModelData Transform data (P4), and building a subset model (p5) by bone assignment. All the other parts can be empty, but certain morph data will not be available.
+
[[Category:Modding]]
+

Revision as of 19:33, 2 August 2006

  1. REDIRECT AC4F8687
Personal tools
Namespaces

Variants
Actions
Navigation
game select
Toolbox