Skip to content

Commit e9caff5

Browse files
refactor: remove redundant header checks in chunk parsers and improve skeletal mesh weight and bone ID logic
1 parent 202bb90 commit e9caff5

2 files changed

Lines changed: 54 additions & 23 deletions

File tree

‎src/Loader/GeometryDecoder.cpp‎

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -671,13 +671,13 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
671671
size_t c = rootBody;
672672
while (c + 12 <= rootEnd) {
673673
const uint32_t ct = ru32(c), cs = ru32(c + 4);
674-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > rootEnd)
674+
if (cs == 0 || c + 12 + cs > rootEnd)
675675
break;
676676
if (ct == 0x1A) { // GeometryList -> Struct, then Geometry chunks
677677
size_t g = c + 12;
678678
while (g + 12 <= c + 12 + cs) {
679679
const uint32_t gt = ru32(g), gs = ru32(g + 4);
680-
if (ru32(g + 8) != 0x1C020065 || gs == 0 || g + 12 + gs > c + 12 + cs)
680+
if (gs == 0 || g + 12 + gs > c + 12 + cs)
681681
break;
682682
if (gt == 0x0F)
683683
collectFrom(g + 12, g + 12 + gs);
@@ -782,7 +782,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
782782
bool hasSkin = false;
783783
for (size_t c = extBegin; c + 12 <= extEnd;) {
784784
const uint32_t ct = ru32(c), cs = ru32(c + 4);
785-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > extEnd)
785+
if (cs == 0 || c + 12 + cs > extEnd)
786786
break;
787787
if (ct == 0x050E) { binMesh = c + 12; binMeshEnd = c + 12 + cs; }
788788
else if (ct == 0x0510) { native = c + 12; nativeEnd = c + 12 + cs; }
@@ -875,11 +875,21 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
875875

876876
std::vector<uint8_t> boneIds;
877877
std::vector<float> boneWeights;
878-
if (hasSkin && meshType == 0 && vifEnd + numIdx * 16 <= blockEnd) {
878+
if (hasSkin) {
879+
if (meshType != 0) {
880+
std::fprintf(stderr, "Skipping weights: meshType is %u, not 0\n", meshType);
881+
} else if (vifEnd + numIdx * 16 > blockEnd) {
882+
std::fprintf(stderr, "Skipping weights: vifEnd + numIdx*16 (%zu + %u) > blockEnd (%zu)\n", vifEnd, numIdx*16, blockEnd);
883+
}
884+
}
885+
886+
size_t weightRecords = (blockEnd > vifEnd) ? (blockEnd - vifEnd) / 16 : 0;
887+
888+
if (hasSkin && meshType == 0 && weightRecords > 0) {
879889
size_t wp = vifEnd;
880-
boneIds.resize(numIdx * 4);
881-
boneWeights.resize(numIdx * 4);
882-
for (uint32_t v = 0; v < numIdx; ++v) {
890+
boneIds.resize(weightRecords * 4);
891+
boneWeights.resize(weightRecords * 4);
892+
for (size_t v = 0; v < weightRecords; ++v) {
883893
for (int w = 0; w < 4; ++w) {
884894
// The byte is the matrix's address in VU memory. A bone
885895
// matrix spans four quadwords, so dividing by four gives the
@@ -917,7 +927,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
917927
if (hasSkin && meshType == 0 && !boneWeights.empty()) {
918928
for (size_t v = 0; v < rawVerts.size(); ++v) {
919929
const size_t wi = base + v;
920-
if (wi >= numIdx) break;
930+
if (wi >= boneWeights.size() / 4) break;
921931
for (int w = 0; w < 4; ++w) {
922932
rawVerts[v].boneIds[w] = boneIds[wi * 4 + w];
923933
rawVerts[v].boneWeights[w] = boneWeights[wi * 4 + w];
@@ -985,7 +995,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
985995
size_t st = 0, stEnd = 0;
986996
for (size_t c = a; c + 12 <= b;) {
987997
const uint32_t ct = ru32(c), cs = ru32(c + 4);
988-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > b)
998+
if (cs == 0 || c + 12 + cs > b)
989999
break;
9901000
if (ct == 0x0001) { st = c + 12; stEnd = c + 12 + cs; break; }
9911001
c += 12 + cs;
@@ -1071,7 +1081,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
10711081
bool sawNative = false;
10721082
for (size_t c = a; c + 12 <= b;) {
10731083
const uint32_t ct = ru32(c), cs = ru32(c + 4);
1074-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > b)
1084+
if (cs == 0 || c + 12 + cs > b)
10751085
break;
10761086
if (ct == 0x0003) {
10771087
for (size_t x = c + 12; x + 12 <= c + 12 + cs;) {
@@ -1092,7 +1102,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
10921102
}
10931103
for (size_t c = a; c + 12 <= b;) {
10941104
const uint32_t ct = ru32(c), cs = ru32(c + 4);
1095-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > b)
1105+
if (cs == 0 || c + 12 + cs > b)
10961106
break;
10971107
if (ct == 0x0003)
10981108
buildFromExtension(c + 12, c + 12 + cs, (int)si, localMats, localCols, localBlend);
@@ -1161,7 +1171,7 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
11611171
std::map<uint32_t, uint32_t> geomFrame;
11621172
for (size_t c = rootBody; c + 12 <= rootEnd;) {
11631173
const uint32_t ct = ru32(c), cs = ru32(c + 4);
1164-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > rootEnd)
1174+
if (cs == 0 || c + 12 + cs > rootEnd)
11651175
break;
11661176
if (ct == 0x0014 && ru32(c + 12) == 0x01)
11671177
geomFrame[ru32(c + 28)] = ru32(c + 24); // struct: frameIdx, geomIdx
@@ -1171,20 +1181,20 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
11711181
uint32_t geomIndex = 0;
11721182
for (size_t c = rootBody; c + 12 <= rootEnd;) {
11731183
const uint32_t ct = ru32(c), cs = ru32(c + 4);
1174-
if (ru32(c + 8) != 0x1C020065 || cs == 0 || c + 12 + cs > rootEnd)
1184+
if (cs == 0 || c + 12 + cs > rootEnd)
11751185
break;
11761186
if (ct == 0x001A) {
11771187
for (size_t g = c + 12; g + 12 <= c + 12 + cs;) {
11781188
const uint32_t gt = ru32(g), gs = ru32(g + 4);
1179-
if (ru32(g + 8) != 0x1C020065 || gs == 0 || g + 12 + gs > c + 12 + cs)
1189+
if (gs == 0 || g + 12 + gs > c + 12 + cs)
11801190
break;
11811191
if (gt == 0x000F) {
11821192
std::vector<std::string> geomMats;
11831193
std::vector<glm::vec4> geomCols;
11841194
std::vector<uint32_t> geomBlend;
11851195
for (size_t gc = g + 12; gc + 12 <= g + 12 + gs;) {
11861196
const uint32_t gct = ru32(gc), gcs = ru32(gc + 4);
1187-
if (ru32(gc + 8) != 0x1C020065 || gcs == 0 || gc + 12 + gcs > g + 12 + gs)
1197+
if (gcs == 0 || gc + 12 + gcs > g + 12 + gs)
11881198
break;
11891199
if (gct == 0x08) {
11901200
geomMats = parseMaterialList(gc);
@@ -1216,19 +1226,39 @@ void DecodeRenderWareGeometry(const std::string& name, const uint8_t* payload, s
12161226
if (cl && !cl->skeleton.bones.empty()) {
12171227
for (size_t gx = g + 12; gx + 12 <= g + 12 + gs;) {
12181228
const uint32_t xt = ru32(gx), xs = ru32(gx + 4);
1219-
if (ru32(gx + 8) != 0x1C020065 || xs == 0 || gx + 12 + xs > g + 12 + gs)
1229+
if (xs == 0 || gx + 12 + xs > g + 12 + gs)
12201230
break;
12211231
if (xt == 0x03) {
12221232
for (size_t sk = gx + 12; sk + 12 <= gx + 12 + xs;) {
12231233
const uint32_t st = ru32(sk), ss = ru32(sk + 4);
12241234
if (ss == 0 || sk + 12 + ss > gx + 12 + xs) break;
1225-
if (st == 0x0116 && ss > 24 && ru32(sk + 12) == 0x01) {
1226-
const size_t base = sk + 24; // past inner Struct header
1227-
const uint8_t used = payload[base + 5];
1228-
if (used == 1) {
1229-
const int want = payload[base + 8]; // usedBoneIds[0]
1230-
for (size_t b = 0; b < cl->skeleton.bones.size(); b++)
1231-
if (cl->skeleton.bones[b].trackIndex == want) { fi = (int)b; break; }
1235+
if (st == 0x0116 && ss > 4) {
1236+
if (ru32(sk + 12) == 0x01 && ss > 24) {
1237+
const size_t base = sk + 24; // past inner Struct header
1238+
const uint8_t used = payload[base + 5];
1239+
if (used == 1) {
1240+
const int want = payload[base + 8]; // usedBoneIds[0]
1241+
for (size_t b = 0; b < cl->skeleton.bones.size(); b++)
1242+
if (cl->skeleton.bones[b].trackIndex == want) { fi = (int)b; break; }
1243+
}
1244+
} else {
1245+
// Custom Climax format: raw bone IDs directly in the chunk.
1246+
// Search the first few bytes for a non-zero bone ID.
1247+
int want = -1;
1248+
for (size_t i = 0; i < 32 && i + 24 < ss; ++i) {
1249+
if (payload[sk + 24 + i] != 0) {
1250+
want = payload[sk + 24 + i];
1251+
break;
1252+
}
1253+
}
1254+
if (want != -1) {
1255+
for (size_t b = 0; b < cl->skeleton.bones.size(); b++) {
1256+
if (cl->skeleton.bones[b].trackIndex == want) {
1257+
fi = (int)b;
1258+
break;
1259+
}
1260+
}
1261+
}
12321262
}
12331263
}
12341264
sk += 12 + ss;

‎src/main.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ void main(){
772772
bool mouse_captured = false;
773773
Uint32 last_tick = SDL_GetTicks();
774774

775+
775776
bool run = true;
776777
while (run) {
777778
Uint32 now = SDL_GetTicks();

0 commit comments

Comments
 (0)