feat(model): implement CM2Model::AttachToParent

This commit is contained in:
VDm 2025-05-25 20:33:03 +04:00
parent 03cb7e699e
commit 6780f5061f
5 changed files with 239 additions and 30 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -23,7 +23,7 @@ int32_t Script_SetCharCustomizeFrame(lua_State* L) {
auto frame = CScriptObject::GetScriptObjectByName(name, type);
if (frame) {
CCharacterCreation::SetCharCustomizeFrame(static_cast<CSimpleModel*>(frame));
CCharacterCreation::SetCharCustomizeFrame(static_cast<CSimpleModelFFX*>(frame));
}
return 0;