From 90c687bde0e9dd82fb4e928445fda8b49403daea Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 17 Dec 2024 15:16:00 -0700 Subject: [PATCH] Implement/match `Act3Brickster::FUN_10042300` (#1238) * Implement/match `Act3Brickster::FUN_10042300` * Add comment about assignment operator * Add another comment * Fix * add back BETA annotation --- .../legoomni/include/legopathcontroller.h | 4 +- LEGO1/lego/legoomni/src/actors/act3actors.cpp | 100 +++++++++++++++++- .../legoomni/src/paths/legopathcontroller.cpp | 62 ----------- LEGO1/lego/sources/geom/legoedge.h | 6 ++ LEGO1/lego/sources/geom/legounkown100db7f4.h | 64 +++++++++++ LEGO1/mxgeometry/mxgeometry3d.h | 3 + LEGO1/realtime/vector.h | 17 +++ 7 files changed, 188 insertions(+), 68 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 85ef1f9f..37096cc2 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -22,9 +22,7 @@ class Vector3; // VTABLE: LEGO1 0x100d7da8 // SIZE 0x40 -struct LegoPathCtrlEdge : public LegoUnknown100db7f4 { - inline MxU32 FUN_10048c40(const Vector3& p_position); -}; +struct LegoPathCtrlEdge : public LegoUnknown100db7f4 {}; struct LegoPathCtrlEdgeCompare { MxU32 operator()(const LegoPathCtrlEdge* p_lhs, const LegoPathCtrlEdge* p_rhs) const diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp index 306a6e3b..d29ef0fc 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -613,11 +613,105 @@ MxResult Act3Brickster::FUN_100417c0() return SUCCESS; } -// STUB: LEGO1 0x10042300 -// STUB: BETA10 0x1001b017 +// FUNCTION: LEGO1 0x10042300 +// FUNCTION: BETA10 0x1001b017 MxS32 Act3Brickster::FUN_10042300() { - // TODO + // TODO: Has poor inlining, can be fixed by changing the assignment operator in vector.h + // See extended comment in vector.h for operator= + + Act3* a3 = (Act3*) m_world; + + assert(a3 && a3->m_cop1 && a3->m_cop2); + assert(a3->m_cop1->GetROI() && a3->m_cop2->GetROI() && GetROI()); + + Mx3DPointFloat local64[2]; + Mx3DPointFloat local38; + Mx3DPointFloat local18; + + MxS32 local1c = 0; + float local24[2]; + + local64[0] = a3->m_cop1->GetROI()->GetLocal2World()[3]; + local64[1] = a3->m_cop2->GetROI()->GetLocal2World()[3]; + local38 = GetROI()->GetLocal2World()[3]; + + local18 = local64[0]; + local18 -= local38; + local24[0] = local18.LenSquared(); + + local18 = local64[1]; + local18 -= local38; + local24[1] = local18.LenSquared(); + + if (local24[1] < local24[0]) { + local1c = 1; + } + + if (local24[local1c] < 225.0f) { + m_unk0x38 = 8; + + if (m_grec != NULL) { + delete m_grec; + m_grec = NULL; + } + + if (m_pInfo != NULL) { + m_pInfo = NULL; + } + + assert(m_boundary && m_destEdge && m_roi); + + LegoPathBoundary* boundaries[2]; + LegoUnknown100db7f4* maxE = NULL; + boundaries[0] = m_boundary; + + if (m_destEdge->FUN_10048c40(local38)) { + boundaries[1] = (LegoPathBoundary*) m_destEdge->OtherFace(m_boundary); + } + else { + boundaries[1] = NULL; + } + + float local78, local98; + for (MxS32 i = 0; i < (MxS32) sizeOfArray(boundaries); i++) { + if (boundaries[i] != NULL) { + for (MxS32 j = 0; j < boundaries[i]->GetNumEdges(); j++) { + LegoUnknown100db7f4* e = boundaries[i]->GetEdges()[j]; + + if (e->GetMask0x03()) { + Mx3DPointFloat local94(*e->GetPointA()); + local94 += *e->GetPointB(); + local94 /= 2.0f; + + local18 = local94; + local18 -= local64[local1c]; + local98 = local18.LenSquared(); + + local94 -= local38; + local18 = local64[local1c]; + local18 -= local38; + + if (maxE == NULL || (local18.Dot(&local94, &local18) < 0.0f && local78 < local98)) { + maxE = e; + m_boundary = boundaries[i]; + local78 = local98; + } + } + } + } + } + + assert(maxE); + m_destEdge = maxE; + + if (m_boundary != boundaries[0]) { + m_unk0xe4 = 1.0 - m_unk0xe4; + } + + VTable0x9c(); + } + return -1; } diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index b17f1508..887d19f7 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -920,68 +920,6 @@ MxResult LegoPathController::FUN_10048310( return FAILURE; } -// FUNCTION: LEGO1 0x10048c40 -// FUNCTION: BETA10 0x1001cc90 -inline MxU32 LegoPathCtrlEdge::FUN_10048c40(const Vector3& p_position) -{ - MxFloat localc, local10; - MxU32 result = FALSE; - - if (m_unk0x28[0] > 0.001 || m_unk0x28[0] < -0.001) { - localc = (p_position[0] - (*m_pointA)[0]) / m_unk0x28[0]; - - if (localc < 0 || localc > 1) { - return FALSE; - } - - result = TRUE; - } - else { - if (p_position[0] > (*m_pointA)[0] + 0.001 || p_position[0] < (*m_pointA)[0] - 0.001) { - return FALSE; - } - } - - if (m_unk0x28[1] > 0.001 || m_unk0x28[1] < -0.001) { - local10 = (p_position[1] - (*m_pointA)[1]) / m_unk0x28[1]; - - if (result) { - if (localc > local10 + 0.001 || localc < local10 - 0.001) { - return FALSE; - } - } - else { - result = TRUE; - localc = local10; - } - } - else { - if (p_position[1] > (*m_pointA)[1] + 0.001 || p_position[1] < (*m_pointA)[1] - 0.001) { - return FALSE; - } - } - - if (m_unk0x28[2] > 0.001 || m_unk0x28[2] < -0.001) { - local10 = (p_position[2] - (*m_pointA)[2]) / m_unk0x28[2]; - - if (result) { - if (localc > local10 + 0.001 || localc < local10 - 0.001) { - return FALSE; - } - } - else { - return TRUE; - } - } - else { - if (p_position[2] > (*m_pointA)[2] + 0.001 || p_position[2] < (*m_pointA)[2] - 0.001) { - return FALSE; - } - } - - return TRUE; -} - // FUNCTION: LEGO1 0x1004a240 // FUNCTION: BETA10 0x100b9160 MxS32 LegoPathController::FUN_1004a240( diff --git a/LEGO1/lego/sources/geom/legoedge.h b/LEGO1/lego/sources/geom/legoedge.h index 753d6e11..43740bda 100644 --- a/LEGO1/lego/sources/geom/legoedge.h +++ b/LEGO1/lego/sources/geom/legoedge.h @@ -19,6 +19,12 @@ struct LegoEdge { LegoResult FUN_1002ddc0(LegoWEEdge& p_face, Vector3& p_point); + // FUNCTION: BETA10 0x1001cb80 + Vector3* GetPointA() { return m_pointA; } + + // FUNCTION: BETA10 0x1001cbb0 + Vector3* GetPointB() { return m_pointB; } + // SYNTHETIC: LEGO1 0x1009a4a0 // LegoEdge::`scalar deleting destructor' diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.h b/LEGO1/lego/sources/geom/legounkown100db7f4.h index bd19ee78..ef525932 100644 --- a/LEGO1/lego/sources/geom/legounkown100db7f4.h +++ b/LEGO1/lego/sources/geom/legounkown100db7f4.h @@ -93,6 +93,8 @@ struct LegoUnknown100db7f4 : public LegoEdge { // FUNCTION: BETA10 0x1001cc60 LegoU32 GetMask0x03() { return m_flags & (c_bit1 | c_bit2); } + inline LegoU32 FUN_10048c40(const Vector3& p_position); + // SYNTHETIC: LEGO1 0x1009a6c0 // LegoUnknown100db7f4::`scalar deleting destructor' @@ -101,4 +103,66 @@ struct LegoUnknown100db7f4 : public LegoEdge { float m_unk0x3c; // 0x3c }; +// FUNCTION: LEGO1 0x10048c40 +// FUNCTION: BETA10 0x1001cc90 +inline LegoU32 LegoUnknown100db7f4::FUN_10048c40(const Vector3& p_position) +{ + LegoFloat localc, local10; + LegoU32 result = FALSE; + + if (m_unk0x28[0] > 0.001 || m_unk0x28[0] < -0.001) { + localc = (p_position[0] - (*m_pointA)[0]) / m_unk0x28[0]; + + if (localc < 0 || localc > 1) { + return FALSE; + } + + result = TRUE; + } + else { + if (p_position[0] > (*m_pointA)[0] + 0.001 || p_position[0] < (*m_pointA)[0] - 0.001) { + return FALSE; + } + } + + if (m_unk0x28[1] > 0.001 || m_unk0x28[1] < -0.001) { + local10 = (p_position[1] - (*m_pointA)[1]) / m_unk0x28[1]; + + if (result) { + if (localc > local10 + 0.001 || localc < local10 - 0.001) { + return FALSE; + } + } + else { + result = TRUE; + localc = local10; + } + } + else { + if (p_position[1] > (*m_pointA)[1] + 0.001 || p_position[1] < (*m_pointA)[1] - 0.001) { + return FALSE; + } + } + + if (m_unk0x28[2] > 0.001 || m_unk0x28[2] < -0.001) { + local10 = (p_position[2] - (*m_pointA)[2]) / m_unk0x28[2]; + + if (result) { + if (localc > local10 + 0.001 || localc < local10 - 0.001) { + return FALSE; + } + } + else { + return TRUE; + } + } + else { + if (p_position[2] > (*m_pointA)[2] + 0.001 || p_position[2] < (*m_pointA)[2] - 0.001) { + return FALSE; + } + } + + return TRUE; +} + #endif // __LEGOUNKNOWN100DB7F4_H diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 1cfa82ac..99a44fd3 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -33,6 +33,9 @@ class Mx3DPointFloat : public Vector3 { // FUNCTION: LEGO1 0x10003c10 virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 + // FUNCTION: BETA10 0x10015240 + // ??4Mx3DPointFloat@@QAEAAV0@ABV0@@Z + // FUNCTION: BETA10 0x10013460 float& operator[](int idx) { return m_data[idx]; } diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 02b8d53b..f609c7af 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -151,8 +151,25 @@ class Vector2 { virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70 // FUNCTION: LEGO1 0x10002260 + // FUNCTION: BETA10 0x100110c0 virtual void SetVector(const Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c + // Note: it's unclear whether Vector3::operator= has been defined explicitly + // with the same function body as Vector2& operator=. The BETA indicates that; + // however, it makes LEGO1 0x10010be0 disappear and worsens matches in + // at least these functions: + // LEGO1 0x100109b0 + // LEGO1 0x10023130 + // LEGO1 0x1002de10 + // LEGO1 0x10050a80 + // LEGO1 0x10053980 + // LEGO1 0x100648f0 + // LEGO1 0x10064b50 + // LEGO1 0x10084030 + // LEGO1 0x100a9410 + // However, defining it as in the BETA improves at least these functions: + // LEGO1 0x10042300 + // SYNTHETIC: LEGO1 0x10010be0 // SYNTHETIC: BETA10 0x100121e0 // Vector3::operator=