From ada83989b13ce816e7e1aff2531b89acd20677c2 Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Thu, 11 Apr 2024 07:35:15 -0400 Subject: [PATCH] Implement LegoPathActor::VTable0x88 (#787) * Implement LegoPathActor::VTable0x88 * Implement FUN_1002ddc0 * Fixes and match * refac --------- Co-authored-by: Christian Semmler --- CMakeLists.txt | 1 + LEGO1/lego/legoomni/include/legopathactor.h | 12 ++- .../lego/legoomni/include/legopathboundary.h | 32 ++++++-- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 4 +- .../lego/legoomni/src/paths/legopathactor.cpp | 77 ++++++++++++++++++- .../legoomni/src/paths/legopathboundary.cpp | 9 +++ LEGO1/lego/sources/geom/legoedge.h | 3 + .../lego/sources/geom/legounkown100db7f4.cpp | 3 + LEGO1/lego/sources/geom/legounkown100db7f4.h | 33 ++++++++ LEGO1/lego/sources/geom/legoweedge.h | 1 + LEGO1/lego/sources/geom/legowegedge.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 2 - LEGO1/realtime/vector.h | 2 + 13 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 LEGO1/lego/sources/geom/legounkown100db7f4.cpp create mode 100644 LEGO1/lego/sources/geom/legounkown100db7f4.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 37d29eb3..1882ba76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ add_library(geom STATIC LEGO1/lego/sources/geom/legoedge.cpp LEGO1/lego/sources/geom/legomesh.cpp LEGO1/lego/sources/geom/legosphere.cpp + LEGO1/lego/sources/geom/legounkown100db7f4.cpp LEGO1/lego/sources/geom/legovertex.cpp LEGO1/lego/sources/geom/legoweedge.cpp LEGO1/lego/sources/geom/legowegedge.cpp diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index df1bb21c..176a7278 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -1,6 +1,7 @@ #ifndef LEGOPATHACTOR_H #define LEGOPATHACTOR_H +#include "geom/legounkown100db7f4.h" #include "legoactor.h" #include "legopathboundary.h" #include "misc/legounknown.h" @@ -48,7 +49,14 @@ class LegoPathActor : public LegoActor { Vector3& p_point4 ); // vtable+0x80 virtual void VTable0x84(); // vtable+0x84 - virtual void VTable0x88(); // vtable+0x88 + virtual MxResult VTable0x88( + LegoPathBoundary* p_boundary, + float p_time, + LegoEdge& p_srcEdge, + float p_srcScale, + LegoUnknown100db7f4& p_destEdge, + float p_destScale + ); // vtable+0x88 virtual void VTable0x8c(); // vtable+0x8c // FUNCTION: LEGO1 0x10002d40 @@ -110,7 +118,7 @@ class LegoPathActor : public LegoActor { LegoUnknown m_unk0x8c; // 0x8c MxU32 m_state; // 0xdc LegoEdge* m_destEdge; // 0xe0 - undefined4 m_unk0xe4; // 0xe4 + MxFloat m_unk0xe4; // 0xe4 undefined m_unk0xe8; // 0xe8 undefined m_unk0xe9; // 0xe9 MxBool m_userNavFlag; // 0xea diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h index 763059f5..8a8a5759 100644 --- a/LEGO1/lego/legoomni/include/legopathboundary.h +++ b/LEGO1/lego/legoomni/include/legopathboundary.h @@ -6,14 +6,20 @@ #include "mxstl/stlcompat.h" #include "mxtypes.h" -struct LegoPathBoundaryComparator { - MxBool operator()(const undefined*, const undefined*) const { return 0; } +class LegoPathActor; + +struct LegoPathActorSetCompare { + MxU32 operator()(const LegoPathActor* p_lhs, const LegoPathActor* p_rhs) const + { + return (MxS32) p_lhs < (MxS32) p_rhs; + } }; struct LegoAnimPresenterSetCompare { - MxBool operator()(const LegoAnimPresenter*, const LegoAnimPresenter*) const { return 0; } + MxBool operator()(const LegoAnimPresenter* p_lhs, const LegoAnimPresenter* p_rhs) const { return 0; } }; +typedef set LegoPathActorSet; typedef set LegoAnimPresenterSet; // VTABLE: LEGO1 0x100d8618 @@ -22,16 +28,28 @@ class LegoPathBoundary : public LegoWEGEdge { public: LegoPathBoundary(); - // STUB: LEGO1 0x10047a80 - // LegoPathBoundary::`scalar deleting destructor' + MxResult AddActor(LegoPathActor* p_actor); + inline LegoAnimPresenterSet* GetUnknown0x64() { return &m_unk0x64; } + // STUB: LEGO1 0x10047a80 + // LegoPathBoundary::`scalar deleting destructor' + private: - map m_unk0x54; // 0x54 - LegoAnimPresenterSet m_unk0x64; // 0x64 + LegoPathActorSet m_unk0x54; // 0x54 + LegoAnimPresenterSet m_unk0x64; // 0x64 }; // clang-format off +// TEMPLATE: LEGO1 0x10045d80 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::iterator::_Dec + +// TEMPLATE: LEGO1 0x10045dd0 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::_Insert + +// GLOBAL: LEGO1 0x100f11a4 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::_Nil + // GLOBAL: LEGO1 0x100f3200 // _Tree >::_Kfn,LegoAnimPresenterSetCompare,allocator >::_Nil // clang-format on diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index dacb7f82..ca3a5c98 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -217,8 +217,8 @@ MxU32 Helicopter::VTable0xd4(LegoControlManagerEvent& p_param) lookat.Add(&loc); Mx3DPointFloat v68, v7c, v90(0, 1, 0), va4; v68 = m_world->GetCamera()->GetWorldUp(); - va4.EqualsCross(v68, dir); - v7c.EqualsCross(va4, v90); + va4.EqualsCross(&v68, &dir); + v7c.EqualsCross(&va4, &v90); if (ret) { if (((Act3*) m_world)->FUN_100727e0(m_controller, loc, dir, v7c)) { break; diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 48b3ceaf..37ca19e7 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -52,10 +52,81 @@ MxResult LegoPathActor::VTable0x80(Vector3& p_point1, Vector3& p_point2, Vector3 return FAILURE; } -// STUB: LEGO1 0x1002d9c0 -void LegoPathActor::VTable0x88() +// FUNCTION: LEGO1 0x1002d9c0 +MxResult LegoPathActor::VTable0x88( + LegoPathBoundary* p_boundary, + float p_time, + LegoEdge& p_srcEdge, + float p_srcScale, + LegoUnknown100db7f4& p_destEdge, + float p_destScale +) { - // TODO + Vector3* v1 = p_srcEdge.GetOpposingPoint(p_boundary); + Vector3* v2 = p_srcEdge.GetPoint(p_boundary); + Vector3* v3 = p_destEdge.GetOpposingPoint(p_boundary); + Vector3* v4 = p_destEdge.GetPoint(p_boundary); + + Mx3DPointFloat p1, p2, p3, p4, p5; + + p1 = *v2; + ((Vector3&) p1).Sub(v1); + ((Vector3&) p1).Mul(p_srcScale); + ((Vector3&) p1).Add(v1); + + p2 = *v4; + ((Vector3&) p2).Sub(v3); + ((Vector3&) p2).Mul(p_destScale); + ((Vector3&) p2).Add(v3); + + m_boundary = p_boundary; + m_destEdge = &p_destEdge; + m_unk0xe4 = p_destScale; + m_unk0x7c = 0; + m_lastTime = p_time; + m_actorTime = p_time; + p_destEdge.FUN_1002ddc0(*p_boundary, p3); + + p4 = p2; + ((Vector3&) p4).Sub(&p1); + p4.Unitize(); + + MxMatrix matrix; + Vector3 pos(matrix[3]); + Vector3 dir(matrix[2]); + Vector3 up(matrix[1]); + Vector3 right(matrix[0]); + + matrix.SetIdentity(); + pos = p1; + dir = p4; + up = *m_boundary->GetUnknown0x14(); // TODO + + if (!m_cameraFlag || !m_userNavFlag) { + ((Vector3&) dir).Mul(-1.0f); + } + + right.EqualsCross(&up, &dir); + m_roi->FUN_100a46b0(matrix); + + if (!m_cameraFlag || !m_userNavFlag) { + p5.EqualsCross(p_boundary->GetUnknown0x14(), &p3); + p5.Unitize(); + + if (VTable0x80(p1, p4, p2, p5) == SUCCESS) { + m_boundary->AddActor(this); + } + else { + return FAILURE; + } + } + else { + m_boundary->AddActor(this); + FUN_10010c30(); + } + + m_unk0xec = m_roi->GetLocal2World(); + return SUCCESS; } // STUB: LEGO1 0x1002de10 diff --git a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp index 641ece72..19afed47 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp @@ -1,6 +1,7 @@ #include "legopathboundary.h" #include "decomp.h" +#include "legopathactor.h" DECOMP_SIZE_ASSERT(LegoPathBoundary, 0x74) @@ -8,3 +9,11 @@ DECOMP_SIZE_ASSERT(LegoPathBoundary, 0x74) LegoPathBoundary::LegoPathBoundary() { } + +// FUNCTION: LEGO1 0x100573f0 +MxResult LegoPathBoundary::AddActor(LegoPathActor* p_actor) +{ + m_unk0x54.insert(p_actor); + p_actor->SetBoundary(this); + return SUCCESS; +} diff --git a/LEGO1/lego/sources/geom/legoedge.h b/LEGO1/lego/sources/geom/legoedge.h index 81396dc4..a3b71b64 100644 --- a/LEGO1/lego/sources/geom/legoedge.h +++ b/LEGO1/lego/sources/geom/legoedge.h @@ -1,6 +1,7 @@ #ifndef __LEGOEDGE_H #define __LEGOEDGE_H +#include "misc/legotypes.h" #include "realtime/vector.h" class LegoWEEdge; @@ -16,6 +17,8 @@ struct LegoEdge { Vector3* GetOpposingPoint(LegoWEEdge* face); Vector3* GetPoint(LegoWEEdge* face); + LegoResult FUN_1002ddc0(LegoWEEdge* p_face, Vector3& p_point); + // SYNTHETIC: LEGO1 0x1009a4a0 // LegoEdge::`scalar deleting destructor' diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.cpp b/LEGO1/lego/sources/geom/legounkown100db7f4.cpp new file mode 100644 index 00000000..79ba66cb --- /dev/null +++ b/LEGO1/lego/sources/geom/legounkown100db7f4.cpp @@ -0,0 +1,3 @@ +#include "legounkown100db7f4.h" + +DECOMP_SIZE_ASSERT(LegoUnknown100db7f4, 0x40) diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.h b/LEGO1/lego/sources/geom/legounkown100db7f4.h new file mode 100644 index 00000000..d1cfa324 --- /dev/null +++ b/LEGO1/lego/sources/geom/legounkown100db7f4.h @@ -0,0 +1,33 @@ +#ifndef __LEGOUNKNOWN100DB7F4_H +#define __LEGOUNKNOWN100DB7F4_H + +#include "legoedge.h" +#include "legoweedge.h" +#include "mxgeometry/mxgeometry3d.h" + +// VTABLE: LEGO1 0x100db7f4 +// SIZE 0x40 +class LegoUnknown100db7f4 : public LegoEdge { +public: + // FUNCTION: LEGO1 0x1002ddc0 + LegoResult FUN_1002ddc0(LegoWEEdge& p_f, Vector3& p_point) + { + if (p_f.IsEqual(*m_faceA)) { + p_point[0] = -m_unk0x28[0]; + p_point[1] = -m_unk0x28[1]; + p_point[2] = -m_unk0x28[2]; + } + else { + p_point = m_unk0x28; + } + + return SUCCESS; + } + +private: + LegoU16 m_unk0x24; // 0x24 + Mx3DPointFloat m_unk0x28; // 0x28 + LegoU32 m_unk0x3c; // 0x3c +}; + +#endif // __LEGOUNKNOWN100DB7F4_H diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index 9320db74..f02b0cac 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -15,6 +15,7 @@ class LegoWEEdge { virtual LegoResult VTable0x04(); // vtable+0x04 inline LegoU8 GetNumEdges() { return m_numEdges; } + inline LegoU32 IsEqual(LegoWEEdge& p_other) { return this == &p_other; } // SYNTHETIC: LEGO1 0x1009a570 // LegoWEEdge::`scalar deleting destructor' diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index c2838123..34a285b3 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -15,6 +15,7 @@ class LegoWEGEdge : public LegoWEEdge { LegoResult VTable0x04() override; // vtable+0x04 inline LegoU32 GetFlag0x10() { return m_unk0x0c & 0x10 ? FALSE : TRUE; } + inline Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } inline Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } // SYNTHETIC: LEGO1 0x1009a7e0 diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 6b822ae0..5d6d3acc 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -38,8 +38,6 @@ class Mx3DPointFloat : public Vector3 { // SYNTHETIC: LEGO1 0x10010c00 // Mx3DPointFloat::operator= - inline void EqualsCross(Mx3DPointFloat& p_a, Mx3DPointFloat& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } - private: float m_elements[3]; // 0x08 }; diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 746008f2..84060d3b 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -101,6 +101,7 @@ class Vector2 { virtual int Unitize() { float sq = LenSquared(); + if (sq > 0.0f) { float root = sqrt(sq); if (root > 0) { @@ -108,6 +109,7 @@ class Vector2 { return 0; } } + return -1; } // vtable+0x44