diff --git a/src/glue/CCharacterCreation.cpp b/src/glue/CCharacterCreation.cpp index 7b77d95..ecc1a8a 100644 --- a/src/glue/CCharacterCreation.cpp +++ b/src/glue/CCharacterCreation.cpp @@ -8,7 +8,7 @@ int32_t CCharacterCreation::m_selectedClassID; int32_t CCharacterCreation::m_existingCharacterIndex; int32_t CCharacterCreation::m_raceIndex; -CSimpleModel* CCharacterCreation::m_charCustomizeFrame; +CSimpleModelFFX* CCharacterCreation::m_charCustomizeFrame; float CCharacterCreation::m_charFacing; uint32_t CCharacterCreation::m_prevSkinIndex; uint32_t CCharacterCreation::m_prevFaceIndex; @@ -66,7 +66,7 @@ void CCharacterCreation::Initialize() { } while (weirdCondition || factionSwitch == 1); } -void CCharacterCreation::SetCharCustomizeFrame(CSimpleModel* frame) { +void CCharacterCreation::SetCharCustomizeFrame(CSimpleModelFFX* frame) { CCharacterCreation::m_charCustomizeFrame = frame; } diff --git a/src/glue/CCharacterCreation.hpp b/src/glue/CCharacterCreation.hpp index 96f2144..2562491 100644 --- a/src/glue/CCharacterCreation.hpp +++ b/src/glue/CCharacterCreation.hpp @@ -27,7 +27,7 @@ class CCharacterCreation { static int32_t m_selectedClassID; static int32_t m_existingCharacterIndex; static int32_t m_raceIndex; - static CSimpleModel* m_charCustomizeFrame; + static CSimpleModelFFX* m_charCustomizeFrame; static float m_charFacing; static uint32_t m_prevSkinIndex; static uint32_t m_prevFaceIndex; @@ -40,7 +40,7 @@ class CCharacterCreation { // Static functions static void Initialize(); - static void SetCharCustomizeFrame(CSimpleModel* frame); + static void SetCharCustomizeFrame(CSimpleModelFFX* frame); static void SetCharCustomizeModel(char const* filename); static void ResetCharCustomizeInfo(); static void GetRandomRaceAndSex(ComponentData* data); diff --git a/src/model/CM2Model.cpp b/src/model/CM2Model.cpp index 85404df..3552c16 100644 --- a/src/model/CM2Model.cpp +++ b/src/model/CM2Model.cpp @@ -24,8 +24,7 @@ CM2Model* CM2Model::AllocModel(uint32_t* heapId) { if (ObjectAlloc(*heapId, &memHandle, &object, 0)) { CM2Model* model = new (object) CM2Model(); - // TODO - // model->uint2E8 = memHandle; + model->m_handle = memHandle; return model; } @@ -587,6 +586,167 @@ void CM2Model::AttachToScene(CM2Scene* scene) { } } +uint16_t CM2Model::AttachToParent(CM2Model* parent, uint32_t attachmentId, const C3Vector* a4, int32_t a5) { + if (this->m_attachParent) { + this->DetachFromParent(); + } + + this->SetAnimating(0); + + uint16_t attachmentIndex = 0xFFFF; + + if (parent->m_loaded) { + if (attachmentId < parent->m_shared->m_data->attachmentIndicesById.Count()) { + attachmentIndex = parent->m_shared->m_data->attachmentIndicesById[attachmentId]; + } + + if (attachmentIndex == 0xFFFF && !a5) { + return attachmentIndex; + } + } + + this->m_attachmentIndex = attachmentIndex; + this->m_attachmentId = attachmentId; + this->m_attachParent = parent; + + if (a5) { + this->f_flags = this->f_flags ^ (this->f_flags ^ (1 << 18)) & 0x40000 | 0x20080; + } else { + this->f_flags = this->f_flags ^ (this->f_flags ^ 0) & 0x40000 | 0x20080; + } + + this->m_attachmentPrev = &parent->m_attachmentBase; + this->m_attachmentNext = parent->m_attachmentBase; + if (parent->m_attachmentBase) { + parent->m_attachmentBase->m_attachmentPrev = &this->m_attachmentNext; + } + parent->m_attachmentBase = this; + + if (!this->m_loaded || !this->m_flag100) { + auto model = parent; + while (parent) { + model->f_flags &= ~0x100u; + model = model->m_attachParent; + } + } + + if (!this->m_flag2) { + auto model = parent; + while (parent) { + model->f_flags &= ~0x200u; + model = model->m_attachParent; + } + } + + if (a4 && this->m_attachParent && this->m_attachParent->m_loaded && this->m_attachmentIndex != 0xFFFF) { + auto transform = parent->GetAttachmentWorldTransform(attachmentId); + + float v12 = sqrt(transform.a0 * transform.a0 + transform.a1 * transform.a1 + transform.a2 * transform.a2); + // WRAP: C44Matrix__AffineInvertInPlace below + if (fabs(v12 - 1.0f) >= 0.00000095367432) { + float v5[3][3]; + v5[0][0] = transform.a0; + v5[0][1] = transform.a1; + v5[0][2] = transform.a2; + v5[1][0] = transform.b0; + v5[1][1] = transform.b1; + v5[1][2] = transform.b2; + v5[2][0] = transform.c0; + v5[2][1] = transform.c1; + v5[2][2] = transform.c2; + + float v8[3][3]; + v8[0][0] = v5[0][0]; + v8[0][1] = v5[1][0]; + v8[0][2] = v5[2][0]; + v8[1][0] = v5[0][1]; + v8[1][1] = v5[1][1]; + v8[1][2] = v5[2][1]; + v8[2][0] = v5[0][2]; + v8[2][1] = v5[1][2]; + v8[2][2] = v5[2][2]; + + C44Matrix matrix; + matrix.a0 = v8[0][0]; + matrix.a1 = v8[0][1]; + matrix.a2 = v8[0][2]; + matrix.a3 = 0.0f; + matrix.b0 = v8[1][0]; + matrix.b1 = v8[1][1]; + matrix.b2 = v8[1][2]; + matrix.b3 = 0.0f; + matrix.c0 = v8[2][0]; + matrix.c1 = v8[2][1]; + matrix.c2 = v8[2][2]; + matrix.c3 = 0.0f; + matrix.d0 = 0.0f; + matrix.d1 = 0.0f; + matrix.d2 = 0.0f; + matrix.d3 = 1.0f; + + matrix.Scale(1.0f / (v12 * v12)); + matrix.Translate(C3Vector(-transform.d0, -transform.d1, -transform.d2)); + transform = matrix; + } else { + float v5[3][3]; + v5[0][0] = transform.a0; + v5[0][1] = transform.a1; + v5[0][2] = transform.a2; + v5[1][0] = transform.b0; + v5[1][1] = transform.b1; + v5[1][2] = transform.b2; + v5[2][0] = transform.c0; + v5[2][1] = transform.c1; + v5[2][2] = transform.c2; + + float v8[3][3]; + v8[0][0] = v5[0][0]; + v8[0][1] = v5[1][0]; + v8[0][2] = v5[2][0]; + v8[1][0] = v5[0][1]; + v8[1][1] = v5[1][1]; + v8[1][2] = v5[2][1]; + v8[2][0] = v5[0][2]; + v8[2][1] = v5[1][2]; + v8[2][2] = v5[2][2]; + + C44Matrix matrix; + matrix.a0 = v8[0][0]; + matrix.a1 = v8[0][1]; + matrix.a2 = v8[0][2]; + matrix.a3 = 0.0f; + matrix.b0 = v8[1][0]; + matrix.b1 = v8[1][1]; + matrix.b2 = v8[1][2]; + matrix.b3 = 0.0f; + matrix.c0 = v8[2][0]; + matrix.c1 = v8[2][1]; + matrix.c2 = v8[2][2]; + matrix.c3 = 0.0f; + matrix.d0 = 0.0f; + matrix.d1 = 0.0f; + matrix.d2 = 0.0f; + matrix.d3 = 1.0f; + + matrix.Translate(C3Vector(-transform.d0, -transform.d1, -transform.d2)); + transform = matrix; + } + + if (!this->m_flag8000) { + this->matrixB4 = C44Matrix(); + } + + transform.Translate(*a4); + + this->matrixB4.d0 = transform.a0; + this->matrixB4.d1 = transform.a1; + this->matrixB4.d2 = transform.a2; + this->m_flag8000 = 1; + } + + ++this->m_refCount; +} + void CM2Model::CancelDeferredSequences(uint32_t boneIndex, bool a3) { // TODO } @@ -595,6 +755,41 @@ void CM2Model::DetachFromScene() { // TODO } +void CM2Model::DetachFromParent() { + // TODO +} + +C44Matrix CM2Model::GetAttachmentWorldTransform(uint32_t attachmentId) { + if (!this->m_loaded) { + this->WaitForLoad(nullptr); + } + + uint16_t attachmentIndex = 0xFFFF; + + auto data = this->m_shared->m_data; + if (attachmentId < data->attachmentIndicesById.Count()) { + attachmentIndex = data->attachmentIndicesById[attachmentId]; + } + + uint16_t boneIndex = 0xFFFF; + if (attachmentIndex < data->attachments.Count()) { + boneIndex = data->attachments[attachmentIndex].boneIndex; + } + + this->Animate(); + + C44Matrix matrix; + + if (attachmentIndex == 0xFFFF) { + matrix = this->m_boneMatrices[0]; + } else { + matrix = this->m_boneMatrices[boneIndex]; + matrix.Translate(data->attachments[attachmentIndex].position); + } + + return matrix * this->m_scene->m_viewInv; +} + void CM2Model::FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint32_t& currentKey, uint32_t& nextKey, float& ratio) { if (!track.sequenceTimes.Count()) { nextKey = 0; diff --git a/src/model/CM2Model.hpp b/src/model/CM2Model.hpp index 1a757fe..08545b2 100644 --- a/src/model/CM2Model.hpp +++ b/src/model/CM2Model.hpp @@ -47,29 +47,34 @@ class CM2Model { uint32_t m_flags = 0; CM2Model** m_scenePrev = nullptr; CM2Model* m_sceneNext = nullptr; - uint32_t m_loaded : 1; - uint32_t m_flag2 : 1; - uint32_t m_flag4 : 1; - uint32_t m_flag8 : 1; - uint32_t m_flag10 : 1; - uint32_t m_flag20 : 1; - uint32_t m_flag40 : 1; - uint32_t m_flag80 : 1; - uint32_t m_flag100 : 1; - uint32_t m_flag200 : 1; - uint32_t m_flag400 : 1; - uint32_t m_flag800 : 1; - uint32_t m_flag1000 : 1; - uint32_t m_flag2000 : 1; - uint32_t m_flag4000 : 1; - uint32_t m_flag8000 : 1; - uint32_t m_flag10000 : 1; - uint32_t m_flag20000 : 1; - uint32_t m_flag40000 : 1; - uint32_t m_flag80000 : 1; - uint32_t m_flag100000 : 1; - uint32_t m_flag200000 : 1; - uint32_t m_flag400000 : 1; + union { + struct { + uint32_t m_loaded : 1; + uint32_t m_flag2 : 1; + uint32_t m_flag4 : 1; + uint32_t m_flag8 : 1; + uint32_t m_flag10 : 1; + uint32_t m_flag20 : 1; + uint32_t m_flag40 : 1; + uint32_t m_flag80 : 1; + uint32_t m_flag100 : 1; + uint32_t m_flag200 : 1; + uint32_t m_flag400 : 1; + uint32_t m_flag800 : 1; + uint32_t m_flag1000 : 1; + uint32_t m_flag2000 : 1; + uint32_t m_flag4000 : 1; + uint32_t m_flag8000 : 1; + uint32_t m_flag10000 : 1; + uint32_t m_flag20000 : 1; + uint32_t m_flag40000 : 1; + uint32_t m_flag80000 : 1; + uint32_t m_flag100000 : 1; + uint32_t m_flag200000 : 1; + uint32_t m_flag400000 : 1; + }; + uint32_t f_flags; + }; CM2Model** m_callbackPrev = nullptr; CM2Model* m_callbackNext = nullptr; void (*m_loadedCallback)(CM2Model*, void*) = nullptr; @@ -82,6 +87,11 @@ class CM2Model { CM2Model** m_animatePrev = nullptr; CM2Model* m_animateNext = nullptr; CM2Model* m_attachParent = nullptr; + uint32_t m_attachmentId; + uint16_t m_attachmentIndex; + CM2Model* m_attachmentBase = nullptr; + CM2Model** m_attachmentPrev = nullptr; + CM2Model* m_attachmentNext = nullptr; uint32_t m_time = 0; CM2Model** m_drawPrev = nullptr; CM2Model* m_drawNext = nullptr; @@ -108,6 +118,7 @@ class CM2Model { void* m_lightingArg = nullptr; M2ModelCamera* m_cameras = nullptr; void* ptr2D0 = nullptr; + uint32_t m_handle = 0; // Member functions CM2Model() @@ -141,8 +152,11 @@ class CM2Model { void AnimateMTSimple(const C44Matrix* view, const C3Vector& a3, const C3Vector& a4, float a5, float a6); 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(); + C44Matrix GetAttachmentWorldTransform(uint32_t attachmentId); void FindKey(M2ModelBoneSeq* sequence, const M2TrackBase& track, uint32_t& currentKey, uint32_t& nextKey, float& ratio); CAaBox& GetBoundingBox(CAaBox& bounds); HCAMERA GetCameraByIndex(uint32_t index); diff --git a/src/ui/ScriptFunctionsCharCreate.cpp b/src/ui/ScriptFunctionsCharCreate.cpp index 75d5be2..f022d1d 100644 --- a/src/ui/ScriptFunctionsCharCreate.cpp +++ b/src/ui/ScriptFunctionsCharCreate.cpp @@ -23,7 +23,7 @@ int32_t Script_SetCharCustomizeFrame(lua_State* L) { auto frame = CScriptObject::GetScriptObjectByName(name, type); if (frame) { - CCharacterCreation::SetCharCustomizeFrame(static_cast(frame)); + CCharacterCreation::SetCharCustomizeFrame(static_cast(frame)); } return 0;