Difference between revisions of "Sims 3:0x015A1849"
From SimsWiki
| Line 1: | Line 1: | ||
| + | ==Header== | ||
| + | |||
| + | Start with the RCOL Header: [[Sims 3:RCOL]] | ||
| + | |||
| + | Then the GEOM chunk: | ||
<pre> | <pre> | ||
| − | |||
long 'GEOM' | long 'GEOM' | ||
long Version // 5 | long Version // 5 | ||
| Line 19: | Line 23: | ||
long NumFacePoints // means faces*3 | long NumFacePoints // means faces*3 | ||
word [NumFacePoints][3] // standard face index (three unsigned words per face) for 2-byte FaceFmt | word [NumFacePoints][3] // standard face index (three unsigned words per face) for 2-byte FaceFmt | ||
| + | |||
---------- | ---------- | ||
Tail: | Tail: | ||
| Line 27: | Line 32: | ||
block references[numtgi] // each is a TGI[sub]64[/sub], a 16-byte quantity, so size is 16*numtgi | block references[numtgi] // each is a TGI[sub]64[/sub], a 16-byte quantity, so size is 16*numtgi | ||
// references are to DDS textures and BONE file | // references are to DDS textures and BONE file | ||
| + | </pre> | ||
| − | == | + | ==VertexFormat== |
| − | + | ||
| − | + | For each vertex count: | |
| + | <pre> | ||
long DataType | long DataType | ||
long SubType | long SubType | ||
| Line 42: | Line 49: | ||
5 == Weights (4 float == 16 bytes) | 5 == Weights (4 float == 16 bytes) | ||
6 == Tangent Normal (3 float == 12 bytes) | 6 == Tangent Normal (3 float == 12 bytes) | ||
| − | 7 == TagVal (4 packed bytes) | + | 7 == TagVal (4 packed bytes) -- colour channel data |
10 == VertexID (long == 4 bytes) | 10 == VertexID (long == 4 bytes) | ||
| Line 49: | Line 56: | ||
2 == bytes | 2 == bytes | ||
4 == long | 4 == long | ||
| − | + | </pre> | |
You calculate the offset of each element from the sum of the previous BytesPerElement | You calculate the offset of each element from the sum of the previous BytesPerElement | ||
| − | |||
| − | |||
| − | + | ==Reading Vertex Data Blocks== | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | For each vertex, you need to loop through the VertexFormat as defined, and read the information in order. | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | The order can be completely arbitary, and varied in size. | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | Here is some example code in c# to do so: | |
| − | float | + | <pre> |
| − | + | for (int i = 0; i < numVerts; i++) | |
| − | float | + | { |
| − | + | ||
| − | + | for (int j = 0; j < vertexFormats.Count; j++) | |
| − | float | + | { |
| − | + | float x = 0; | |
| − | float | + | float y = 0; |
| − | + | float z = 0; | |
| + | |||
| + | vertexFormat vf = (vertexFormat)vertexFormats[j]; | ||
| + | switch (vf.dataType) | ||
| + | { | ||
| + | case 1: | ||
| + | x = reader.ReadSingle(); | ||
| + | z = reader.ReadSingle(); | ||
| + | y = reader.ReadSingle(); | ||
| + | sb.AppendLine(" XYZ: " + x.ToString() + " " + y.ToString() + " " + z.ToString() ); | ||
| + | break; | ||
| + | case 2: | ||
| + | x = reader.ReadSingle(); | ||
| + | z = reader.ReadSingle(); | ||
| + | y = reader.ReadSingle(); | ||
| + | sb.AppendLine(" Normal: " + x.ToString() + " " + y.ToString() + " " + z.ToString() ); | ||
| + | break; | ||
| + | case 3: | ||
| + | float u = reader.ReadSingle(); | ||
| + | float v = reader.ReadSingle(); | ||
| + | sb.AppendLine(" UV: " + u.ToString() + " " + v.ToString() ); | ||
| + | break; | ||
| + | case 4: | ||
| + | sb.AppendLine(" Bone: " + reader.ReadUInt32().ToString() ); | ||
| + | break; | ||
| + | case 5: | ||
| + | float w1 = reader.ReadSingle(); | ||
| + | float w2 = reader.ReadSingle(); | ||
| + | float w3 = reader.ReadSingle(); | ||
| + | float w4 = reader.ReadSingle(); | ||
| + | sb.AppendLine(" Weights: " + w1.ToString() + " " + w2.ToString() + " " + w3.ToString() + " " + w4.ToString() ); | ||
| + | break; | ||
| + | case 6: | ||
| + | x = reader.ReadSingle(); | ||
| + | z = reader.ReadSingle(); | ||
| + | y = reader.ReadSingle(); | ||
| + | sb.AppendLine(" Tangent Normal: " + x.ToString() + " " + y.ToString() + " " + z.ToString() ); | ||
| + | break; | ||
| + | case 7: | ||
| + | // Note, not splitting this up yet just reading an int | ||
| + | sb.AppendLine(" TagVal: " + reader.ReadUInt32().ToString() ); | ||
| + | break; | ||
| + | case 10: | ||
| + | sb.AppendLine(" VertexID: " + reader.ReadUInt32().ToString() ); | ||
| + | break; | ||
| + | |||
| + | } | ||
| + | |||
| + | } | ||
| + | } | ||
</pre> | </pre> | ||
| + | |||
| + | Note that basically we just look through the VertexFormat, and read the data in order. There is no fixed "vertex format" version, it's all controlled via the vertexformat data. | ||
Revision as of 20:01, 25 June 2009
Header
Start with the RCOL Header: Sims 3:RCOL
Then the GEOM chunk:
long 'GEOM'
long Version // 5
long TailOffset
long TailSectionSize // (0x14, 0x44 observed)
long EmbeddedID //(0, 0x548394B9 observed)
if(EmbeddedID!=0) {
long ChunkSize
byte[ChunkSize] // starts with 'MTNF'
}
long 0 //unknown purpose
long 0 // unknown purpose
long NumVerts
long FCount // was named Version, but is number of vertex elements
block VertexFormat[FCount] // long, long, byte; documented below 9 bytes/vertex-element-count
struct VertexData[NumVerts] // follows vertex format block, documented below
block FaceFmt // long ItemCount, byte BytesPerFacepoint
long NumFacePoints // means faces*3
word [NumFacePoints][3] // standard face index (three unsigned words per face) for 2-byte FaceFmt
----------
Tail:
long flags
long count1
long bonehasharray[count1] // 32-bit hash of used bone names.
long numtgi
block references[numtgi] // each is a TGI[sub]64[/sub], a 16-byte quantity, so size is 16*numtgi
// references are to DDS textures and BONE file
VertexFormat
For each vertex count:
long DataType long SubType byte BytesPerElement For DataType: 1 == Position (3 float == 12 bytes) 2 == Normal (3 float == 12 bytes) 3 == UV (2 float == 8 bytes) 4 == Bone Assignment (long == 4 bytes) 5 == Weights (4 float == 16 bytes) 6 == Tangent Normal (3 float == 12 bytes) 7 == TagVal (4 packed bytes) -- colour channel data 10 == VertexID (long == 4 bytes) For SubType 1 == floats 2 == bytes 4 == long
You calculate the offset of each element from the sum of the previous BytesPerElement
Reading Vertex Data Blocks
For each vertex, you need to loop through the VertexFormat as defined, and read the information in order.
The order can be completely arbitary, and varied in size.
Here is some example code in c# to do so:
for (int i = 0; i < numVerts; i++)
{
for (int j = 0; j < vertexFormats.Count; j++)
{
float x = 0;
float y = 0;
float z = 0;
vertexFormat vf = (vertexFormat)vertexFormats[j];
switch (vf.dataType)
{
case 1:
x = reader.ReadSingle();
z = reader.ReadSingle();
y = reader.ReadSingle();
sb.AppendLine(" XYZ: " + x.ToString() + " " + y.ToString() + " " + z.ToString() );
break;
case 2:
x = reader.ReadSingle();
z = reader.ReadSingle();
y = reader.ReadSingle();
sb.AppendLine(" Normal: " + x.ToString() + " " + y.ToString() + " " + z.ToString() );
break;
case 3:
float u = reader.ReadSingle();
float v = reader.ReadSingle();
sb.AppendLine(" UV: " + u.ToString() + " " + v.ToString() );
break;
case 4:
sb.AppendLine(" Bone: " + reader.ReadUInt32().ToString() );
break;
case 5:
float w1 = reader.ReadSingle();
float w2 = reader.ReadSingle();
float w3 = reader.ReadSingle();
float w4 = reader.ReadSingle();
sb.AppendLine(" Weights: " + w1.ToString() + " " + w2.ToString() + " " + w3.ToString() + " " + w4.ToString() );
break;
case 6:
x = reader.ReadSingle();
z = reader.ReadSingle();
y = reader.ReadSingle();
sb.AppendLine(" Tangent Normal: " + x.ToString() + " " + y.ToString() + " " + z.ToString() );
break;
case 7:
// Note, not splitting this up yet just reading an int
sb.AppendLine(" TagVal: " + reader.ReadUInt32().ToString() );
break;
case 10:
sb.AppendLine(" VertexID: " + reader.ReadUInt32().ToString() );
break;
}
}
}
Note that basically we just look through the VertexFormat, and read the data in order. There is no fixed "vertex format" version, it's all controlled via the vertexformat data.