Decompile 3 functions in Source/Resource/Models/ModelResourceV2.cpp, Source/Resource/Models/ModelResource.h, ...

Batch #14636 by secret: 0 byte-identical, 3 confirmed by peer review.

- fn_08020 C3dModelResV2::ReadVersion1: logic confirmed by peer review
- fn_08021 C3dModelResV2::ReadVersion2: logic confirmed by peer review
- fn_08022 C3dModelResV2::ReadVersion3: logic confirmed by peer review

Peer-reviewed-by: Tanke, Toshiro, codeplay
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
This commit is contained in:
ragnarok-clanker 2026-11-07 17:22:36 +00:00
commit adbe1db7e1
4 changed files with 45 additions and 73 deletions

View file

@ -34,10 +34,6 @@ void SampleModelTexture(const ModelTextureChannels& channels, float frame, Model
}
}
struct ModelKeyList1 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
// OFFSET: 0x00541160
// FUNCTION: fn_01728
void ModelKeyList1::Read(CFile& file) {
@ -50,10 +46,6 @@ void ModelKeyList1::Read(CFile& file) {
}
}
struct ModelKeyList2 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
// OFFSET: 0x005411E0
// FUNCTION: fn_01729
void ModelKeyList2::Read(CFile& file) {
@ -66,10 +58,6 @@ void ModelKeyList2::Read(CFile& file) {
}
}
struct ModelKeyList3 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
// OFFSET: 0x00541250
// FUNCTION: fn_01730
void ModelKeyList3::Read(CFile& file) {
@ -82,10 +70,6 @@ void ModelKeyList3::Read(CFile& file) {
}
}
struct ModelKeyList4 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
// OFFSET: 0x00541350
// FUNCTION: fn_01731
void ModelKeyList4::Read(CFile& file) {
@ -98,10 +82,6 @@ void ModelKeyList4::Read(CFile& file) {
}
}
struct ModelTextureChannelMap : ModelTextureChannels {
void Read(CFile& file);
};
// OFFSET: 0x005413D0
// FUNCTION: fn_01732
void ModelTextureChannelMap::Read(CFile& file) {

View file

@ -72,9 +72,6 @@ __forceinline ModelNodeV1::ModelNodeV1() = default;
// INLINED
ModelNodeV1::~ModelNodeV1() = default;
// INLINED
ModelNodeV2::ModelNodeV2() = default;
// INLINED
ModelNodeV2::~ModelNodeV2() = default;

View file

@ -40,6 +40,28 @@ struct ModelTextureKey {
using ModelTextureChannels = std::map<int, std::vector<ModelTextureKey>>;
class CFile;
struct ModelKeyList1 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
struct ModelKeyList2 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
struct ModelKeyList3 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
struct ModelKeyList4 : std::vector<ModelRotationKey> {
void Read(CFile& file);
};
struct ModelTextureChannelMap : ModelTextureChannels {
void Read(CFile& file);
};
static_assert(sizeof(ModelTextureKey) == 8);
struct ModelVolume {
@ -88,12 +110,15 @@ public:
~ModelNodeV2() override;
/* 0058 */ float transform[12];
/* 0088 */ std::vector<ModelRotationKey> scaleKeys;
/* 0094 */ std::vector<ModelRotationKey> rotationKeys;
/* 00A0 */ std::vector<ModelRotationKey> positionKeys;
/* 0088 */ ModelKeyList4 scaleKeys;
/* 0094 */ ModelKeyList3 rotationKeys;
/* 00A0 */ ModelKeyList1 positionKeys;
/* 00AC */ std::map<int, ModelTextureChannels> textureKeys;
};
// INLINED
inline ModelNodeV2::ModelNodeV2() = default;
class C3dModelRes : public CRes {
friend class ModelNode;
public:

View file

@ -10,25 +10,6 @@
#include <algorithm>
#include <cstring>
namespace {
// INLINED
void ReadKeys(CFile& input, std::vector<ModelRotationKey>& keys, bool scale) {
int count = 0;
input.Read(&count, 4);
for (int index = 0; index < count; ++index) {
ModelRotationKey key;
if (scale) {
key = {0, {0, 0, 0, 1}};
}
input.Read(&key, sizeof(key));
keys.push_back(key);
}
}
}
// OFFSET: 0x007555C0
// FUNCTION: fn_07984
C3dModelResV2::C3dModelResV2() : framesPerSecond(0.0f), animationLength(0) {
@ -175,10 +156,13 @@ void C3dModelResV2::ReadVersion1(CFile& input) {
/* 0014 */ std::uint32_t smoothing;
} record;
input.Read(&record, sizeof(record));
std::memcpy(target.vertices, record.vertices, sizeof(target.vertices));
std::memcpy(target.textureVertices, record.textureVertices, sizeof(target.textureVertices));
for (int corner = 0; corner < 3; ++corner) {
target.vertices[corner] = record.vertices[corner];
}
for (int corner = 0; corner < 3; ++corner) {
target.textureVertices[corner] = record.textureVertices[corner];
}
target.texture = record.texture;
target.unknown_000E = record.unknown_000E;
target.twoSided = record.twoSided;
if (target.smoothing.empty()) {
@ -188,9 +172,9 @@ void C3dModelResV2::ReadVersion1(CFile& input) {
std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; });
mesh.CalculateNormals();
ReadKeys(input, node->scaleKeys, false);
ReadKeys(input, node->rotationKeys, true);
ReadKeys(input, node->positionKeys, false);
node->scaleKeys.Read(input);
node->rotationKeys.Read(input);
node->positionKeys.Read(input);
this->nodes.push_back(node);
this->meshes[node->name] = node->mesh.get();
}
@ -307,9 +291,9 @@ void C3dModelResV2::ReadVersion2(CFile& input) {
std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; });
mesh.CalculateNormals();
ReadKeys(input, node->scaleKeys, false);
ReadKeys(input, node->rotationKeys, true);
ReadKeys(input, node->positionKeys, false);
node->scaleKeys.Read(input);
node->rotationKeys.Read(input);
node->positionKeys.Read(input);
this->nodes.push_back(node);
this->meshes[node->name] = node->mesh.get();
}
@ -416,31 +400,17 @@ void C3dModelResV2::ReadVersion3(CFile& input) {
std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; });
mesh.CalculateNormals();
ReadKeys(input, node->scaleKeys, false);
ReadKeys(input, node->rotationKeys, true);
ReadKeys(input, node->positionKeys, false);
node->scaleKeys.Read(input);
node->rotationKeys.Read(input);
node->positionKeys.Read(input);
int textureAnimations = 0;
input.Read(&textureAnimations, 4);
for (int animation = 0; animation < textureAnimations; ++animation) {
int texture = 0;
input.Read(&texture, 4);
ModelTextureChannels channels;
int channelCount = 0;
input.Read(&channelCount, 4);
for (int channel = 0; channel < channelCount; ++channel) {
int id = 0;
int keyCount = 0;
input.Read(&id, 4);
input.Read(&keyCount, 4);
for (int key = 0; key < keyCount; ++key) {
ModelTextureKey value;
input.Read(&value, sizeof(value));
channels[id].push_back(value);
}
}
ModelTextureChannelMap channels;
channels.Read(input);
node->textureKeys[texture] = std::move(channels);
}