From 667ea3ff82041a309e8b92480a8c28aee64690c8 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 25 Dec 2024 14:05:28 -0700 Subject: [PATCH] Various matches with BETA functions (#1281) * Match functions to BETA * Improve `Matrix4::FromQuaternion` * Improve `Matrix4::ToQuaternion` match * Fix bug that was fixed in retail * Match `Vector4::NormalizeQuaternion` --- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 31 ++++++--- .../legoomni/src/video/legoanimpresenter.cpp | 2 +- LEGO1/library_msvc.h | 3 + LEGO1/mxgeometry/mxgeometry3d.h | 16 ++--- LEGO1/realtime/matrix.h | 69 ++++++++++--------- LEGO1/realtime/vector.h | 34 +++++---- 6 files changed, 85 insertions(+), 70 deletions(-) diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index ab46617607..bdec74e460 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -30,6 +30,7 @@ DECOMP_SIZE_ASSERT(Matrix4, 0x08) DECOMP_SIZE_ASSERT(MxMatrix, 0x48) // FUNCTION: LEGO1 0x10001e60 +// FUNCTION: BETA10 0x1002a0d0 Helicopter::Helicopter() { m_maxLinearVel = 60; @@ -43,6 +44,7 @@ Helicopter::~Helicopter() } // FUNCTION: LEGO1 0x100032c0 +// FUNCTION: BETA10 0x1002a16d MxResult Helicopter::Create(MxDSAction& p_dsAction) { MxResult result = IslePathActor::Create(p_dsAction); @@ -52,6 +54,8 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction) ((Act3*) m_world)->SetHelicopter(this); } + assert(m_world); + if (m_world != NULL) { m_world->Add(this); } @@ -61,6 +65,7 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction) } // FUNCTION: LEGO1 0x10003320 +// FUNCTION: BETA10 0x1002a240 void Helicopter::CreateState() { m_state = (HelicopterState*) GameState()->GetState("HelicopterState"); @@ -70,8 +75,11 @@ void Helicopter::CreateState() } // FUNCTION: LEGO1 0x10003360 +// FUNCTION: BETA10 0x1002a29a void Helicopter::Exit() { + assert(UserActor() == this); + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { SpawnPlayer( LegoGameState::e_unk40, @@ -110,6 +118,7 @@ void Helicopter::Exit() } // FUNCTION: LEGO1 0x10003480 +// FUNCTION: BETA10 0x1002a3db MxLong Helicopter::HandleClick() { if (!FUN_1003ef60()) { @@ -118,6 +127,7 @@ MxLong Helicopter::HandleClick() if (!m_world) { m_world = CurrentWorld(); + assert(m_world); } AnimationManager()->FUN_1005f6d0(FALSE); @@ -163,6 +173,8 @@ MxLong Helicopter::HandleClick() MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; + + assert(m_world); MxAtomId script; switch (GameState()->GetCurrentAct()) { @@ -199,9 +211,10 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) break; } - Act1State* state = (Act1State*) GameState()->GetState("Act1State"); + Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); + assert(act1State); if (m_state->m_unk0x08 == 0) { - state->m_unk0x018 = 4; + act1State->m_unk0x018 = 4; m_state->m_unk0x08 = 1; m_world->RemoveActor(this); InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterTakeOff_Anim, NULL); @@ -303,9 +316,9 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param) switch (m_state->m_unk0x08) { case 1: { if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { - Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); - assert(act1state); - act1state->m_unk0x018 = 4; + Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); + assert(act1State); + act1State->m_unk0x018 = 4; SpawnPlayer( LegoGameState::e_unk42, TRUE, @@ -344,9 +357,9 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param) m_world->GetCameraController()->SetWorldTransform(at, dir, up); if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { - Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); - assert(act1state); - act1state->m_unk0x018 = 0; + Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); + assert(act1State); + act1State->m_unk0x018 = 0; SpawnPlayer( LegoGameState::e_unk41, TRUE, @@ -423,7 +436,7 @@ void Helicopter::Animate(float p_time) ((Act3*) m_world)->FUN_10073430(); } - LegoPathActor::m_actorState = c_disabled; + SetActorState(c_disabled); } } else { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 9df19e513e..6c698bcf2b 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -716,7 +716,7 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi) for (i = 1; i <= m_roiMapSize; i++) { if (m_roiMap[i] == p_roi) { - if (local5c[i].Unknown(local58) != SUCCESS) { + if (local5c[i].BETA_1005a590(local58) != SUCCESS) { goto done; } diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 34f6941cb4..38e19a2964 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -675,6 +675,9 @@ // LIBRARY: BETA10 0x100f9a50 // _sin +// LIBRARY: BETA10 0x100f9a5a +// _cos + // LIBRARY: BETA10 0x100f95d0 // _sqrt diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 309c430b7c..1b41d03e5c 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -164,9 +164,8 @@ inline int UnknownMx4DPointFloat::BETA_1004aaa0(Matrix4& p_matrix, float p_f) if (FUN_100040a0(v, p_f) == 0) { return p_matrix.FromQuaternion(v); } - else { - return -1; - } + + return -1; } // FUNCTION: LEGO1 0x10004520 @@ -201,12 +200,14 @@ inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f) p_v[3] = (float) ((1.0 - p_f) * acos((double) p_v[3]) * 2.0); return p_v.NormalizeQuaternion(); } - else if (m_unk0x30 == c_bit2) { + + if (m_unk0x30 == c_bit2) { p_v = m_unk0x18; p_v[3] = (float) (p_f * acos((double) p_v[3]) * 2.0); return p_v.NormalizeQuaternion(); } - else if (m_unk0x30 == (c_bit1 | c_bit2)) { + + if (m_unk0x30 == (c_bit1 | c_bit2)) { int i; double d1 = p_v.Dot(m_unk0x00, m_unk0x18); double a; @@ -243,9 +244,8 @@ inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f) return 0; } - else { - return -1; - } + + return -1; } #endif // MXGEOMETRY3D_H diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 2f52ce7195..8704d739ff 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -179,7 +179,7 @@ class Matrix4 { } } - inline int Unknown(Matrix4& p_mat); + inline int BETA_1005a590(Matrix4& p_mat); // FUNCTION: LEGO1 0x1006b500 void Swap(int p_d1, int p_d2) @@ -202,9 +202,11 @@ class Matrix4 { // FUNCTION: BETA10 0x100101c0 inline void Matrix4::ToQuaternion(Vector4& p_outQuat) { - float trace = m_data[0][0] + m_data[1][1] + m_data[2][2]; - if (trace > 0) { - trace = (float) sqrt(trace + 1.0); + float trace; + float localc = m_data[0][0] + m_data[1][1] + m_data[2][2]; + + if (localc > 0) { + trace = (float) sqrt(localc + 1.0); p_outQuat[3] = trace * 0.5f; trace = 0.5f / trace; p_outQuat[0] = (m_data[2][1] - m_data[1][2]) * trace; @@ -212,7 +214,6 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat) p_outQuat[2] = (m_data[1][0] - m_data[0][1]) * trace; } else { - // GLOBAL: LEGO1 0x100d4090 static int rotateIndex[] = {1, 2, 0}; @@ -228,8 +229,7 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat) int next = rotateIndex[largest]; int nextNext = rotateIndex[next]; - float trace = - (float) (sqrt(*Element(largest, largest) - (*Element(nextNext, nextNext) + *Element(next, next)) + 1.0)); + trace = (float) sqrt(*Element(largest, largest) - (*Element(nextNext, nextNext) + *Element(next, next)) + 1.0); p_outQuat[largest] = trace * 0.5f; trace = 0.5f / trace; @@ -244,38 +244,38 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat) // FUNCTION: BETA10 0x10010550 inline int Matrix4::FromQuaternion(const Vector4& p_vec) { - float len = p_vec.LenSquared(); + float local14 = p_vec.LenSquared(); - if (len > 0.0f) { - float v7 = 2.0f / len; + if (local14 > 0.0f) { + local14 = 2.0f / local14; - float v9 = p_vec[0] * v7; - float v11 = p_vec[1] * v7; - float v12 = p_vec[2] * v7; + float local24 = p_vec[0] * local14; + float local34 = p_vec[1] * local14; + float local10 = p_vec[2] * local14; - float v13 = p_vec[3] * v9; - float v14 = p_vec[3] * v11; - float v16 = p_vec[3] * v12; + float local28 = p_vec[3] * local24; + float local2c = p_vec[3] * local34; + float local30 = p_vec[3] * local10; - float v17 = p_vec[0] * v9; - float v22 = p_vec[0] * v11; - float v23 = p_vec[0] * v12; + float local38 = p_vec[0] * local24; + float local8 = p_vec[0] * local34; + float localc = p_vec[0] * local10; - float v18 = p_vec[1] * v11; - float v24 = p_vec[1] * v12; - float v19 = p_vec[2] * v12; + float local18 = p_vec[1] * local34; + float local1c = p_vec[1] * local10; + float local20 = p_vec[2] * local10; - m_data[0][0] = 1.0f - (v18 + v19); - m_data[1][0] = v22 + v16; - m_data[2][0] = v23 - v14; + m_data[0][0] = 1.0f - (local18 + local20); + m_data[1][0] = local8 + local30; + m_data[2][0] = localc - local2c; - m_data[0][1] = v22 - v16; - m_data[1][1] = 1.0f - (v17 + v19); - m_data[2][1] = v24 + v13; + m_data[0][1] = local8 - local30; + m_data[1][1] = 1.0f - (local38 + local20); + m_data[2][1] = local1c + local28; - m_data[0][2] = v14 + v23; - m_data[1][2] = v24 - v13; - m_data[2][2] = 1.0f - (v18 + v17); + m_data[0][2] = local2c + localc; + m_data[1][2] = local1c - local28; + m_data[2][2] = 1.0f - (local18 + local38); m_data[3][0] = 0.0f; m_data[3][1] = 0.0f; @@ -287,12 +287,13 @@ inline int Matrix4::FromQuaternion(const Vector4& p_vec) m_data[2][3] = 0.0f; return 0; } - - return -1; + else { + return -1; + } } // FUNCTION: BETA10 0x1005a590 -inline int Matrix4::Unknown(Matrix4& p_mat) +inline int Matrix4::BETA_1005a590(Matrix4& p_mat) { float local5c[4][4]; Matrix4 localc(local5c); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 360363b95a..c6d0150c3b 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -467,38 +467,36 @@ class Vector4 : public Vector3 { // FUNCTION: BETA10 0x10048ad0 inline int Vector4::NormalizeQuaternion() { - float* v = m_data; - float magnitude = v[0] * v[0] + v[2] * v[2] + v[1] * v[1]; - if (magnitude > 0.0f) { - float theta = v[3] * 0.5f; - v[3] = cos(theta); - magnitude = sin(theta) / sqrt(magnitude); - Vector3::MulImpl(magnitude); - return 0; - } + float length = m_data[0] * m_data[0] + m_data[1] * m_data[1] + m_data[2] * m_data[2]; - return -1; -} + if (length > 0.0f) { + float theta = m_data[3] * 0.5f; + float magnitude = sin((double) theta); + m_data[3] = cos((double) theta); -inline static float QuaternionProductScalarPart(const float* bDat, const float* aDat) -{ - // We have no indication from the beta that this function exists, - // but it helps with the stack layout of Vector4::EqualsHamiltonProduct() - return aDat[3] * bDat[3] - (aDat[0] * bDat[0] + aDat[2] * bDat[2] + aDat[1] * bDat[1]); + magnitude = magnitude / (float) sqrt((double) length); + m_data[0] *= magnitude; + m_data[1] *= magnitude; + m_data[2] *= magnitude; + return 0; + } + else { + return -1; + } } // FUNCTION: LEGO1 0x10002bf0 // FUNCTION: BETA10 0x10048c20 inline int Vector4::EqualsHamiltonProduct(const Vector4& p_a, const Vector4& p_b) { - m_data[3] = QuaternionProductScalarPart(p_a.m_data, p_b.m_data); + m_data[3] = p_a.m_data[3] * p_b.m_data[3] - + (p_a.m_data[0] * p_b.m_data[0] + p_a.m_data[2] * p_b.m_data[2] + p_a.m_data[1] * p_b.m_data[1]); Vector3::EqualsCrossImpl(p_a.m_data, p_b.m_data); m_data[0] = p_b.m_data[3] * p_a.m_data[0] + p_a.m_data[3] * p_b.m_data[0] + m_data[0]; m_data[1] = p_b.m_data[1] * p_a.m_data[3] + p_a.m_data[1] * p_b.m_data[3] + m_data[1]; m_data[2] = p_b.m_data[2] * p_a.m_data[3] + p_a.m_data[2] * p_b.m_data[3] + m_data[2]; - return 0; }