On this page I'll try to describe how indices parsing is done and what current issues are.
We have a single vertex buffer per model variation, this makes up the vertices for one whole model. We get the indices data per surface, a surface is a part of the mesh with a specific material. There might be multiple surfaces with the same material.
The indices data appears to be a 16bit stream, we have 3 different types of 16bit values, the type depends on some MSB bits.
So we need to keep track of a vertex start offset in order to normalize the indices to real indices inside the vertex buffer.
Summing the problem: I don't know how to adjust the indices to real indices inside the vertex buffer when they are out of current vertex count bounds.
I've added a simple debug program that prints out the polygon data for further debugging.
Some South Park models that are of interest because they are relatively simple and all the math operations on the polygon data I've checked seem to be different somehow, when a formula works on one model, an other will usual break..
$ bin/debug_indices files/win32.dat 172
T2FS::INFO::Found schema ./schema/win32.json
total verts: 140
sufrace: 0
<set boneID> 1
[new block] 00 28
surface: 00 i: 004 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 00 b: 01 c: 02
surface: 00 i: 006 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 00 b: 03 c: 01
surface: 00 i: 008 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 05 b: 00 c: 04
surface: 00 i: 010 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 01 b: 04 c: 02
surface: 00 i: 012 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 04 b: 01 c: 05
surface: 00 i: 014 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 00 b: 05 c: 03
surface: 00 i: 016 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 06 b: 07 c: 08
surface: 00 i: 018 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 09 b: 06 c: 08
surface: 00 i: 020 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 11 b: 12 c: 13
surface: 00 i: 022 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 15 b: 16 c: 17
surface: 00 i: 024 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 19 b: 20 c: 21
surface: 00 i: 026 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 24 b: 19 c: 25
surface: 00 i: 028 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 17 b: 18 c: 15
surface: 00 i: 030 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 10 b: 08 c: 07
surface: 00 i: 032 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 22 b: 23 c: 19
surface: 00 i: 034 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 19 b: 21 c: 22
surface: 00 i: 036 offset: 0000 unk: 00 verts: 28 boneId: 01 a: 13 b: 14 c: 11
<set boneID> 3
[new block] 22 07
surface: 00 i: 042 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 22 b: 02 c: 24
surface: 00 i: 044 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 02 b: 23 c: 24
surface: 00 i: 046 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 22 b: 04 c: 00
surface: 00 i: 048 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 04 b: 22 c: 23
surface: 00 i: 050 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 23 b: 02 c: 04
surface: 00 i: 052 offset: 0028 unk: 22 verts: 07 boneId: 03 a: 22 b: 00 c: 02
<set boneID> 4
[new block] 00 11
surface: 00 i: 058 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 06 b: 07 c: 08
surface: 00 i: 060 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 01 b: 05 c: 04
surface: 00 i: 062 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 02 b: 01 c: 04
surface: 00 i: 064 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 25 b: 26 c: 00
surface: 00 i: 066 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 02 b: 27 c: 01
surface: 00 i: 068 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 25 b: 00 c: 03
surface: 00 i: 070 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 01 b: 27 c: 28
surface: 00 i: 072 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 06 b: 08 c: 09
surface: 00 i: 074 offset: 0035 unk: 00 verts: 11 boneId: 04 a: 09 b: 08 c: 10
[new block] 00 03
surface: 00 i: 078 offset: 0046 unk: 00 verts: 03 boneId: 04 a: 00 b: 01 c: 02
<set boneID> 5
[new block] 00 11
surface: 00 i: 084 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 01 b: 02 c: 03
surface: 00 i: 086 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 04 b: 01 c: 03
surface: 00 i: 088 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 05 b: 01 c: 04
surface: 00 i: 090 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 07 b: 08 c: 09
surface: 00 i: 092 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 06 b: 05 c: 04
surface: 00 i: 094 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 11 b: 14 c: 00
surface: 00 i: 096 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 02 b: 05 c: 06
surface: 00 i: 098 offset: 0049 unk: 00 verts: 11 boneId: 05 a: 03 b: 02 c: 06
<set boneID> 1
[new block] 11 04
surface: 00 i: 104 offset: 0060 unk: 11 verts: 04 boneId: 01 a: 10 b: 11 c: 12
<set boneID> 6
[new block] 00 10
surface: 00 i: 110 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 01 b: 02 c: 03
surface: 00 i: 112 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 04 b: 05 c: 06
surface: 00 i: 114 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 07 b: 05 c: 04
surface: 00 i: 116 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 08 b: 07 c: 04
surface: 00 i: 118 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 09 b: 07 c: 08
surface: 00 i: 120 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 06 b: 09 c: 08
surface: 00 i: 122 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 05 b: 09 c: 06
surface: 00 i: 124 offset: 0064 unk: 00 verts: 10 boneId: 06 a: 00 b: 13 c: 14
end surface 0: processed verts: 74
sufrace: 1
<set boneID> 1
[new block] 00 10
surface: 01 i: 004 offset: 0074 unk: 00 verts: 10 boneId: 01 a: 00 b: 01 c: 02
<set boneID> 6
[new block] 11 03
surface: 01 i: 010 offset: 0084 unk: 11 verts: 03 boneId: 06 a: 11 b: 03 c: 04
surface: 01 i: 012 offset: 0084 unk: 11 verts: 03 boneId: 06 a: 05 b: 06 c: 12
surface: 01 i: 014 offset: 0084 unk: 11 verts: 03 boneId: 06 a: 08 b: 13 c: 09
<set boneID> 5
[new block] 22 02
surface: 01 i: 020 offset: 0087 unk: 22 verts: 02 boneId: 05 a: 03 b: 22 c: 04
surface: 01 i: 022 offset: 0087 unk: 22 verts: 02 boneId: 05 a: 07 b: 05 c: 23
<set boneID> 4
[new block] 00 10
surface: 01 i: 028 offset: 0089 unk: 00 verts: 10 boneId: 04 a: 00 b: 01 c: 02
surface: 01 i: 030 offset: 0089 unk: 00 verts: 10 boneId: 04 a: 03 b: 04 c: 05
<set boneID> 3
[new block] 11 03
surface: 01 i: 036 offset: 0099 unk: 11 verts: 03 boneId: 03 a: 11 b: 07 c: 13
surface: 01 i: 038 offset: 0099 unk: 11 verts: 03 boneId: 03 a: 06 b: 07 c: 11
surface: 01 i: 040 offset: 0099 unk: 11 verts: 03 boneId: 03 a: 08 b: 12 c: 09
end surface 1: processed verts: 28
sufrace: 2
<set boneID> 4
[new block] 00 12
surface: 02 i: 004 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 00 b: 01 c: 02
surface: 02 i: 006 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 00 b: 05 c: 04
surface: 02 i: 008 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 02 b: 01 c: 03
surface: 02 i: 010 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 04 b: 06 c: 01
surface: 02 i: 012 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 08 b: 00 c: 09
surface: 02 i: 014 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 08 b: 09 c: 10
surface: 02 i: 016 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 00 b: 07 c: 05
surface: 02 i: 018 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 00 b: 08 c: 07
surface: 02 i: 020 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 01 b: 00 c: 04
surface: 02 i: 022 offset: 0102 unk: 00 verts: 12 boneId: 04 a: 08 b: 11 c: 07
end surface 2: processed verts: 12
sufrace: 3
<set boneID> 1
[new block] 00 04
<set boneID> 2
[new block] 11 02
surface: 03 i: 008 offset: 0118 unk: 11 verts: 02 boneId: 02 a: 03 b: 12 c: 11
surface: 03 i: 010 offset: 0118 unk: 11 verts: 02 boneId: 02 a: 11 b: 02 c: 03
<set boneID> 7
[new block] 22 02
surface: 03 i: 016 offset: 0120 unk: 22 verts: 02 boneId: 07 a: 22 b: 23 c: 01
surface: 03 i: 018 offset: 0120 unk: 22 verts: 02 boneId: 07 a: 00 b: 22 c: 01
end surface 3: processed verts: 8
sufrace: 4
<set boneID> 1
[new block] 00 05
surface: 04 i: 004 offset: 0122 unk: 00 verts: 05 boneId: 01 a: 00 b: 01 c: 02
surface: 04 i: 006 offset: 0122 unk: 00 verts: 05 boneId: 01 a: 03 b: 04 c: 00
surface: 04 i: 008 offset: 0122 unk: 00 verts: 05 boneId: 01 a: 00 b: 02 c: 03
end surface 4: processed verts: 5
sufrace: 5
<set boneID> 1
[new block] 00 05
surface: 05 i: 004 offset: 0127 unk: 00 verts: 05 boneId: 01 a: 00 b: 01 c: 02
surface: 05 i: 006 offset: 0127 unk: 00 verts: 05 boneId: 01 a: 02 b: 01 c: 03
surface: 05 i: 008 offset: 0127 unk: 00 verts: 05 boneId: 01 a: 02 b: 04 c: 00
end surface 5: processed verts: 5
sufrace: 6
<set boneID> 4
[new block] 00 08
surface: 06 i: 004 offset: 0132 unk: 00 verts: 08 boneId: 04 a: 00 b: 01 c: 02
surface: 06 i: 006 offset: 0132 unk: 00 verts: 08 boneId: 04 a: 01 b: 00 c: 03
surface: 06 i: 008 offset: 0132 unk: 00 verts: 08 boneId: 04 a: 00 b: 04 c: 03
surface: 06 i: 010 offset: 0132 unk: 00 verts: 08 boneId: 04 a: 02 b: 04 c: 00
surface: 06 i: 012 offset: 0132 unk: 00 verts: 08 boneId: 04 a: 05 b: 06 c: 07
end surface 6: processed verts: 8
processed verts: 140
uint32_t
get_real_vert_index(uint8_t index, uint32_t vertOffset, uint32_t prevVertOffset,
uint8_t blockType, uint8_t vertCount)
{
if (blockType == 0) {
if (index >= vertCount) {
return vertOffset - (32 - index);
}
else {
return vertOffset + index;
}
}
else
if (blockType == 11) {
if (index < 11) {
return vertOffset - (11 - index);
}
else
if (index <= 21) {
return vertOffset + (index - 11);
}
else {
return prevVertOffset + index;
}
}
else
if (blockType = 22) {
if (index <= 11) {
return prevVertOffset + index;
}
else
if (index < 22) {
return prevVertOffset + (index - 11);
}
else {
return vertOffset + (index - 22);
}
}
return (uint32_t)-1;
}
uint32_t prevVertOffset = 0;
uint32_t vertOffset = 0;
uint8_t vertCount = 0;
uint8_t blockType = 0;
uint8_t boneId = 0;
for (uint16_t value in indicesData) {
if (value & 0x8000) {
uint8_t a = (value & 0x7C00) >> 10;
uint8_t b = (value & 0x03E0) >> 5;
uint8_t c = (value & 0x001F);
uint32_t realA = get_real_vert_index(a, vertOffset, prevVertOffset, blockType, vertCount);
uint32_t realB = get_real_vert_index(b, vertOffset, prevVertOffset, blockType, vertCount);
uint32_t realC = get_real_vert_index(c, vertOffset, prevVertOffset, blockType, vertCount);
someCall(realA, realB, realC, boneId);
}
else
if (value & 0x4000) {
boneId = value & 0xFF;
}
else
if (value & 0x2000) {
prevVertOffset = vertOffset;
vertOffset += vertCount;
vertCount = value & 0x1F;
blockType = (value & 0x03E0) >> 5;
if (vertCount == 0) {
vertCount = 32;
}
}
}