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

Batch #959 by ragnarok-clanker: 0 byte-identical, 12 confirmed by peer review.

- fn_07948 C3dModelRes::Unload: logic confirmed by peer review (already on main)
- fn_07949 C3dModelResV1::Create: logic confirmed by peer review (already on main)
- fn_07982 C3dModelRes::C3dModelRes: logic confirmed by peer review (already on main)
- fn_07995 C3dModelRes::~C3dModelRes: logic confirmed by peer review (already on main)
- fn_07996 ModelNode::~ModelNode: logic confirmed by peer review
- fn_08012 C3dModelRes::FindNode: logic confirmed by peer review (already on main)
- fn_07985 ModelNode::ModelNode: logic confirmed by peer review
- fn_07950 C3dModelResV1::Load: logic confirmed by peer review (already on main)
- fn_07983 C3dModelResV1::C3dModelResV1: logic confirmed by peer review (already on main)
- fn_07984 C3dModelResV2::C3dModelResV2: logic confirmed by peer review (already on main)
- fn_17482 C3dNodeV1::Initialize: logic confirmed by peer review
- fn_17484 C3dNodeV2::Initialize: logic confirmed by peer review

Reviewed-by: ragnarok-clanker
This commit is contained in:
ragnarok-clanker 2026-10-27 08:05:28 +00:00
commit 220df4d318
4 changed files with 78 additions and 43 deletions

View file

@ -42,7 +42,8 @@ void C3dNode::Animate(double) {
// OFFSET: 0x00AB7050 // OFFSET: 0x00AB7050
// FUNCTION: fn_17482 // FUNCTION: fn_17482
void C3dNodeV1::Initialize(const ModelNode& resource) { void C3dNodeV1::Initialize(const ModelNode& base) {
const auto& resource = static_cast<const ModelNodeV1&>(base);
this->name = resource.name; this->name = resource.name;
this->mesh = resource.mesh.get(); this->mesh = resource.mesh.get();
this->textures = resource.textures; this->textures = resource.textures;
@ -80,7 +81,8 @@ void C3dNodeV1::Initialize(const ModelNode& resource) {
// OFFSET: 0x00AB73F0 // OFFSET: 0x00AB73F0
// FUNCTION: fn_17484 // FUNCTION: fn_17484
void C3dNodeV2::Initialize(const ModelNode& resource) { void C3dNodeV2::Initialize(const ModelNode& base) {
const auto& resource = static_cast<const ModelNodeV2&>(base);
this->name = resource.name; this->name = resource.name;
this->mesh = resource.mesh.get(); this->mesh = resource.mesh.get();
std::memcpy(this->resourceTransform.values, resource.transform, sizeof(resource.transform)); std::memcpy(this->resourceTransform.values, resource.transform, sizeof(resource.transform));

View file

@ -9,32 +9,47 @@
#include <cstring> #include <cstring>
// OFFSET: 0x00755630 // OFFSET: 0x00755630
// OFFSET: 0x00750B10
// FUNCTION: fn_07985 // FUNCTION: fn_07985
ModelNode::ModelNode(TextureCache& textures) : model(nullptr), parent(nullptr), alpha(255), m_textures(textures) { ModelNode::ModelNode() : model(nullptr), parent(nullptr), alpha(255) {
} }
// OFFSET: 0x007570F0 // OFFSET: 0x007568E0
// FUNCTION: fn_07996 // FUNCTION: fn_07996
ModelNode::~ModelNode() { ModelNode::~ModelNode() {
for (CTexture* texture : this->textures) { for (CTexture* texture : this->textures) {
if (texture) { if (texture) {
texture->Release(); texture->Release();
this->m_textures.Remove(texture); this->model->m_context->textures.Remove(texture);
} }
} }
this->textures.clear();
this->mesh.reset();
this->children.clear();
} }
// INLINED
ModelNodeV1::ModelNodeV1() = default;
// INLINED
ModelNodeV1::~ModelNodeV1() = default;
// INLINED
ModelNodeV2::ModelNodeV2() = default;
// INLINED
ModelNodeV2::~ModelNodeV2() = default;
// OFFSET: 0x007553E0 // OFFSET: 0x007553E0
// FUNCTION: fn_07982 // FUNCTION: fn_07982
C3dModelRes::C3dModelRes(ModelResourceContext& context) : major(0), shade(0), alpha(255), m_context(&context) { C3dModelRes::C3dModelRes(ModelResourceContext& context) : major(0), shade(0), alpha(255), m_context(&context) {
} }
// OFFSET: 0x00757090 // OFFSET: 0x007567B0
// FUNCTION: fn_07995 // FUNCTION: fn_07995
C3dModelRes::~C3dModelRes() = default; C3dModelRes::~C3dModelRes() = default;
// OFFSET: 0x00750A70 // OFFSET: 0x00755560
// FUNCTION: fn_07983 // FUNCTION: fn_07983
C3dModelResV1::C3dModelResV1(ModelResourceContext& context) : C3dModelRes(context), animationLength(0) { C3dModelResV1::C3dModelResV1(ModelResourceContext& context) : C3dModelRes(context), animationLength(0) {
} }
@ -81,7 +96,7 @@ void C3dModelRes::Unload() {
// INLINED // INLINED
inline void C3dModelResV1::ReadNode(ResourceByteReader& input, unsigned minor, const std::vector<std::string>& textureNames) { inline void C3dModelResV1::ReadNode(ResourceByteReader& input, unsigned minor, const std::vector<std::string>& textureNames) {
auto node = std::make_unique<ModelNode>(this->m_context->textures); auto node = std::make_unique<ModelNodeV1>();
node->model = this; node->model = this;
node->alpha = this->alpha; node->alpha = this->alpha;
char field[40]{}; char field[40]{};

View file

@ -50,33 +50,44 @@ struct ModelVolume {
class ModelNode { class ModelNode {
public: public:
explicit ModelNode(TextureCache& textures); ModelNode();
~ModelNode(); virtual ~ModelNode();
ModelNode(const ModelNode&) = delete; ModelNode(const ModelNode&) = delete;
ModelNode& operator=(const ModelNode&) = delete; ModelNode& operator=(const ModelNode&) = delete;
std::string name; /* 0004 */ std::string name;
std::string parentName; /* 001C */ std::string parentName;
C3dModelRes* model; /* 0034 */ C3dModelRes* model;
ModelNode* parent; /* 0038 */ ModelNode* parent;
std::list<ModelNode*> children; /* 003C */ std::list<ModelNode*> children;
std::vector<class CTexture*> textures; /* 0044 */ std::vector<class CTexture*> textures;
std::unique_ptr<ModelMesh> mesh; /* 0050 */ std::unique_ptr<ModelMesh> mesh;
unsigned char alpha; /* 0054 */ unsigned char alpha;
unsigned char unknown_0055[3]; };
float position[3];
float scale[3];
float angle;
float axis[3];
float transform[12];
std::vector<ModelPositionKey> legacyPositionKeys;
std::vector<ModelRotationKey> rotationKeys;
std::vector<ModelRotationKey> scaleKeys;
std::vector<ModelRotationKey> positionKeys;
std::map<int, ModelTextureChannels> textureKeys;
private: class ModelNodeV1 : public ModelNode {
TextureCache& m_textures; public:
ModelNodeV1();
~ModelNodeV1() override;
/* 0058 */ float position[3];
/* 0064 */ float axis[3];
/* 0070 */ float angle;
/* 0074 */ float scale[3];
/* 0080 */ std::vector<ModelPositionKey> legacyPositionKeys;
/* 008C */ std::vector<ModelRotationKey> rotationKeys;
};
class ModelNodeV2 : public ModelNode {
public:
ModelNodeV2();
~ModelNodeV2() override;
/* 0058 */ float transform[12];
/* 0088 */ std::vector<ModelRotationKey> scaleKeys;
/* 0094 */ std::vector<ModelRotationKey> rotationKeys;
/* 00A0 */ std::vector<ModelRotationKey> positionKeys;
/* 00AC */ std::map<int, ModelTextureChannels> textureKeys;
}; };
struct ModelResourceContext { struct ModelResourceContext {
@ -86,6 +97,7 @@ struct ModelResourceContext {
}; };
class C3dModelRes : public CRes { class C3dModelRes : public CRes {
friend class ModelNode;
public: public:
explicit C3dModelRes(ModelResourceContext& context); explicit C3dModelRes(ModelResourceContext& context);
~C3dModelRes() override; ~C3dModelRes() override;
@ -93,15 +105,15 @@ public:
ModelNode* FindNode(const char* name) const; ModelNode* FindNode(const char* name) const;
void RegisterMovies(class BinkMovies& movies, const float* position) const; void RegisterMovies(class BinkMovies& movies, const float* position) const;
int major; /* 0110 */ int major;
std::list<ModelNode*> nodes; /* 0114 */ std::list<ModelNode*> nodes;
std::list<std::string> rootNames; /* 011C */ std::list<std::string> rootNames;
std::map<std::string, ModelMesh*> meshes; /* 0124 */ std::map<std::string, ModelMesh*> meshes;
std::list<ModelVolume*> volumes; /* 012C */ std::list<ModelVolume*> volumes;
std::string sourceName; /* 0134 */ std::string sourceName;
int shade; /* 014C */ int shade;
unsigned char alpha; /* 0150 */ unsigned char alpha;
std::list<std::string> movieNames; /* 0154 */ std::list<std::string> movieNames;
protected: protected:
ModelResourceContext* m_context; ModelResourceContext* m_context;
@ -139,4 +151,10 @@ static_assert(sizeof(ModelScaleKey) == 32);
static_assert(sizeof(ModelRotationKey) == 20); static_assert(sizeof(ModelRotationKey) == 20);
static_assert(sizeof(ModelVolume) == 232); static_assert(sizeof(ModelVolume) == 232);
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(ModelNode) == 0x58);
static_assert(sizeof(ModelNodeV1) == 0x98);
static_assert(sizeof(ModelNodeV2) == 0xB4);
#endif
#endif #endif

View file

@ -36,7 +36,7 @@ namespace {
} }
} }
// OFFSET: 0x00751ED0 // OFFSET: 0x007555C0
// FUNCTION: fn_07984 // FUNCTION: fn_07984
C3dModelResV2::C3dModelResV2(ModelResourceContext& context) : C3dModelRes(context), framesPerSecond(0.0f), animationLength(0) { C3dModelResV2::C3dModelResV2(ModelResourceContext& context) : C3dModelRes(context), framesPerSecond(0.0f), animationLength(0) {
} }
@ -92,7 +92,7 @@ bool C3dModelResV2::Load(const char* name) {
// INLINED // INLINED
inline void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const std::vector<std::string>& textureNames) { inline void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const std::vector<std::string>& textureNames) {
auto node = std::make_unique<ModelNode>(this->m_context->textures); auto node = std::make_unique<ModelNodeV2>();
node->model = this; node->model = this;
node->mesh = std::make_unique<ModelMesh>(); node->mesh = std::make_unique<ModelMesh>();
node->name = ReadName(input); node->name = ReadName(input);