From 29994c118157bf583eab7671cd7d194eec996c2a Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 25 May 2025 23:07:13 +0400 Subject: [PATCH] feat(model): first implementation of character rendering --- src/glue/CCharacterSelection.cpp | 14 +++++ src/model/CM2Model.cpp | 96 +++++++++++++++++++++++++++++--- src/model/CM2Model.hpp | 3 + 3 files changed, 106 insertions(+), 7 deletions(-) diff --git a/src/glue/CCharacterSelection.cpp b/src/glue/CCharacterSelection.cpp index b6fcc63..6e98e93 100644 --- a/src/glue/CCharacterSelection.cpp +++ b/src/glue/CCharacterSelection.cpp @@ -77,11 +77,25 @@ void CCharacterSelection::ShowCharacter() { } // TODO + if (CCharacterSelection::m_modelFrame) { + auto model = CCharacterSelection::m_modelFrame->m_model; + if (model) { + //model->DetachAllChildrenById(0); + //model->DetachAllChildrenById(1); + } + } + CCharacterSelection::m_charFacing = 0.0; auto& character = CCharacterSelection::s_characterList[index]; if (character.m_characterModel) { + if (!character.m_characterModel->m_attachParent && CCharacterSelection::m_modelFrame && CCharacterSelection::m_modelFrame->m_model) { + character.m_characterModel->SetVisible(1); + character.m_characterModel->AttachToParent(CCharacterSelection::m_modelFrame->m_model, 0, nullptr, 0); + character.m_characterModel->SetVisible(1); + } + // TODO return; } diff --git a/src/model/CM2Model.cpp b/src/model/CM2Model.cpp index 3552c16..d04c95b 100644 --- a/src/model/CM2Model.cpp +++ b/src/model/CM2Model.cpp @@ -75,6 +75,10 @@ uint16_t CM2Model::Sub8260C0(M2Data* data, uint32_t sequenceId, int32_t a3) { return -1; } +CM2Model::~CM2Model() { + +} + void CM2Model::Animate() { // TODO } @@ -475,6 +479,10 @@ void CM2Model::AnimateMT(const C44Matrix* view, const C3Vector& a3, const C3Vect } } + if (this->m_attachmentBase) { + this->AnimateAttachmentsMT(); + } + // TODO } @@ -482,6 +490,25 @@ void CM2Model::AnimateMTSimple(const C44Matrix* view, const C3Vector& a3, const // TODO } +void CM2Model::AnimateAttachmentsMT() { + // TODO: Proper implementation + + for (auto child = this->m_attachmentBase; child; child = child->m_attachmentNext) { + child->m_flag80 = 1; + child->m_flag8 = 1; + + if (child->m_attachmentIndex == 0xFFFF) { + child->AnimateMT(&this->m_boneMatrices[0], this->m_currentDiffuse, this->m_currentEmissive, 1.0f, 1.0f); + } else { + auto data = &this->m_shared->m_data->attachments[child->m_attachmentIndex]; + C44Matrix matrix = this->m_boneMatrices[data->boneIndex]; + matrix.Translate(data->position); + child->AnimateMT(&matrix, this->m_currentDiffuse, this->m_currentEmissive, 1.0f, 1.0f); + } + + } +} + void CM2Model::AnimateST() { if (!this->m_loaded) { return; @@ -558,6 +585,11 @@ void CM2Model::AnimateST() { } // TODO + + for (auto child = this->m_attachmentBase; child; child = child->m_attachmentNext) { + // TODO: v43 + child->AnimateST(); + } } void CM2Model::AttachToScene(CM2Scene* scene) { @@ -624,7 +656,7 @@ uint16_t CM2Model::AttachToParent(CM2Model* parent, uint32_t attachmentId, const if (!this->m_loaded || !this->m_flag100) { auto model = parent; - while (parent) { + while (model) { model->f_flags &= ~0x100u; model = model->m_attachParent; } @@ -632,7 +664,7 @@ uint16_t CM2Model::AttachToParent(CM2Model* parent, uint32_t attachmentId, const if (!this->m_flag2) { auto model = parent; - while (parent) { + while (model) { model->f_flags &= ~0x200u; model = model->m_attachParent; } @@ -756,7 +788,58 @@ void CM2Model::DetachFromScene() { } void CM2Model::DetachFromParent() { - // TODO + if (this->m_attachmentPrev) { + *this->m_attachmentPrev = this->m_attachmentNext; + } + + if (this->m_attachmentNext) { + this->m_attachmentNext->m_attachmentPrev = this->m_attachmentPrev; + } + + this->f_flags &= ~0x40000u; + this->m_attachmentPrev = nullptr; + this->m_attachmentNext = nullptr; + this->m_attachParent = nullptr; + this->m_attachmentId = static_cast(-1); + // this->dword174 = 0; + if (--this->m_refCount == 0) { + this->~CM2Model(); + // TODO: ObjectFree + } +} + +void CM2Model::DetachAllChildrenById(uint32_t id) { + CM2Model* attachmentNext = nullptr; + + auto attachmentBase = this->m_attachmentBase; + if (attachmentBase) { + do { + attachmentNext = attachmentBase->m_attachmentNext; + auto v8 = attachmentNext; + if (attachmentBase->m_attachmentId == id) { + auto attachmentPrev = attachmentBase->m_attachmentPrev; + if (attachmentPrev) { + *attachmentPrev = attachmentBase->m_attachmentNext; + } + auto v5 = attachmentBase->m_attachmentNext; + if (v5) { + v5->m_attachmentPrev = attachmentBase->m_attachmentPrev; + } + attachmentBase->f_flags &= ~0x40000u; + attachmentBase->m_attachmentPrev = 0; + attachmentBase->m_attachmentNext = 0; + attachmentBase->m_attachParent = 0; + attachmentBase->m_attachmentId = -1; + // attachmentBase->dword174 = 0; + if (--attachmentBase->m_refCount == 0) { + attachmentBase->~CM2Model(); + // ObjectFree(*v7, attachmentBase->m_handle); + attachmentNext = v8; + } + } + attachmentBase = attachmentNext; + } while (attachmentNext); + } } C44Matrix CM2Model::GetAttachmentWorldTransform(uint32_t attachmentId) { @@ -1627,10 +1710,9 @@ void CM2Model::SetupLighting() { this->m_lighting.CameraSpace(); } - // TODO - // for (auto model = this->model58; model; model = model->model60) { - // model->SetupLighting(); - // } + for (auto model = this->m_attachmentBase; model; model = model->m_attachmentNext) { + model->SetupLighting(); + } } void CM2Model::SetVisible(int32_t visible) { diff --git a/src/model/CM2Model.hpp b/src/model/CM2Model.hpp index 08545b2..990a935 100644 --- a/src/model/CM2Model.hpp +++ b/src/model/CM2Model.hpp @@ -146,16 +146,19 @@ class CM2Model { , m_flag200000(0) , m_flag400000(0) {}; + ~CM2Model(); void Animate(); void AnimateCamerasST(); void AnimateMT(const C44Matrix* view, const C3Vector& a3, const C3Vector& a4, float a5, float a6); void AnimateMTSimple(const C44Matrix* view, const C3Vector& a3, const C3Vector& a4, float a5, float a6); + void AnimateAttachmentsMT(); void AnimateST(); void AttachToScene(CM2Scene* scene); uint16_t AttachToParent(CM2Model* parent, uint32_t attachmentId, const C3Vector* a4, int32_t a5); void CancelDeferredSequences(uint32_t boneIndex, bool a3); void DetachFromScene(); void DetachFromParent(); + void DetachAllChildrenById(uint32_t id); C44Matrix GetAttachmentWorldTransform(uint32_t attachmentId); void FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint32_t& currentKey, uint32_t& nextKey, float& ratio); CAaBox& GetBoundingBox(CAaBox& bounds);