From d24f5db42f161b4b4cff251ce85db8e628d7e02f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 12 Jan 2024 19:34:38 -0500 Subject: [PATCH] Matrix/vector refactor (#426) --- CMakeLists.txt | 2 + LEGO1/lego/legoomni/include/helicopter.h | 14 +- .../legoomni/include/legocameracontroller.h | 18 +- LEGO1/lego/legoomni/include/legoentity.h | 21 +- .../legoomni/include/legoentitypresenter.h | 2 +- LEGO1/lego/legoomni/include/legopathactor.h | 8 +- LEGO1/lego/legoomni/include/legoworld.h | 4 +- LEGO1/lego/legoomni/src/build/helicopter.cpp | 65 ++- .../src/entity/legocameracontroller.cpp | 48 +- LEGO1/lego/legoomni/src/entity/legoentity.cpp | 4 +- .../src/entity/legoentitypresenter.cpp | 6 +- .../legoomni/src/entity/legopathactor.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 4 +- .../legoomni/src/video/legovideomanager.cpp | 8 +- LEGO1/lego/sources/3dmanager/legoview1.cpp | 65 ++- LEGO1/lego/sources/roi/legoroi.cpp | 6 +- LEGO1/lego/sources/roi/legoroi.h | 6 +- LEGO1/mxgeometry/mxgeometry3d.cpp | 6 + LEGO1/mxgeometry/mxgeometry3d.h | 48 ++ LEGO1/mxgeometry/mxmatrix.cpp | 5 + LEGO1/mxgeometry/mxmatrix.h | 22 + LEGO1/omni/include/mxdsaction.h | 36 +- LEGO1/omni/include/mxvideopresenter.h | 3 +- LEGO1/omni/src/common/mxpresenter.cpp | 2 +- LEGO1/realtime/matrix.cpp | 177 +----- LEGO1/realtime/matrix.h | 208 ++++--- LEGO1/realtime/orientableroi.cpp | 36 +- LEGO1/realtime/orientableroi.h | 58 +- LEGO1/realtime/realtime.cpp | 45 +- LEGO1/realtime/realtime.h | 7 +- LEGO1/realtime/roi.h | 30 +- LEGO1/realtime/vector.cpp | 456 +-------------- LEGO1/realtime/vector.h | 523 ++++++++++++------ LEGO1/tgl/d3drm/camera.cpp | 2 +- LEGO1/tgl/d3drm/group.cpp | 2 +- LEGO1/tgl/d3drm/impl.h | 8 +- LEGO1/tgl/d3drm/light.cpp | 2 +- LEGO1/tgl/tgl.h | 6 +- LEGO1/tgl/tglvector.h | 251 +-------- LEGO1/viewmanager/viewroi.cpp | 12 +- LEGO1/viewmanager/viewroi.h | 2 +- 41 files changed, 865 insertions(+), 1365 deletions(-) create mode 100644 LEGO1/mxgeometry/mxgeometry3d.cpp create mode 100644 LEGO1/mxgeometry/mxgeometry3d.h create mode 100644 LEGO1/mxgeometry/mxmatrix.cpp create mode 100644 LEGO1/mxgeometry/mxmatrix.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7efecd09..25422132 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,8 @@ add_library(lego1 SHARED LEGO1/main.cpp LEGO1/mxdirectx/mxdirect3d.cpp LEGO1/mxdirectx/mxdirectdraw.cpp + LEGO1/mxgeometry/mxgeometry3d.cpp + LEGO1/mxgeometry/mxmatrix.cpp LEGO1/omni/src/action/mxdsaction.cpp LEGO1/omni/src/action/mxdsanim.cpp LEGO1/omni/src/action/mxdsevent.cpp diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index 7c5be4ea..ef932f30 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -9,12 +9,12 @@ class HelicopterSubclass { public: inline HelicopterSubclass() : m_unk0x30(0) {} - MxResult FUN_100040a0(Vector4Impl& p_v, float p_f); + MxResult FUN_100040a0(Vector4& p_v, float p_f); private: - Vector4Data m_unk0x0; // 0x0 - Vector4Data m_unk0x18; // 0x18 - undefined4 m_unk0x30; // 0x30 + Mx4DPointFloat m_unk0x0; // 0x0 + Mx4DPointFloat m_unk0x18; // 0x18 + undefined4 m_unk0x30; // 0x30 }; // VTABLE: LEGO1 0x100d40f8 @@ -39,7 +39,7 @@ class Helicopter : public IslePathActor { virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 void VTable0x70(float p_float) override; // vtable+0x70 - void VTable0x74(Matrix4Impl& p_transform) override; // vtable+0x74 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 virtual MxU32 VTable0xcc() override; // vtable+0xcc virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 virtual MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 @@ -49,8 +49,8 @@ class Helicopter : public IslePathActor { // Helicopter::`scalar deleting destructor' protected: - Matrix4Data m_unk0x160; // 0x160 - Matrix4Data m_unk0x1a8; // 0x1a8 + MxMatrix m_unk0x160; // 0x160 + MxMatrix m_unk0x1a8; // 0x1a8 float m_unk0x1f0; // 0x1f0 HelicopterSubclass m_unk0x1f4; // 0x1f4 HelicopterState* m_state; // 0x228 diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h index ba66461a..48256789 100644 --- a/LEGO1/lego/legoomni/include/legocameracontroller.h +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -3,9 +3,9 @@ #include "legopointofviewcontroller.h" #include "mxcore.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "mxpoint32.h" -#include "realtime/matrix.h" -#include "realtime/vector.h" // VTABLE: LEGO1 0x100d57b0 // SIZE 0xc8 @@ -36,15 +36,15 @@ class LegoCameraController : public LegoPointOfViewController { virtual void OnMouseMove(MxU8 p_modifier, MxPoint32 p_point); // vtable+0x40 virtual MxResult Create(); // vtable+0x44 - void SetWorldTransform(const Vector3Impl& p_at, const Vector3Impl& p_dir, const Vector3Impl& p_up); - void FUN_100123e0(Matrix4Data& p_transform, MxU32); - Vector3Data& FUN_10012740(); - Vector3Data& FUN_100127f0(); - Vector3Data& FUN_100128a0(); + void SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up); + void FUN_100123e0(MxMatrix& p_transform, MxU32); + Mx3DPointFloat GetWorldUp(); + Mx3DPointFloat GetWorldLocation(); + Mx3DPointFloat GetWorldDirection(); private: - Matrix4Data m_matrix1; // 0x38 - Matrix4Data m_matrix2; // 0x80 + MxMatrix m_matrix1; // 0x38 + MxMatrix m_matrix2; // 0x80 }; // SYNTHETIC: LEGO1 0x10011f50 diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index d911457c..8ca966b1 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -36,11 +36,8 @@ class LegoEntity : public MxEntity { virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c virtual void ParseAction(char*); // vtable+0x20 virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 - virtual void SetWorldTransform( - const Vector3Impl& p_loc, - const Vector3Impl& p_dir, - const Vector3Impl& p_up - ); // vtable+0x28 + virtual void SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, + const Vector3& p_up); // vtable+0x28 virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c // FUNCTION: LEGO1 0x10001090 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 @@ -53,7 +50,7 @@ class LegoEntity : public MxEntity { virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); - void SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool); + void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); protected: void Init(); @@ -61,12 +58,12 @@ class LegoEntity : public MxEntity { undefined m_unk0x10; undefined m_unk0x11; - Vector3Data m_worldLocation; // 0x14 - Vector3Data m_worldDirection; // 0x28 - Vector3Data m_worldUp; // 0x3c - MxFloat m_worldSpeed; // 0x50 - LegoROI* m_roi; // 0x54 - MxBool m_cameraFlag; // 0x58 + Mx3DPointFloat m_worldLocation; // 0x14 + Mx3DPointFloat m_worldDirection; // 0x28 + Mx3DPointFloat m_worldUp; // 0x3c + MxFloat m_worldSpeed; // 0x50 + LegoROI* m_roi; // 0x54 + MxBool m_cameraFlag; // 0x58 undefined m_unk0x59; // For tokens from the extra string that look like this: // "Action:openram;\lego\scripts\Race\CarRaceR;0" diff --git a/LEGO1/lego/legoomni/include/legoentitypresenter.h b/LEGO1/lego/legoomni/include/legoentitypresenter.h index 72af0498..de6690ec 100644 --- a/LEGO1/lego/legoomni/include/legoentitypresenter.h +++ b/LEGO1/lego/legoomni/include/legoentitypresenter.h @@ -33,7 +33,7 @@ class LegoEntityPresenter : public MxCompositePresenter { virtual void Init(); // vtable+0x68 virtual undefined4 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c - void SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up); + void SetBackendLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up); private: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index a3f5756c..5f67af4f 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -25,10 +25,10 @@ class LegoPathActor : public LegoActor { return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name); } - virtual void VTable0x68(); // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(float p_float); // vtable+0x70 - virtual void VTable0x74(Matrix4Impl& p_transform); // vtable+0x74 + virtual void VTable0x68(); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(float p_float); // vtable+0x70 + virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74 // FUNCTION: LEGO1 0x10002d20 virtual void VTable0x78(MxU8 p_unk0xea) { m_unk0xea = p_unk0xea; } // vtable+0x78 // FUNCTION: LEGO1 0x10002d30 diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index f55043c3..385e0b07 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -49,8 +49,8 @@ class LegoWorld : public LegoEntity { MxResult SetAsCurrentWorld(MxDSObject& p_dsObject); void EndAction(MxCore* p_object); void FUN_1001fc80(IslePathActor* p_actor); - MxBool FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); - MxBool FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); + MxBool FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + MxBool FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); void FUN_10073400(); void FUN_10073430(); MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); diff --git a/LEGO1/lego/legoomni/src/build/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index f4220183..d661b4d7 100644 --- a/LEGO1/lego/legoomni/src/build/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -181,15 +181,15 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) if (*g_act3Script != script) break; if (m_world && m_world->GetCamera()) { - Vector3Data loc, dir, lookat; - loc.CopyFrom(m_world->GetCamera()->FUN_100127f0()); - dir.CopyFrom(m_world->GetCamera()->FUN_100128a0()); + Mx3DPointFloat loc, dir, lookat; + loc.CopyFrom(m_world->GetCamera()->GetWorldLocation()); + dir.CopyFrom(m_world->GetCamera()->GetWorldDirection()); lookat = dir; float scale = 3; lookat.Mul(scale); lookat.Add(&loc); - Vector3Data v68, v7c, v90(0, 1, 0), va4; - v68.CopyFrom(m_world->GetCamera()->FUN_10012740()); + Mx3DPointFloat v68, v7c, v90(0, 1, 0), va4; + v68.CopyFrom(m_world->GetCamera()->GetWorldUp()); va4.EqualsCross(v68, dir); v7c.EqualsCross(va4, v90); if (ret) @@ -219,6 +219,8 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) // FUNCTION: LEGO1 0x10003c20 MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) { + MxU32 ret = 0; + switch (m_state->GetUnkown8()) { case 1: { if (GameState()->GetUnknown10() == 0) { @@ -227,44 +229,54 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) } else VTable0xe8(0x31, TRUE, 7); + m_state->SetUnknown8(2); - Matrix4Data mat; - mat.SetIdentity(); - Matrix4 mat2 = mat.GetMatrix(); + + MxMatrix matrix; + matrix.SetIdentity(); + float s = sin(0.5235987901687622); // PI / 6, 30 deg float c = cos(0.5235987901687622); // PI / 6, 30 deg + + float matrixCopy[4][4]; + memcpy(matrixCopy, matrix.GetData(), sizeof(matrixCopy)); for (MxS32 i = 0; i < 4; i++) { - mat.GetMatrix()[i][1] = mat2[i][1] * c - mat2[i][2] * s; - mat.GetMatrix()[i][2] = mat2[i][2] * c + mat2[i][1] * s; + matrix.GetData()[i][1] = matrixCopy[i][1] * c - matrixCopy[i][2] * s; + matrix.GetData()[i][2] = matrixCopy[i][2] * c + matrixCopy[i][1] * s; } - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); m_world->GetCamera()->SetWorldTransform(at, dir, up); FUN_10010c30(); + ret = 1; break; } case 3: { - Matrix4Data mat; - mat.SetIdentity(); - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + MxMatrix matrix; + matrix.SetIdentity(); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); at[1] = 1.25; m_world->GetCamera()->SetWorldTransform(at, dir, up); + if (GameState()->GetUnknown10() == 0) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(0); VTable0xe8(0x29, TRUE, 7); } else VTable0xe8(0x30, TRUE, 7); + m_state->SetUnknown8(0); + ret = 1; break; } - default: - return 0; } - return 1; + + return ret; } // FUNCTION: LEGO1 0x10003e90 -void Helicopter::VTable0x74(Matrix4Impl& p_transform) +void Helicopter::VTable0x74(Matrix4& p_transform) { if (m_unk0xea != 0) { m_roi->FUN_100a46b0(p_transform); @@ -295,13 +307,13 @@ void Helicopter::VTable0x70(float p_float) f2 = 0; if (1.0f < f2) f2 = 1.0f; - Vector3Impl v(m_unk0x160.GetMatrix()[3]); - Matrix4Data mat; - Vector3Impl v2(m_unk0x1a8.GetMatrix()[3]); - float* loc = m_unk0x1a8.GetMatrix()[3]; + Vector3 v(m_unk0x160[3]); + MxMatrix mat; + Vector3 v2(m_unk0x1a8[3]); + float* loc = m_unk0x1a8[3]; mat.SetIdentity(); float fa[4]; - Vector4Impl v3(fa); + Vector4 v3(fa); if (m_unk0x1f4.FUN_100040a0(v3, f2) == SUCCESS) { mat.FromQuaternion(v3); } @@ -322,18 +334,17 @@ void Helicopter::VTable0x70(float p_float) } // FUNCTION: LEGO1 0x100040a0 -MxResult HelicopterSubclass::FUN_100040a0(Vector4Impl& p_v, float p_f) +MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) { MxU32 state = m_unk0x30; if (state == 1) { - p_v.EqualsImpl(m_unk0x0.GetVector().elements); + p_v.EqualsImpl(m_unk0x0.GetData()); p_v[3] = acos(p_v[3]) * (1 - p_f) * 2.0; return p_v.NormalizeQuaternion(); } else if (state == 2) { - p_v.EqualsImpl(m_unk0x18.GetVector().elements); + p_v.EqualsImpl(m_unk0x18.GetData()); p_v[3] = acos(p_v[3]) * p_f * 2.0; - p_v.NormalizeQuaternion(); return p_v.NormalizeQuaternion(); } else if (state == 3) { diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index d339b104..b30a78b8 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -10,7 +10,7 @@ DECOMP_SIZE_ASSERT(LegoCameraController, 0xc8); // FUNCTION: LEGO1 0x10011d50 LegoCameraController::LegoCameraController() { - SetWorldTransform(Vector3Data(0, 0, 0), Vector3Data(0, 0, 1), Vector3Data(0, 1, 0)); + SetWorldTransform(Mx3DPointFloat(0, 0, 0), Mx3DPointFloat(0, 0, 1), Mx3DPointFloat(0, 1, 0)); } // FUNCTION: LEGO1 0x10011f70 @@ -71,37 +71,49 @@ void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) } // FUNCTION: LEGO1 0x10012260 -void LegoCameraController::SetWorldTransform(const Vector3Impl& p_at, const Vector3Impl& p_dir, const Vector3Impl& p_up) +void LegoCameraController::SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up) { CalcLocalTransform(p_at, p_dir, p_up, m_matrix1); m_matrix2 = m_matrix1; } // STUB: LEGO1 0x100123e0 -void LegoCameraController::FUN_100123e0(Matrix4Data& p_transform, MxU32) +void LegoCameraController::FUN_100123e0(MxMatrix& p_transform, MxU32) { } -// STUB: LEGO1 0x10012740 -Vector3Data& LegoCameraController::FUN_10012740() +// FUNCTION: LEGO1 0x10012740 +Mx3DPointFloat LegoCameraController::GetWorldUp() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldUp(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100127f0 -Vector3Data& LegoCameraController::FUN_100127f0() +// FUNCTION: LEGO1 0x100127f0 +Mx3DPointFloat LegoCameraController::GetWorldLocation() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldPosition(); + return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100128a0 -Vector3Data& LegoCameraController::FUN_100128a0() +// FUNCTION: LEGO1 0x100128a0 +Mx3DPointFloat LegoCameraController::GetWorldDirection() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldDirection(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index b000da96..62058e50 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -36,7 +36,7 @@ void LegoEntity::ResetWorldTransform(MxBool p_inVehicle) } // STUB: LEGO1 0x10010790 -void LegoEntity::SetWorldTransform(const Vector3Impl& p_loc, const Vector3Impl& p_dir, const Vector3Impl& p_up) +void LegoEntity::SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, const Vector3& p_up) { // TODO } @@ -77,7 +77,7 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } // STUB: LEGO1 0x100109b0 -void LegoEntity::SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool) +void LegoEntity::SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp index 995705bd..b7638b75 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -82,7 +82,11 @@ void LegoEntityPresenter::RepeatingTickle() } // FUNCTION: LEGO1 0x10053730 -void LegoEntityPresenter::SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up) +void LegoEntityPresenter::SetBackendLocation( + Mx3DPointFloat& p_location, + Mx3DPointFloat& p_direction, + Mx3DPointFloat& p_up +) { if (m_objectBackend) { m_objectBackend->SetLocation(p_location, p_direction, p_up, TRUE); diff --git a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp index f6d0a10d..472f2e4b 100644 --- a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp @@ -39,7 +39,7 @@ void LegoPathActor::VTable0x8c() } // STUB: LEGO1 0x1002e740 -void LegoPathActor::VTable0x74(Matrix4Impl& p_transform) +void LegoPathActor::VTable0x74(Matrix4& p_transform) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index b04543df..339360e7 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -131,13 +131,13 @@ void LegoWorld::VTable0x50() } // STUB: LEGO1 0x100727e0 -MxBool LegoWorld::FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } // STUB: LEGO1 0x10072980 -MxBool LegoWorld::FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 4d3dd304..33ebb53a 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -65,10 +65,10 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM MxResult result = FAILURE; MxDeviceEnumerate100d9cc8 deviceEnumerate; - Vector3Data posVec(0.0, 1.25, -50.0); - Vector3Data dirVec(0.0, 0.0, 1.0); - Vector3Data upVec(0.0, 1.0, 0.0); - Matrix4Data outMatrix; + Mx3DPointFloat posVec(0.0, 1.25, -50.0); + Mx3DPointFloat dirVec(0.0, 0.0, 1.0); + Mx3DPointFloat upVec(0.0, 1.0, 0.0); + MxMatrix outMatrix; HWND hwnd = MxOmni::GetInstance()->GetWindowHandle(); MxS32 bits = p_videoParam.Flags().Get16Bit() ? 16 : 8; MxS32 deviceNum = -1; diff --git a/LEGO1/lego/sources/3dmanager/legoview1.cpp b/LEGO1/lego/sources/3dmanager/legoview1.cpp index 3705eb33..97114469 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.cpp +++ b/LEGO1/lego/sources/3dmanager/legoview1.cpp @@ -4,13 +4,24 @@ #include "legoview1.h" #include "decomp.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "realtime/realtime.h" -#include // SETMAT4 +#include DECOMP_SIZE_ASSERT(LegoView, 0x78); DECOMP_SIZE_ASSERT(LegoView1, 0x88); +// GLOBAL: LEGO1 0x101013e4 +float g_sunLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013e8 +float g_directionalLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013ec +float g_ambientLightRGB = 0.3; + ///////////////////////////////////////////////////////////////////////////// // LegoView @@ -112,51 +123,39 @@ BOOL LegoView1::AddLightsToViewport() return TRUE; } -// STUB: LEGO1 0x100ab860 +// FUNCTION: LEGO1 0x100ab860 BOOL LegoView1::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { - double position[3] = {0, 0, 0}; - double direction[3]; - double up[3] = {0, 1, 0}; - if (!LegoView::Create(rCreateStruct, pRenderer)) { return FALSE; } // lights - m_pSunLight = pRenderer->CreateLight(Tgl::Directional, .9, .9, .9); - m_pDirectionalLight = pRenderer->CreateLight(Tgl::Directional, .4, .4, .4); - m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, .3, .3, .3); + m_pSunLight = pRenderer->CreateLight(Tgl::Point, g_sunLightRGB, g_sunLightRGB, g_sunLightRGB); + m_pDirectionalLight = + pRenderer->CreateLight(Tgl::Directional, g_directionalLightRGB, g_directionalLightRGB, g_directionalLightRGB); + m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, g_ambientLightRGB, g_ambientLightRGB, g_ambientLightRGB); -#if 0 - direction[0] = 1, direction[1] = -1, direction[2] = 2; - m_pSunLight->SetOrientation(direction, up); - direction[0] = -1, direction[1] = -2, direction[2] = -1; - m_pDirectionalLight->SetOrientation(direction, up); -#else - { - // Change everything to float and proper Matrix types - /* - Tgl::FloatMatrix4 transformation; - Matrix4Data transform; + Mx3DPointFloat direction(0.0, -1.0, 0.0); + Mx3DPointFloat position(0.0, 0.0, 0.0); + Mx3DPointFloat up(1.0, 0.0, 0.0); - direction[0] = 1, direction[1] = -1, direction[2] = 2; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pSunLight->SetTransformation(transformation); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + MxMatrix transform; - direction[0] = -1, direction[1] = -2, direction[2] = -1; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pDirectionalLight->SetTransformation(transformation); - */ - } -#endif + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pDirectionalLight->SetTransformation(matrix); + + direction[0] = 0, direction[1] = 150, direction[2] = -150; + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pSunLight->SetTransformation(matrix); assert(GetView()); - AddLightsToViewport(); - return TRUE; + return AddLightsToViewport(); } // FUNCTION: LEGO1 0x100abad0 diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index dab06a1a..9d530b16 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -38,18 +38,18 @@ MxS32 g_roiConfig = 100; ROIHandler g_someHandlerFunction = NULL; // FUNCTION: LEGO1 0x100a46a0 -void LegoROI::WrappedSetLocalTransform(Matrix4Impl& p_transform) +void LegoROI::WrappedSetLocalTransform(Matrix4& p_transform) { SetLocalTransform(p_transform); } // STUB: LEGO1 0x100a46b0 -void LegoROI::FUN_100a46b0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a46b0(Matrix4& p_transform) { } // STUB: LEGO1 0x100a58f0 -void LegoROI::FUN_100a58f0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a58f0(Matrix4& p_transform) { } diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index d84e8df4..17d66ef4 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -28,9 +28,9 @@ class LegoROI : public ViewROI { ); static MxBool ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other); - void WrappedSetLocalTransform(Matrix4Impl& p_transform); - void FUN_100a46b0(Matrix4Impl& p_transform); - void FUN_100a58f0(Matrix4Impl& p_transform); + void WrappedSetLocalTransform(Matrix4& p_transform); + void FUN_100a46b0(Matrix4& p_transform); + void FUN_100a58f0(Matrix4& p_transform); // Note: Actually part of parent class (doesn't exist yet) virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 diff --git a/LEGO1/mxgeometry/mxgeometry3d.cpp b/LEGO1/mxgeometry/mxgeometry3d.cpp new file mode 100644 index 00000000..03ce60eb --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.cpp @@ -0,0 +1,6 @@ +#include "mxgeometry3d.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(Mx3DPointFloat, 0x14); +DECOMP_SIZE_ASSERT(Mx4DPointFloat, 0x18); diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h new file mode 100644 index 00000000..13781722 --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -0,0 +1,48 @@ +#ifndef MXGEOMETRY3D_H +#define MXGEOMETRY3D_H + +#include "realtime/vector.h" + +// VTABLE: LEGO1 0x100d4488 +// SIZE 0x14 +class Mx3DPointFloat : public Vector3 { +public: + inline Mx3DPointFloat() : Vector3(m_elements) {} + inline Mx3DPointFloat(float p_x, float p_y, float p_z) : Vector3(m_elements) + { + m_elements[0] = p_x; + m_elements[1] = p_y; + m_elements[2] = p_z; + } + + // FUNCTION: LEGO1 0x10003c10 + virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 + + inline void CopyFrom(const Mx3DPointFloat& p_other) + { + // ALPHA: 0x10010860, multiple indirections to this call + EqualsImpl(p_other.m_data); + + float* dest = m_elements; + const float* src = p_other.m_elements; + for (size_t i = sizeof(m_elements) / sizeof(float); i > 0; --i) + *dest++ = *src++; + } + + inline void EqualsCross(Mx3DPointFloat& p_a, Mx3DPointFloat& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } + +private: + float m_elements[3]; +}; + +// VTABLE: LEGO1 0x100d41e8 +// SIZE 0x18 +class Mx4DPointFloat : public Vector4 { +public: + inline Mx4DPointFloat() : Vector4(m_elements) {} + +private: + float m_elements[4]; +}; + +#endif // MXGEOMETRY3D_H diff --git a/LEGO1/mxgeometry/mxmatrix.cpp b/LEGO1/mxgeometry/mxmatrix.cpp new file mode 100644 index 00000000..fc768f38 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.cpp @@ -0,0 +1,5 @@ +#include "mxmatrix.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxMatrix, 0x48); diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h new file mode 100644 index 00000000..2db07671 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -0,0 +1,22 @@ +#ifndef MXMATRIX_H +#define MXMATRIX_H + +#include "realtime/matrix.h" + +// VTABLE: LEGO1 0x100d4300 +// SIZE 0x48 +class MxMatrix : public Matrix4 { +public: + inline MxMatrix() : Matrix4(m_elements) {} + inline MxMatrix(const MxMatrix& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); } + + // No idea why there's another equals. Maybe to some other type like the + // DirectX Retained Mode Matrix type which is also a float* alias? + // FUNCTION: LEGO1 0x10002860 + virtual void operator=(const MxMatrix& p_matrix) { Equals(p_matrix); } // vtable+0x48 + +private: + float m_elements[4][4]; +}; + +#endif // MXMATRIX_H diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index c32dd4aa..b4d6192e 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -2,8 +2,8 @@ #define MXDSACTION_H #include "mxdsobject.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxtypes.h" -#include "realtime/vector.h" class MxOmni; @@ -63,9 +63,9 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline Vector3Data& GetLocation() { return m_location; } - inline Vector3Data& GetDirection() { return m_direction; } - inline Vector3Data& GetUp() { return m_up; } + inline Mx3DPointFloat& GetLocation() { return m_location; } + inline Mx3DPointFloat& GetDirection() { return m_direction; } + inline Mx3DPointFloat& GetUp() { return m_up; } inline MxCore* GetUnknown84() { return m_unk0x84; } inline void SetUnknown84(MxCore* p_unk0x84) { m_unk0x84 = p_unk0x84; } inline MxCore* GetOrigin() { return m_origin; } @@ -83,20 +83,20 @@ class MxDSAction : public MxDSObject { } protected: - MxU32 m_sizeOnDisk; // 0x2c - MxU32 m_flags; // 0x30 - MxLong m_startTime; // 0x34 - MxLong m_duration; // 0x38 - MxS32 m_loopCount; // 0x3c - Vector3Data m_location; // 0x40 - Vector3Data m_direction; // 0x54 - Vector3Data m_up; // 0x68 - char* m_extraData; // 0x7c - MxU16 m_extraLength; // 0x80 - MxCore* m_unk0x84; // 0x84 - undefined4 m_unk0x88; // 0x88 - MxCore* m_origin; // 0x8c - MxLong m_unk0x90; // 0x90 + MxU32 m_sizeOnDisk; // 0x2c + MxU32 m_flags; // 0x30 + MxLong m_startTime; // 0x34 + MxLong m_duration; // 0x38 + MxS32 m_loopCount; // 0x3c + Mx3DPointFloat m_location; // 0x40 + Mx3DPointFloat m_direction; // 0x54 + Mx3DPointFloat m_up; // 0x68 + char* m_extraData; // 0x7c + MxU16 m_extraLength; // 0x80 + MxCore* m_unk0x84; // 0x84 + undefined4 m_unk0x88; // 0x88 + MxCore* m_origin; // 0x8c + MxLong m_unk0x90; // 0x90 }; #endif // MXDSACTION_H diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index 78c89f14..48389490 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -65,7 +65,8 @@ class MxVideoPresenter : public MxMediaPresenter { // FUNCTION: LEGO1 0x1000c730 virtual void RealizePalette(){}; // vtable+0x70 - virtual undefined VTable0x74(); // vtable+0x74 + + virtual undefined VTable0x74(); // vtable+0x74 // FUNCTION: LEGO1 0x1000c7b0 virtual LPDIRECTDRAWSURFACE VTable0x78() { return m_unk0x58; }; // vtable+0x78 diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index f08b0f30..6d025394 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -36,7 +36,7 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) this->m_action = p_action; - const Vector3Data& location = this->m_action->GetLocation(); + const Mx3DPointFloat& location = this->m_action->GetLocation(); MxS32 previousTickleState = this->m_currentTickleState; this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]); diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 818650eb..806e6659 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -1,180 +1,5 @@ - #include "matrix.h" #include "decomp.h" -#include "math.h" -#include - -DECOMP_SIZE_ASSERT(Matrix4, 0x40); -DECOMP_SIZE_ASSERT(Matrix4Impl, 0x8); -DECOMP_SIZE_ASSERT(Matrix4Data, 0x48); - -// FUNCTION: LEGO1 0x10002320 -void Matrix4Impl::EqualsMatrixData(const Matrix4& p_matrix) -{ - *m_data = p_matrix; -} - -// FUNCTION: LEGO1 0x10002340 -void Matrix4Impl::EqualsMatrixImpl(const Matrix4Impl* p_other) -{ - *m_data = *p_other->m_data; -} - -// FUNCTION: LEGO1 0x10002360 -void Matrix4Impl::AnotherSetData(Matrix4& p_data) -{ - m_data = &p_data; -} - -// FUNCTION: LEGO1 0x10002380 -const Matrix4* Matrix4Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x10002390 -Matrix4* Matrix4Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100023a0 -const float* Matrix4Impl::Element(int p_row, int p_col) const -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023c0 -float* Matrix4Impl::Element(int p_row, int p_col) -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023e0 -void Matrix4Impl::Clear() -{ - memset(m_data, 0, 16 * sizeof(float)); -} - -// FUNCTION: LEGO1 0x100023f0 -void Matrix4Impl::SetIdentity() -{ - Clear(); - (*m_data)[0][0] = 1.0f; - (*m_data)[1][1] = 1.0f; - (*m_data)[2][2] = 1.0f; - (*m_data)[3][3] = 1.0f; -} - -// FUNCTION: LEGO1 0x10002430 -Matrix4Impl* Matrix4Impl::operator+=(const Matrix4& p_matrix) -{ - for (int i = 0; i < 16; ++i) - ((float*) m_data)[i] += ((float*) &p_matrix)[i]; - return this; -} - -// Matches but instructions are significantly out of order. Probably not wrong -// code given that the very similar SetTranslation does match. -// FUNCTION: LEGO1 0x10002460 -void Matrix4Impl::TranslateBy(const float* p_x, const float* p_y, const float* p_z) -{ - ((float*) m_data)[12] += *p_x; - ((float*) m_data)[13] += *p_y; - ((float*) m_data)[14] += *p_z; -} - -// FUNCTION: LEGO1 0x100024a0 -void Matrix4Impl::SetTranslation(const float* p_x, const float* p_y, const float* p_z) -{ - (*m_data)[3][0] = *p_x; - (*m_data)[3][1] = *p_y; - (*m_data)[3][2] = *p_z; -} - -// FUNCTION: LEGO1 0x100024d0 -void Matrix4Impl::EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b) -{ - float* cur = (float*) m_data; - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - *cur = 0.0f; - for (int k = 0; k < 4; ++k) { - *cur += p_a[row][k] * p_b[k][col]; - } - cur++; - } - } -} - -// FUNCTION: LEGO1 0x10002530 -void Matrix4Impl::EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b) -{ - EqualsDataProduct(*p_a->m_data, *p_b->m_data); -} - -// Not close, Ghidra struggles understinging this method so it will have to -// be manually worked out. Included since I at least figured out what it was -// doing with rotateIndex and what overall operation it's trying to do. -// STUB: LEGO1 0x10002550 -void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) -{ - /* - float trace = m_data[0] + m_data[5] + m_data[10]; - if (trace > 0) { - trace = sqrt(trace + 1.0); - p_outQuat->GetData()[3] = trace * 0.5f; - p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; - p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; - p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; - return; - } - - // ~GLOBAL: LEGO1 0x100d4090 - static int rotateIndex[] = {1, 2, 0}; - - // Largest element along the trace - int largest = m_data[0] < m_data[5]; - if (*Element(largest, largest) < m_data[10]) - largest = 2; - - int next = rotateIndex[largest]; - int nextNext = rotateIndex[next]; - float valueA = *Element(nextNext, nextNext); - float valueB = *Element(next, next); - float valueC = *Element(largest, largest); - - // Above is somewhat decomped, below is pure speculation since the automatic - // decomp becomes very garbled. - float traceValue = sqrt(valueA - valueB - valueC + 1.0); - - p_outQuat->GetData()[largest] = traceValue * 0.5f; - traceValue = 0.5f / traceValue; - - p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; - p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; - p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; - */ -} - -// No idea what this function is doing and it will be hard to tell until -// we have a confirmed usage site. -// STUB: LEGO1 0x10002710 -int Matrix4Impl::FromQuaternion(const Vector4Impl& p_vec) -{ - return -1; -} - -// FUNCTION: LEGO1 0x10002850 -void Matrix4Impl::operator=(const Matrix4Impl& p_other) -{ - EqualsMatrixImpl(&p_other); -} - -// FUNCTION: LEGO1 0x10002860 -void Matrix4Data::operator=(const Matrix4Data& p_other) -{ - EqualsMatrixImpl(&p_other); -} +DECOMP_SIZE_ASSERT(Matrix4, 0x8); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index c087d331..4e661ddb 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -3,90 +3,166 @@ #include "vector.h" -/* - * A simple array of four Vector4s that can be indexed into. - */ -class Matrix4 { -public: - float rows[4][4]; // storage is public for easy access +#include - inline Matrix4() {} - /* - Matrix4(const Vector4& x_axis, const Vector4& y_axis, const Vector4& z_axis, const Vector4& position) - { - rows[0] = x_axis; - rows[1] = y_axis; - rows[2] = z_axis; - rows[3] = position; - } - Matrix4(const float m[4][4]) - { - rows[0] = m[0]; - rows[1] = m[1]; - rows[2] = m[2]; - rows[3] = m[3]; - } - */ - const float* operator[](long i) const { return rows[i]; } - float* operator[](long i) { return rows[i]; } +struct UnknownMatrixType { + float m_data[4][4]; }; // VTABLE: LEGO1 0x100d4350 // SIZE 0x8 -class Matrix4Impl { +class Matrix4 { public: - inline Matrix4Impl(Matrix4& p_data) { SetData(p_data); } + inline Matrix4(float (*p_data)[4]) { SetData(p_data); } + + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10002320 + virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 + + // FUNCTION: LEGO1 0x10002340 + virtual void Equals(const Matrix4& p_matrix) + { + memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); + }; // vtable+0x00 + + // FUNCTION: LEGO1 0x10002360 + virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c - // vtable + 0x00 - virtual void EqualsMatrixImpl(const Matrix4Impl* p_other); - virtual void EqualsMatrixData(const Matrix4& p_matrix); // FUNCTION: LEGO1 0x10002370 - virtual void SetData(Matrix4& p_data) { m_data = &p_data; } - virtual void AnotherSetData(Matrix4& p_data); + virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; }; // vtable+0x08 - // vtable + 0x10 - virtual Matrix4* GetData(); - virtual const Matrix4* GetData() const; - virtual float* Element(int p_row, int p_col); - virtual const float* Element(int p_row, int p_col) const; + // FUNCTION: LEGO1 0x10002380 + virtual float (*GetData())[4] { return m_data; }; // vtable+0x14 - // vtable + 0x20 - virtual void Clear(); - virtual void SetIdentity(); - virtual void operator=(const Matrix4Impl& p_other); - virtual Matrix4Impl* operator+=(const Matrix4& p_matrix); + // FUNCTION: LEGO1 0x10002390 + virtual float (*GetData() const)[4] { return m_data; }; // vtable+0x10 - // vtable + 0x30 - virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z); - virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z); - virtual void EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b); - virtual void EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b); + // FUNCTION: LEGO1 0x100023a0 + virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c - // vtable + 0x40 - virtual void ToQuaternion(Vector4Impl* p_resultQuat); - virtual int FromQuaternion(const Vector4Impl& p_vec); + // FUNCTION: LEGO1 0x100023c0 + virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; }; // vtable+0x18 - inline float& operator[](size_t idx) { return ((float*) m_data)[idx]; } + // FUNCTION: LEGO1 0x100023e0 + virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); }; // vtable+0x20 + + // FUNCTION: LEGO1 0x100023f0 + virtual void SetIdentity() + { + Clear(); + m_data[0][0] = 1.0f; + m_data[1][1] = 1.0f; + m_data[2][2] = 1.0f; + m_data[3][3] = 1.0f; + } // vtable+0x24 + + // FUNCTION: LEGO1 0x10002850 + virtual void operator=(const Matrix4& p_matrix) { Equals(p_matrix); } // vtable+0x28 + + // FUNCTION: LEGO1 0x10002430 + virtual Matrix4& operator+=(float (*p_data)[4]) + { + for (int i = 0; i < 16; i++) + ((float*) m_data)[i] += ((float*) p_data)[i]; + return *this; + } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002460 + virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z) + { + m_data[3][0] += *p_x; + m_data[3][1] += *p_y; + m_data[3][2] += *p_z; + } // vtable+0x30 + + // FUNCTION: LEGO1 0x100024a0 + virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z) + { + m_data[3][0] = *p_x; + m_data[3][1] = *p_y; + m_data[3][2] = *p_z; + } // vtable+0x34 + + // FUNCTION: LEGO1 0x100024d0 + virtual void Product(float (*p_a)[4], float (*p_b)[4]) + { + float* cur = (float*) m_data; + for (int row = 0; row < 4; row++) { + for (int col = 0; col < 4; col++) { + *cur = 0.0f; + for (int k = 0; k < 4; k++) { + *cur += p_a[row][k] * p_b[k][col]; + } + cur++; + } + } + }; // vtable+0x3c + + // FUNCTION: LEGO1 0x10002530 + virtual void Product(const Matrix4& p_a, const Matrix4& p_b) { Product(p_a.m_data, p_b.m_data); } // vtable+0x38 + + inline virtual void ToQuaternion(Vector4& p_resultQuat); // vtable+0x40 + inline virtual int FromQuaternion(const Vector4& p_vec); // vtable+0x44 + + float* operator[](size_t idx) { return m_data[idx]; } + const float* operator[](size_t idx) const { return m_data[idx]; } protected: - // TODO: Currently unclear whether this class contains a Matrix4* or float*. - Matrix4* m_data; + float (*m_data)[4]; }; -// VTABLE: LEGO1 0x100d4300 -// SIZE 0x48 -class Matrix4Data : public Matrix4Impl { -public: - inline Matrix4Data() : Matrix4Impl(m_matrix) {} - inline Matrix4Data(Matrix4Data& p_other) : Matrix4Impl(m_matrix) { m_matrix = *p_other.m_data; } - inline Matrix4& GetMatrix() { return *m_data; } +// Not close, Ghidra struggles understinging this method so it will have to +// be manually worked out. Included since I at least figured out what it was +// doing with rotateIndex and what overall operation it's trying to do. +// STUB: LEGO1 0x10002550 +inline void Matrix4::ToQuaternion(Vector4& p_outQuat) +{ + /* + float trace = m_data[0] + m_data[5] + m_data[10]; + if (trace > 0) { + trace = sqrt(trace + 1.0); + p_outQuat->GetData()[3] = trace * 0.5f; + p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; + p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; + p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; + return; + } - // No idea why there's another equals. Maybe to some other type like the - // DirectX Retained Mode Matrix type which is also a float* alias? - // vtable + 0x44 - virtual void operator=(const Matrix4Data& p_other); + // ~GLOBAL: LEGO1 0x100d4090 + static int rotateIndex[] = {1, 2, 0}; - Matrix4 m_matrix; -}; + // Largest element along the trace + int largest = m_data[0] < m_data[5]; + if (*Element(largest, largest) < m_data[10]) + largest = 2; + + int next = rotateIndex[largest]; + int nextNext = rotateIndex[next]; + float valueA = *Element(nextNext, nextNext); + float valueB = *Element(next, next); + float valueC = *Element(largest, largest); + + // Above is somewhat decomped, below is pure speculation since the automatic + // decomp becomes very garbled. + float traceValue = sqrt(valueA - valueB - valueC + 1.0); + + p_outQuat->GetData()[largest] = traceValue * 0.5f; + traceValue = 0.5f / traceValue; + + p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; + p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; + p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; + */ +} + +// No idea what this function is doing and it will be hard to tell until +// we have a confirmed usage site. +// STUB: LEGO1 0x10002710 +inline int Matrix4::FromQuaternion(const Vector4& p_vec) +{ + return -1; +} #endif // MATRIX_H diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index e03b78cb..f73758b9 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -2,8 +2,24 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(OrientableROI, 0xdc) +// FUNCTION: LEGO1 0x100a4420 +OrientableROI::OrientableROI() +{ + FILLVEC3(m_world_bounding_box.Min(), 888888.8); + FILLVEC3(m_world_bounding_box.Max(), -888888.8); + ZEROVEC3(m_world_bounding_sphere.Center()); + m_world_bounding_sphere.Radius() = 0.0; + ZEROVEC3(m_world_velocity); + IDENTMAT4(m_local2world); + + m_unk0xd4 = 0; + m_unk0xd8 |= Flag_Bit1 | Flag_Bit2; +} + // FUNCTION: LEGO1 0x100a5910 void OrientableROI::VTable0x1c() { @@ -12,27 +28,27 @@ void OrientableROI::VTable0x1c() } // FUNCTION: LEGO1 0x100a5930 -void OrientableROI::SetLocalTransform(const Matrix4Impl& p_transform) +void OrientableROI::SetLocalTransform(const Matrix4& p_transform) { - reinterpret_cast(m_local2world) = p_transform; + reinterpret_cast(m_local2world) = p_transform; UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a5960 -void OrientableROI::VTable0x24(const Matrix4Data& p_transform) +void OrientableROI::VTable0x24(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&p_transform, &l_matrix); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(p_transform, l_matrix); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a59b0 -void OrientableROI::UpdateWorldData(const Matrix4Data& p_transform) +void OrientableROI::UpdateWorldData(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&l_matrix, &p_transform); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(l_matrix, p_transform); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); @@ -50,9 +66,9 @@ void OrientableROI::UpdateWorldVelocity() } // FUNCTION: LEGO1 0x100a5d80 -const Vector3& OrientableROI::GetWorldVelocity() const +const float* OrientableROI::GetWorldVelocity() const { - return (Vector3&) *m_world_velocity.GetData(); + return m_world_velocity.GetData(); } // FUNCTION: LEGO1 0x100a5d90 diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 82db8271..9b754b05 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -1,47 +1,55 @@ #ifndef ORIENTABLEROI_H #define ORIENTABLEROI_H -#include "matrix.h" +#include "decomp.h" +#include "mxgeometry/mxmatrix.h" #include "roi.h" // VTABLE: LEGO1 0x100dbc08 // SIZE 0xdc class OrientableROI : public ROI { public: - // FUNCTION: LEGO1 0x100a4420 - OrientableROI() - { - FILLVEC3(m_world_bounding_box.Min(), 888888.8); - FILLVEC3(m_world_bounding_box.Max(), -888888.8); - ZEROVEC3(m_world_bounding_sphere.Center()); - m_world_bounding_sphere.Radius() = 0.0; - ZEROVEC3(m_world_velocity); - IDENTMAT4(m_local2world.GetMatrix()); - } + enum { + Flag_Bit1 = 0x01, + Flag_Bit2 = 0x02 + }; - virtual const Vector3& GetWorldVelocity() const override; // vtable+0x8 + OrientableROI(); + + virtual const float* GetWorldVelocity() const override; // vtable+0x8 virtual const BoundingBox& GetWorldBoundingBox() const override; // vtable+0xc virtual const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 // FUNCTION: LEGO1 0x100a5db0 - virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 - virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 - virtual void VTable0x1c(); // vtable+0x1c - virtual void SetLocalTransform(const Matrix4Impl& p_transform); // vtable+0x20 - virtual void VTable0x24(const Matrix4Data& p_transform); // vtable+0x24 - virtual void UpdateWorldData(const Matrix4Data& p_transform); // vtable+0x28 - virtual void UpdateWorldVelocity(); // vtable+0x2c + virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 + virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 + virtual void VTable0x1c(); // vtable+0x1c + virtual void SetLocalTransform(const Matrix4& p_transform); // vtable+0x20 + virtual void VTable0x24(const MxMatrix& p_transform); // vtable+0x24 + virtual void UpdateWorldData(const MxMatrix& p_transform); // vtable+0x28 + virtual void UpdateWorldVelocity(); // vtable+0x2c + + const float* GetWorldPosition() const { return m_local2world[3]; } + const float* GetWorldDirection() const { return m_local2world[2]; } + const float* GetWorldUp() const { return m_local2world[1]; } // SYNTHETIC: LEGO1 0x100a4630 // OrientableROI::`scalar deleting destructor' protected: - char m_unk0xc; // 0xc - Matrix4Data m_local2world; // 0x10 - BoundingBox m_world_bounding_box; // 0x58 + MxMatrix m_local2world; // 0x10 + BoundingBox m_world_bounding_box; // 0x58 + + // Unclear whether the following vectors are: + // 1) Part of m_world_bounding_box; + // 2) A second BoundingBox; + // 3) Standalone vectors + + Mx3DPointFloat m_unk0x80; // 0x80 + Mx3DPointFloat m_unk0x94; // 0x94 BoundingSphere m_world_bounding_sphere; // 0xa8 - Vector3Data m_world_velocity; // 0xc0 - unsigned int m_unk0xd4; // 0xd4 - unsigned int m_unk0xd8; // 0xd8 + Mx3DPointFloat m_world_velocity; // 0xc0 + undefined4 m_unk0xd4; // 0xd4 + undefined4 m_unk0xd8; // 0xd8 }; #endif // ORIENTABLEROI_H diff --git a/LEGO1/realtime/realtime.cpp b/LEGO1/realtime/realtime.cpp index 750082ec..829b2271 100644 --- a/LEGO1/realtime/realtime.cpp +++ b/LEGO1/realtime/realtime.cpp @@ -1,45 +1,20 @@ #include "realtime.h" +#include + // FUNCTION: LEGO1 0x100a5b40 -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -) +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix) { float x_axis[3], y_axis[3], z_axis[3]; - // This is an unrolled version of the "NORMVEC3" macro, - // used here to apply a silly hack to get a 100% match - { - const float dirVec1Operation = (p_dirVec)[1] * (p_dirVec)[1]; - double len = sqrt(((p_dirVec)[0] * (p_dirVec)[0] + dirVec1Operation + (p_dirVec)[2] * (p_dirVec)[2])); - ((z_axis)[0] = (p_dirVec)[0] / (len), (z_axis)[1] = (p_dirVec)[1] / (len), (z_axis)[2] = (p_dirVec)[2] / (len)); - } - + NORMVEC3(z_axis, p_dirVec); NORMVEC3(y_axis, p_upVec) - VXV3(x_axis, y_axis, z_axis); - - // Exact same thing as pointed out by the above comment - { - const float axis2Operation = (x_axis)[2] * (x_axis)[2]; - double len = sqrt(((x_axis)[0] * (x_axis)[0] + axis2Operation + (x_axis)[1] * (x_axis)[1])); - ((x_axis)[0] = (x_axis)[0] / (len), (x_axis)[1] = (x_axis)[1] / (len), (x_axis)[2] = (x_axis)[2] / (len)); - } - + NORMVEC3(x_axis, x_axis); VXV3(y_axis, z_axis, x_axis); - - // Again, the same thing - { - const float axis2Operation = (y_axis)[2] * (y_axis)[2]; - double len = sqrt(((y_axis)[0] * (y_axis)[0] + axis2Operation + (y_axis)[1] * (y_axis)[1])); - ((y_axis)[0] = (y_axis)[0] / (len), (y_axis)[1] = (y_axis)[1] / (len), (y_axis)[2] = (y_axis)[2] / (len)); - } - - SET4from3(&p_outMatrix[0], x_axis, 0); - SET4from3(&p_outMatrix[4], y_axis, 0); - SET4from3(&p_outMatrix[8], z_axis, 0); - SET4from3(&p_outMatrix[12], p_posVec, 1); + NORMVEC3(y_axis, y_axis); + SET4from3(p_outMatrix[0], x_axis, 0); + SET4from3(p_outMatrix[1], y_axis, 0); + SET4from3(p_outMatrix[2], z_axis, 0); + SET4from3(p_outMatrix[3], p_posVec, 1); } diff --git a/LEGO1/realtime/realtime.h b/LEGO1/realtime/realtime.h index ae166dfa..cb8298a1 100644 --- a/LEGO1/realtime/realtime.h +++ b/LEGO1/realtime/realtime.h @@ -9,11 +9,6 @@ VDS3(dst, src, len); \ } -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -); +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix); #endif // REALTIME_H diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index c8458cd7..2a96d40b 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -5,39 +5,39 @@ #include "compat.h" #include "lodlist.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxstl/stlcompat.h" #include "realtime/realtime.h" -#include "vector.h" /* * A simple bounding box object with Min and Max accessor methods. */ +// SIZE 0x28 class BoundingBox { public: - const Vector3Data& Min() const { return min; } - Vector3Data& Min() { return min; } - const Vector3Data& Max() const { return max; } - Vector3Data& Max() { return max; } + const Mx3DPointFloat& Min() const { return min; } + Mx3DPointFloat& Min() { return min; } + const Mx3DPointFloat& Max() const { return max; } + Mx3DPointFloat& Max() { return max; } private: - Vector3Data min; - Vector3Data max; - Vector3Data m_unk0x28; - Vector3Data m_unk0x3c; + Mx3DPointFloat min; + Mx3DPointFloat max; }; /* * A simple bounding sphere object with center and radius accessor methods. */ +// SIZE 0x18 class BoundingSphere { public: - const Vector3Data& Center() const { return center; } - Vector3Data& Center() { return center; } + const Mx3DPointFloat& Center() const { return center; } + Mx3DPointFloat& Center() { return center; } const float& Radius() const { return radius; } float& Radius() { return radius; } private: - Vector3Data center; + Mx3DPointFloat center; float radius; }; @@ -74,13 +74,14 @@ typedef vector ROIList; typedef vector IntList; // VTABLE: LEGO1 0x100dbc38 -// SIZE 0xc +// SIZE 0x10 class ROI { public: ROI() { m_comp = 0; m_lods = 0; + m_unk0xc = 1; } virtual ~ROI() { @@ -89,7 +90,7 @@ class ROI { assert(!m_lods); } virtual float IntrinsicImportance() const = 0; // vtable+0x4 - virtual const Vector3& GetWorldVelocity() const = 0; // vtable+0x8 + virtual const float* GetWorldVelocity() const = 0; // vtable+0x8 virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0xc virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; // vtable+0x10 @@ -105,5 +106,6 @@ class ROI { protected: CompoundObject* m_comp; // 0x4 LODListBase* m_lods; // 0x8 + undefined m_unk0xc; // 0xc }; #endif // ROI_H diff --git a/LEGO1/realtime/vector.cpp b/LEGO1/realtime/vector.cpp index 390cfdd9..57c93e66 100644 --- a/LEGO1/realtime/vector.cpp +++ b/LEGO1/realtime/vector.cpp @@ -1,457 +1,7 @@ - #include "vector.h" #include "decomp.h" -#include -#include - -DECOMP_SIZE_ASSERT(Vector2Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector4Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Data, 0x14); -DECOMP_SIZE_ASSERT(Vector4Data, 0x18); - -// FUNCTION: LEGO1 0x10001f80 -void Vector2Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fa0 -void Vector2Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; -} - -// FUNCTION: LEGO1 0x10001fc0 -void Vector2Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fe0 -void Vector2Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; -} - -// FUNCTION: LEGO1 0x10002000 -void Vector2Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; -} - -// FUNCTION: LEGO1 0x10002020 -void Vector2Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; -} - -// FUNCTION: LEGO1 0x10002040 -float Vector2Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_b[0] * p_a[0] + p_b[1] * p_a[1]; -} - -// FUNCTION: LEGO1 0x10002070 -void Vector2Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; -} - -// FUNCTION: LEGO1 0x10002090 -float* Vector2Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020a0 -const float* Vector2Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020b0 -void Vector2Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; -} - -// FUNCTION: LEGO1 0x100020d0 -float Vector2Impl::Dot(float* p_a, float* p_b) const -{ - return DotImpl(p_a, p_b); -} - -// FUNCTION: LEGO1 0x100020f0 -float Vector2Impl::Dot(Vector2Impl* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002110 -float Vector2Impl::Dot(float* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002130 -float Vector2Impl::Dot(Vector2Impl* p_a, float* p_b) const -{ - return DotImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002150 -float Vector2Impl::LenSquared() const -{ - return m_data[0] * m_data[0] + m_data[1] * m_data[1]; -} - -// FUNCTION: LEGO1 0x10002160 -int Vector2Impl::Unitize() -{ - float sq = LenSquared(); - if (sq > 0.0f) { - float root = sqrt(sq); - if (root > 0) { - DivScalarImpl(&root); - return 0; - } - } - return -1; -} - -// FUNCTION: LEGO1 0x100021c0 -void Vector2Impl::Add(float p_value) -{ - AddScalarImpl(p_value); -} - -// FUNCTION: LEGO1 0x100021d0 -void Vector2Impl::Add(float* p_other) -{ - AddVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x100021e0 -void Vector2Impl::Add(Vector2Impl* p_other) -{ - AddVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x100021f0 -void Vector2Impl::Sub(float* p_other) -{ - SubVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002200 -void Vector2Impl::Sub(Vector2Impl* p_other) -{ - SubVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002210 -void Vector2Impl::Mul(float* p_other) -{ - MullVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002220 -void Vector2Impl::Mul(Vector2Impl* p_other) -{ - MullVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002230 -void Vector2Impl::Mul(float& p_value) -{ - MullScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002240 -void Vector2Impl::Div(float& p_value) -{ - DivScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002250 -void Vector2Impl::SetVector(float* p_other) -{ - EqualsImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002260 -void Vector2Impl::SetVector(Vector2Impl* p_other) -{ - EqualsImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002270 -void Vector3Impl::EqualsCrossImpl(float* p_a, float* p_b) -{ - m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; - m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; - m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; -} - -// FUNCTION: LEGO1 0x100022c0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x100022e0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, float* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002300 -void Vector3Impl::EqualsCross(float* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002870 -void Vector4Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; - m_data[3] += p_value[3]; -} - -// FUNCTION: LEGO1 0x100028b0 -void Vector4Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; - m_data[3] += p_value; -} - -// FUNCTION: LEGO1 0x100028f0 -void Vector4Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; - m_data[3] -= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002930 -void Vector4Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; - m_data[3] *= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002970 -void Vector4Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; - m_data[3] *= *p_value; -} - -// FUNCTION: LEGO1 0x100029b0 -void Vector4Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; - m_data[3] /= *p_value; -} - -// FUNCTION: LEGO1 0x100029f0 -float Vector4Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); -} - -// FUNCTION: LEGO1 0x10002a20 -void Vector4Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; - vec[3] = p_data[3]; -} - -// FUNCTION: LEGO1 0x10002a40 -void Vector4Impl::SetMatrixProductImpl(float* p_vec, float* p_mat) -{ - m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; - m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; - m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; - m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; -} - -// FUNCTION: LEGO1 0x10002ae0 -void Vector4Impl::SetMatrixProduct(Vector4Impl* p_a, float* p_b) -{ - SetMatrixProductImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002b00 -void Vector4Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; - vec[3] = 0.0f; -} - -// FUNCTION: LEGO1 0x10002b20 -float Vector4Impl::LenSquared() const -{ - return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; -} - -// FUNCTION: LEGO1 0x10002b40 -void Vector4Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; - m_data[3] = *p_value; -} - -// Note close yet, included because I'm at least confident I know what operation -// it's trying to do. -// STUB: LEGO1 0x10002b70 -int Vector4Impl::NormalizeQuaternion() -{ - float* v = m_data; - float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; - if (magnitude > 0.0f) { - float theta = v[3] * 0.5f; - v[3] = cos(theta); - float frac = sin(theta); - magnitude = frac / sqrt(magnitude); - v[0] *= magnitude; - v[1] *= magnitude; - v[2] *= magnitude; - return 0; - } - return -1; -} - -// FUNCTION: LEGO1 0x10002bf0 -void Vector4Impl::UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b) -{ - float* bDat = p_b->m_data; - float* aDat = p_a->m_data; - - this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); - this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; - this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; - this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; - - 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]; -} - -// FUNCTION: LEGO1 0x10003a60 -void Vector3Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; -} - -// FUNCTION: LEGO1 0x10003a90 -void Vector3Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; -} - -// FUNCTION: LEGO1 0x10003ac0 -void Vector3Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003af0 -void Vector3Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003b20 -void Vector3Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; -} - -// FUNCTION: LEGO1 0x10003b50 -void Vector3Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; -} - -// FUNCTION: LEGO1 0x10003b80 -float Vector3Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; -} - -// FUNCTION: LEGO1 0x10003ba0 -void Vector3Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; -} - -// FUNCTION: LEGO1 0x10003bc0 -void Vector3Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; -} - -// FUNCTION: LEGO1 0x10003bd0 -float Vector3Impl::LenSquared() const -{ - return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; -} - -// FUNCTION: LEGO1 0x10003bf0 -void Vector3Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; -} +DECOMP_SIZE_ASSERT(Vector2, 0x8); +DECOMP_SIZE_ASSERT(Vector3, 0x8); +DECOMP_SIZE_ASSERT(Vector4, 0x8); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 1af21c9a..eb03d29d 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -1,115 +1,145 @@ #ifndef VECTOR_H #define VECTOR_H -#include +#include "compat.h" -/* - * A simple array of three floats that can be indexed into. - */ -class Vector3 { -public: - float elements[3]; // storage is public for easy access - - Vector3() {} - Vector3(float x, float y, float z) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - } - - Vector3(const float v[3]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; - -/* - * A simple array of four floats that can be indexed into. - */ -struct Vector4 { -public: - float elements[4]; // storage is public for easy access - - inline Vector4() {} - Vector4(float x, float y, float z, float w) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - elements[3] = w; - } - Vector4(const float v[4]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - elements[3] = v[3]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; +#include +#include // VTABLE: LEGO1 0x100d4288 -// SIZE 0x8 -class Vector2Impl { +// SIZE 0x08 +class Vector2 { public: // FUNCTION: LEGO1 0x1000c0f0 - inline Vector2Impl(float* p_data) { SetData(p_data); } + inline Vector2(float* p_data) { SetData(p_data); } - // vtable + 0x00 (no virtual destructor) - virtual void AddScalarImpl(float p_value) = 0; - virtual void AddVectorImpl(float* p_value) = 0; - virtual void SubVectorImpl(float* p_value) = 0; - virtual void MullScalarImpl(float* p_value) = 0; + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10001f80 + virtual void AddImpl(float* p_value) + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10001fa0 + virtual void AddImpl(float p_value) + { + m_data[0] += p_value; + m_data[1] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10001fc0 + virtual void SubImpl(float* p_value) + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + } // vtable+0x08 + + // Those are also overloads in all likelihood, + // but we need a type to do that. + + // FUNCTION: LEGO1 0x10002000 + virtual void MulScalarImpl(float* p_value) + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10001fe0 + virtual void MulVectorImpl(float* p_value) + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10002020 + virtual void DivScalarImpl(float* p_value) + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10002040 + virtual float DotImpl(float* p_a, float* p_b) const { return p_b[0] * p_a[0] + p_b[1] * p_a[1]; } // vtable+0x18 - // vtable + 0x10 - virtual void MullVectorImpl(float* p_value) = 0; - virtual void DivScalarImpl(float* p_value) = 0; - virtual float DotImpl(float* p_a, float* p_b) const = 0; // FUNCTION: LEGO1 0x10002060 - virtual void SetData(float* p_data) { m_data = p_data; } + virtual void SetData(float* p_data) { m_data = p_data; } // vtable+0x1c - // vtable + 0x20 - virtual void EqualsImpl(float* p_data) = 0; - virtual float* GetData(); - virtual const float* GetData() const; - virtual void Clear() = 0; + // FUNCTION: LEGO1 0x10002070 + virtual void EqualsImpl(float* p_data) { memcpy(m_data, p_data, sizeof(float) * 2); } // vtable+0x20 - // vtable + 0x30 - virtual float Dot(Vector2Impl* p_a, float* p_b) const; - virtual float Dot(float* p_a, Vector2Impl* p_b) const; - virtual float Dot(Vector2Impl* p_a, Vector2Impl* p_b) const; - virtual float Dot(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002090 + virtual float* GetData() { return m_data; } // vtable+0x28 - // vtable + 0x40 - virtual float LenSquared() const = 0; - virtual int Unitize(); + // FUNCTION: LEGO1 0x100020a0 + virtual const float* GetData() const { return m_data; } // vtable+0x24 - // vtable + 0x48 - virtual void Add(Vector2Impl* p_other); - virtual void Add(float* p_other); - virtual void Add(float p_value); + // FUNCTION: LEGO1 0x100020b0 + virtual void Clear() { memset(m_data, 0, sizeof(float) * 2); } // vtable+0x2c - // vtable + 0x54 - virtual void Sub(Vector2Impl* p_other); - virtual void Sub(float* p_other); + // FUNCTION: LEGO1 0x100020d0 + virtual float Dot(float* p_a, float* p_b) const { return DotImpl(p_a, p_b); } // vtable+0x3c - // vtable + 0x5C - virtual void Mul(float* p_value); - virtual void Mul(Vector2Impl* p_other); - virtual void Mul(float& p_other); - virtual void Div(float& p_value); + // FUNCTION: LEGO1 0x100020f0 + virtual float Dot(Vector2* p_a, Vector2* p_b) const { return DotImpl(p_a->m_data, p_b->m_data); } // vtable+0x38 - // vtable + 0x6C - virtual void SetVector(Vector2Impl* p_other); - virtual void SetVector(float* p_other); + // FUNCTION: LEGO1 0x10002110 + virtual float Dot(float* p_a, Vector2* p_b) const { return DotImpl(p_a, p_b->m_data); } // vtable+0x34 + + // FUNCTION: LEGO1 0x10002130 + virtual float Dot(Vector2* p_a, float* p_b) const { return DotImpl(p_a->m_data, p_b); } // vtable+0x30 + + // FUNCTION: LEGO1 0x10002150 + virtual float LenSquared() const { return m_data[0] * m_data[0] + m_data[1] * m_data[1]; } // vtable+0x40 + + // FUNCTION: LEGO1 0x10002160 + virtual int Unitize() + { + float sq = LenSquared(); + if (sq > 0.0f) { + float root = sqrt(sq); + if (root > 0) { + DivScalarImpl(&root); + return 0; + } + } + return -1; + } // vtable+0x44 + + // FUNCTION: LEGO1 0x100021c0 + virtual void Add(float p_value) { AddImpl(p_value); } // vtable+0x50 + + // FUNCTION: LEGO1 0x100021d0 + virtual void Add(float* p_other) { AddImpl(p_other); } // vtable+0x4c + + // FUNCTION: LEGO1 0x100021e0 + virtual void Add(Vector2* p_other) { AddImpl(p_other->m_data); } // vtable+0x48 + + // FUNCTION: LEGO1 0x100021f0 + virtual void Sub(float* p_other) { SubImpl(p_other); } // vtable+0x58 + + // FUNCTION: LEGO1 0x10002200 + virtual void Sub(Vector2* p_other) { SubImpl(p_other->m_data); } // vtable+0x54 + + // FUNCTION: LEGO1 0x10002210 + virtual void Mul(float* p_other) { MulVectorImpl(p_other); } // vtable+0x64 + + // FUNCTION: LEGO1 0x10002220 + virtual void Mul(Vector2* p_other) { MulVectorImpl(p_other->m_data); } // vtable+0x60 + + // FUNCTION: LEGO1 0x10002230 + virtual void Mul(float& p_value) { MulScalarImpl(&p_value); } // vtable+0x5c + + // FUNCTION: LEGO1 0x10002240 + virtual void Div(float& p_value) { DivScalarImpl(&p_value); } // vtable+0x68 + + // FUNCTION: LEGO1 0x10002250 + virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70 + + // FUNCTION: LEGO1 0x10002260 + virtual void SetVector(Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c inline float& operator[](size_t idx) { return m_data[idx]; } inline const float& operator[](size_t idx) const { return m_data[idx]; } @@ -119,100 +149,261 @@ class Vector2Impl { }; // VTABLE: LEGO1 0x100d4518 -// SIZE 0x8 -class Vector3Impl : public Vector2Impl { +// SIZE 0x08 +class Vector3 : public Vector2 { public: - inline Vector3Impl(float* p_data) : Vector2Impl(p_data) {} + // FUNCTION: LEGO1 0x1001d150 + inline Vector3(float* p_data) : Vector2(p_data) {} - void AddScalarImpl(float p_value); + // Hack: Some code initializes a Vector3 from a (most likely) const float* source. + // Example: LegoCameraController::GetWorldUp + // Vector3 however is a class that can mutate its underlying source, making + // initialization with a const source fundamentally incompatible. + inline Vector3(const float* p_data) : Vector2((float*) p_data) {} - void AddVectorImpl(float* p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002270 + virtual void EqualsCrossImpl(float* p_a, float* p_b) + { + m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; + m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; + m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; + } // vtable+0x74 - void EqualsImpl(float* p_data); + // FUNCTION: LEGO1 0x100022c0 + virtual void EqualsCross(Vector3* p_a, Vector3* p_b) { EqualsCrossImpl(p_a->m_data, p_b->m_data); } // vtable+0x80 - void Clear(); + // FUNCTION: LEGO1 0x100022e0 + virtual void EqualsCross(Vector3* p_a, float* p_b) { EqualsCrossImpl(p_a->m_data, p_b); } // vtable+0x7c - float LenSquared() const; + // FUNCTION: LEGO1 0x10002300 + virtual void EqualsCross(float* p_a, Vector3* p_b) { EqualsCrossImpl(p_a, p_b->m_data); } // vtable+0x78 - // vtable + 0x74 - virtual void EqualsCrossImpl(float* p_a, float* p_b); - virtual void EqualsCross(float* p_a, Vector3Impl* p_b); - virtual void EqualsCross(Vector3Impl* p_a, float* p_b); - virtual void EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b); - virtual void EqualsScalar(float* p_value); + // FUNCTION: LEGO1 0x10003bf0 + virtual void EqualsScalar(float* p_value) + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + } // vtable+0x84 + + // Vector2 overrides + + // FUNCTION: LEGO1 0x10003a60 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10003a90 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10003ac0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10003b20 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10003af0 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10003b50 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10003b80 + virtual float DotImpl(float* p_a, float* p_b) const override + { + return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; + } // vtable+0x18 + + // FUNCTION: LEGO1 0x10003ba0 + virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10003bc0 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10003bd0 + virtual float LenSquared() const override + { + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; + } // vtable+0x40 inline void Fill(float p_value) { EqualsScalar(&p_value); } + + friend class Mx3DPointFloat; }; // VTABLE: LEGO1 0x100d45a0 // SIZE 0x8 -class Vector4Impl : public Vector3Impl { +class Vector4 : public Vector3 { public: - inline Vector4Impl(float* p_data) : Vector3Impl(p_data) {} + inline Vector4(float* p_data) : Vector3(p_data) {} - void AddScalarImpl(float p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void AddVectorImpl(float* p_value); - - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; - - void EqualsImpl(float* p_data); - - void Clear(); - - float LenSquared() const; - - void EqualsScalar(float* p_value); - - // vtable + 0x88 - virtual void SetMatrixProduct(Vector4Impl* p_a, float* p_b); - virtual void SetMatrixProductImpl(float* p_vec, float* p_mat); - virtual int NormalizeQuaternion(); - virtual void UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b); - - inline Vector4& GetVector() { return *((Vector4*) m_data); } -}; - -// VTABLE: LEGO1 0x100d4488 -// SIZE 0x14 -class Vector3Data : public Vector3Impl { -public: - inline Vector3Data() : Vector3Impl(m_vector.elements) {} - inline Vector3Data(float p_x, float p_y, float p_z) : Vector3Impl(m_vector.elements), m_vector(p_x, p_y, p_z) {} - - void CopyFrom(Vector3Data& p_other) + // FUNCTION: LEGO1 0x10002a40 + virtual void SetMatrixProduct(float* p_vec, float* p_mat) { - EqualsImpl(p_other.m_data); + m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; + m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; + m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; + m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; + } // vtable+0x8c - float* dest = m_vector.elements; - float* src = p_other.m_vector.elements; - for (size_t i = sizeof(m_vector) / sizeof(float); i > 0; --i) - *dest++ = *src++; + // FUNCTION: LEGO1 0x10002ae0 + virtual void SetMatrixProduct(Vector4* p_a, float* p_b) { SetMatrixProduct(p_a->m_data, p_b); } // vtable+0x88 + + inline virtual int NormalizeQuaternion(); // vtable+90 + inline virtual void UnknownQuaternionOp(Vector4* p_a, Vector4* p_b); // vtable+94 + + // Vector3 overrides + + // FUNCTION: LEGO1 0x10002870 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + m_data[3] += p_value[3]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x100028b0 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + m_data[3] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x100028f0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + m_data[3] -= p_value[3]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10002970 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + m_data[3] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10002930 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + m_data[3] *= p_value[3]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x100029b0 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + m_data[3] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x100029f0 + virtual float DotImpl(float* p_a, float* p_b) const override + { + return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); + } // vtable+0x18 + + // FUNCTION: LEGO1 0x10002a20 + virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 4); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10002b00 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002b20 + virtual float LenSquared() const override + { + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; + } // vtable+0x40 + + // FUNCTION: LEGO1 0x10002b40 + virtual void EqualsScalar(float* p_value) override + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + m_data[3] = *p_value; + } // vtable+0x84 +}; + +// Note close yet, included because I'm at least confident I know what operation +// it's trying to do. +// STUB: LEGO1 0x10002b70 +inline int Vector4::NormalizeQuaternion() +{ + float* v = m_data; + float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; + if (magnitude > 0.0f) { + float theta = v[3] * 0.5f; + v[3] = cos(theta); + float frac = sin(theta); + magnitude = frac / sqrt(magnitude); + v[0] *= magnitude; + v[1] *= magnitude; + v[2] *= magnitude; + return 0; } - inline void EqualsCross(Vector3Data& p_a, Vector3Data& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } + return -1; +} -private: - Vector3 m_vector; -}; +// FUNCTION: LEGO1 0x10002bf0 +inline void Vector4::UnknownQuaternionOp(Vector4* p_a, Vector4* p_b) +{ + float* bDat = p_b->m_data; + float* aDat = p_a->m_data; -// VTABLE: LEGO1 0x100d41e8 -// SIZE 0x18 -class Vector4Data : public Vector4Impl { -public: - inline Vector4Data() : Vector4Impl(m_vector.elements) {} + this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); + this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; + this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; + this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; -private: - Vector4 m_vector; -}; + 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]; +} #endif // VECTOR_H diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp index 5084c2ca..9e000ba8 100644 --- a/LEGO1/tgl/d3drm/camera.cpp +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -12,7 +12,7 @@ void* CameraImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3700 -Result CameraImpl::SetTransformation(const FloatMatrix4& matrix) +Result CameraImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* pTransformation = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp index 022dc757..4b966cd2 100644 --- a/LEGO1/tgl/d3drm/group.cpp +++ b/LEGO1/tgl/d3drm/group.cpp @@ -9,7 +9,7 @@ void* GroupImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a31e0 -Result GroupImpl::SetTransformation(const FloatMatrix4& matrix) +Result GroupImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 4c76a365..0c1e869d 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -209,7 +209,7 @@ class CameraImpl : public Camera { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -234,7 +234,7 @@ class LightImpl : public Light { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -300,7 +300,7 @@ class GroupImpl : public Group { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b, float a); // vtable+0x10 @@ -474,7 +474,7 @@ inline D3DRMPROJECTIONTYPE Translate(ProjectionType tglProjectionType) // Yes this function serves no purpose, originally they intended it to // convert from doubles to floats but ended up using floats throughout // the software stack. -inline D3DRMMATRIX4D* Translate(const FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) +inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) { for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) { for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) { diff --git a/LEGO1/tgl/d3drm/light.cpp b/LEGO1/tgl/d3drm/light.cpp index 5ceafa4b..dfc23b44 100644 --- a/LEGO1/tgl/d3drm/light.cpp +++ b/LEGO1/tgl/d3drm/light.cpp @@ -12,7 +12,7 @@ void* LightImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3780 -Result LightImpl::SetTransformation(const FloatMatrix4& matrix) +Result LightImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index dfc18f3f..3e09ad5a 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -222,13 +222,13 @@ class View : public Object { // VTABLE 0x100dbae8 class Camera : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; }; // VTABLE 0x100dbb08 class Light : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; virtual Result SetColor(float r, float g, float b) = 0; }; @@ -252,7 +252,7 @@ class Mesh : public Object { // VTABLE 0x100dbaa0 class Group : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; virtual Result SetColor(float r, float g, float b, float a) = 0; virtual Result SetTexture(const Texture*) = 0; virtual Result GetTexture(Texture*&) = 0; diff --git a/LEGO1/tgl/tglvector.h b/LEGO1/tgl/tglvector.h index 78255937..8612724f 100644 --- a/LEGO1/tgl/tglvector.h +++ b/LEGO1/tgl/tglvector.h @@ -1,8 +1,5 @@ #ifndef _tglVector_h #define _tglVector_h -// Note: This file is almost an exact copy of the one from -// the leak but using floats instead of doubles, hence the -// strange formatting in some places. #include "math.h" // sin() in RotateAroundY() @@ -26,253 +23,7 @@ inline float RadiansToDegrees(float radians) return (radians / Constant::Pi) * 180.0; } -////////////////////////////////////////////////////////////////////////////// -// -// Array - -template -class Array { -public: - Array() {} - Array(const Array& rArray) { *this = rArray; } - ~Array() {} - - const T& operator[](int i) const { return m_elements[i]; }; - T& operator[](int i) { return m_elements[i]; }; - - Array& operator=(const Array&); - void operator+=(const Array&); - -protected: - T m_elements[N]; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// Array implementation - -template -inline Array& Array::operator=(const Array& rArray) -{ - int i; - - for (i = 0; i < N; i++) { - m_elements[i] = rArray.m_elements[i]; - } - - return *this; -} - -template -inline void Array::operator+=(const Array& rArray) -{ - int i; - - for (i = 0; i < N; i++) { - m_elements[i] += rArray.m_elements[i]; - } -} - -////////////////////////////////////////////////////////////////////////////// -// -// FloatMatrix4 - -class FloatMatrix4 : public Array, 4> { -public: - FloatMatrix4() {} - FloatMatrix4(const FloatMatrix4& rMatrix) { *this = rMatrix; } - FloatMatrix4(const FloatMatrix4&, const FloatMatrix4&); - - void operator*=(const FloatMatrix4&); -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FloatMatrix4 implementation - -inline FloatMatrix4::FloatMatrix4(const FloatMatrix4& rMatrix1, const FloatMatrix4& rMatrix2) -{ - for (int row = 0; row < 4; row++) { - for (int column = 0; column < 4; column++) { - float element = 0; - - for (int i = 0; i < 4; i++) { - element += rMatrix1[row][i] * rMatrix2[i][column]; - } - - m_elements[row][column] = element; - } - } -} - -inline void FloatMatrix4::operator*=(const FloatMatrix4& rMatrix) -{ - FloatMatrix4 temp(*this, rMatrix); - - // *this = FloatMatrix4(*this, rMatrix); - *this = temp; -} - -////////////////////////////////////////////////////////////////////////////// -// -// Transformation matrices - -class Translation : public FloatMatrix4 { -public: - Translation(const float[3]); - Translation(float x, float y, float z); - -protected: - void Init(float x, float y, float z); -}; - -class Scale : public FloatMatrix4 { -public: - Scale(const float[3]); - Scale(float x, float y, float z); - Scale(float); - -protected: - void Init(float x, float y, float z); -}; - -class RotationX : public FloatMatrix4 { -public: - RotationX(float radians); -}; - -class RotationY : public FloatMatrix4 { -public: - RotationY(float radians); -}; -////////////////////////////////////////////////////////////////////////////// -// -// Transformation matrices implementation - -inline Translation::Translation(const float vector[3]) -{ - Init(vector[0], vector[1], vector[2]); -} - -inline Translation::Translation(float x, float y, float z) -{ - Init(x, y, z); -} - -inline void Translation::Init(float x, float y, float z) -{ - m_elements[0][0] = 1; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = 1; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = 0; - m_elements[2][2] = 1; - m_elements[2][3] = 0; - - m_elements[3][0] = x; - m_elements[3][1] = y; - m_elements[3][2] = z; - m_elements[3][3] = 1; -} - -inline Scale::Scale(const float vector[3]) -{ - Init(vector[0], vector[1], vector[2]); -} - -inline Scale::Scale(float x, float y, float z) -{ - Init(x, y, z); -} - -inline Scale::Scale(float scale) -{ - Init(scale, scale, scale); -} - -inline void Scale::Init(float x, float y, float z) -{ - m_elements[0][0] = x; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = y; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = 0; - m_elements[2][2] = z; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -inline RotationX::RotationX(float radians) -{ - float cosRadians = cos(radians); - float sinRadians = sin(radians); - - m_elements[0][0] = 1; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = cosRadians; - m_elements[1][2] = -sinRadians; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = sinRadians; - m_elements[2][2] = cosRadians; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -inline RotationY::RotationY(float radians) -{ - float cosRadians = cos(radians); - float sinRadians = sin(radians); - - m_elements[0][0] = cosRadians; - m_elements[0][1] = 0; - m_elements[0][2] = sinRadians; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = 1; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = -sinRadians; - m_elements[2][1] = 0; - m_elements[2][2] = cosRadians; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -////////////////////////////////////////////////////////////////////////////// +typedef float FloatMatrix4[4][4]; } // namespace Tgl diff --git a/LEGO1/viewmanager/viewroi.cpp b/LEGO1/viewmanager/viewroi.cpp index 523814a2..ff846394 100644 --- a/LEGO1/viewmanager/viewroi.cpp +++ b/LEGO1/viewmanager/viewroi.cpp @@ -2,6 +2,8 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(ViewROI, 0xe0) // GLOBAL: LEGO1 0x101013d8 @@ -26,13 +28,15 @@ Tgl::Group* ViewROI::GetGeometry() } // FUNCTION: LEGO1 0x100a9ee0 -void ViewROI::UpdateWorldData(const Matrix4Data& parent2world) +void ViewROI::UpdateWorldData(const MxMatrix& parent2world) { OrientableROI::UpdateWorldData(parent2world); + if (geometry) { - Tgl::FloatMatrix4 mat; - SETMAT4(mat, m_local2world.GetMatrix()); - Tgl::Result result = geometry->SetTransformation(mat); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + SETMAT4(in, m_local2world); + Tgl::Result result = geometry->SetTransformation(matrix); // assert(Tgl::Succeeded(result)); } } diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h index 02d69ab5..7157033a 100644 --- a/LEGO1/viewmanager/viewroi.h +++ b/LEGO1/viewmanager/viewroi.h @@ -52,7 +52,7 @@ class ViewROI : public OrientableROI { protected: Tgl::Group* geometry; - void UpdateWorldData(const Matrix4Data& parent2world); + void UpdateWorldData(const MxMatrix& parent2world); }; // SYNTHETIC: LEGO1 0x100aa250