diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1a50eda6..61736b13 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -139,7 +139,7 @@ jobs: run: | reccmp-reccmp -S CONFIGPROGRESS.SVG --svg-icon assets/config.png --target CONFIG | tee CONFIGPROGRESS.TXT reccmp-reccmp -S ISLEPROGRESS.SVG --svg-icon assets/isle.png --target ISLE | tee ISLEPROGRESS.TXT - reccmp-reccmp -S LEGO1PROGRESS.SVG -T 4357 --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT + reccmp-reccmp -S LEGO1PROGRESS.SVG -T 4358 --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT - name: Compare Accuracy With Current Master shell: bash diff --git a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp index 8c98dd87..87f1cbdc 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp @@ -48,7 +48,7 @@ void LegoPathBoundary::FUN_100575b0(Vector3& p_point1, Vector3& p_point2, LegoPa { Vector3* ccwV = NULL; - if (m_unk0x48 > 0 && m_unk0x50 != NULL) { + if (m_numTriggers > 0 && m_unk0x50 != NULL) { ccwV = m_edges[0]->CCWVertex(*this); Mx3DPointFloat v; @@ -61,7 +61,7 @@ void LegoPathBoundary::FUN_100575b0(Vector3& p_point1, Vector3& p_point2, LegoPa float dot2 = v.Dot(&v, m_unk0x50); if (dot2 > dot1) { - for (MxS32 i = 0; i < m_unk0x48; i++) { + for (MxS32 i = 0; i < m_numTriggers; i++) { LegoPathStruct* s = m_pathTrigger[i].m_pathStruct; if (m_pathTrigger[i].m_unk0x08 >= dot1 && m_pathTrigger[i].m_unk0x08 < dot2) { @@ -70,7 +70,7 @@ void LegoPathBoundary::FUN_100575b0(Vector3& p_point1, Vector3& p_point2, LegoPa } } else if (dot2 < dot1) { - for (MxS32 i = 0; i < m_unk0x48; i++) { + for (MxS32 i = 0; i < m_numTriggers; i++) { LegoPathStruct* s = m_pathTrigger[i].m_pathStruct; if (m_pathTrigger[i].m_unk0x08 >= dot2 && m_pathTrigger[i].m_unk0x08 < dot1) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index 887d19f7..a36a9a53 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -673,15 +673,15 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage) return FAILURE; } - if (p_storage->Read(&boundary.m_unk0x48, sizeof(boundary.m_unk0x48)) != SUCCESS) { + if (p_storage->Read(&boundary.m_numTriggers, sizeof(boundary.m_numTriggers)) != SUCCESS) { return FAILURE; } - if (boundary.m_unk0x48 > 0) { + if (boundary.m_numTriggers > 0) { boundary.m_unk0x50 = new Mx3DPointFloat; - boundary.m_pathTrigger = new LegoWEGEdge::PathWithTrigger[boundary.m_unk0x48]; + boundary.m_pathTrigger = new LegoWEGEdge::PathWithTrigger[boundary.m_numTriggers]; - for (j = 0; j < boundary.m_unk0x48; j++) { + for (j = 0; j < boundary.m_numTriggers; j++) { if (p_storage->Read(&s, sizeof(s)) != SUCCESS) { return FAILURE; } diff --git a/LEGO1/lego/sources/geom/legoedge.h b/LEGO1/lego/sources/geom/legoedge.h index 43740bda..881f9325 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 0x10184170 + LegoWEEdge* GetFaceA() { return m_faceA; } + + // FUNCTION: BETA10 0x10184190 + LegoWEEdge* GetFaceB() { return m_faceB; } + // FUNCTION: BETA10 0x1001cb80 Vector3* GetPointA() { return m_pointA; } diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.h b/LEGO1/lego/sources/geom/legounkown100db7f4.h index ef525932..1c9c266d 100644 --- a/LEGO1/lego/sources/geom/legounkown100db7f4.h +++ b/LEGO1/lego/sources/geom/legounkown100db7f4.h @@ -93,6 +93,9 @@ public: // FUNCTION: BETA10 0x1001cc60 LegoU32 GetMask0x03() { return m_flags & (c_bit1 | c_bit2); } + // FUNCTION: BETA10 0x101841b0 + void SetFlags(LegoU16 p_flags) { m_flags = p_flags; } + inline LegoU32 FUN_10048c40(const Vector3& p_position); // SYNTHETIC: LEGO1 0x1009a6c0 diff --git a/LEGO1/lego/sources/geom/legoweedge.cpp b/LEGO1/lego/sources/geom/legoweedge.cpp index a87072e9..862b247d 100644 --- a/LEGO1/lego/sources/geom/legoweedge.cpp +++ b/LEGO1/lego/sources/geom/legoweedge.cpp @@ -20,7 +20,7 @@ LegoWEEdge::~LegoWEEdge() } // FUNCTION: LEGO1 0x1009a5b0 -LegoResult LegoWEEdge::VTable0x04() +LegoS32 LegoWEEdge::VTable0x04() { for (LegoS32 i = 0; i < m_numEdges; i++) { LegoUnknown100db7f4* e1 = m_edges[i]; @@ -52,5 +52,5 @@ LegoResult LegoWEEdge::VTable0x04() } } - return SUCCESS; + return 0; } diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index bc0f6c3c..c2df2758 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -14,7 +14,7 @@ public: LegoWEEdge(); virtual ~LegoWEEdge(); // vtable+0x00 - virtual LegoResult VTable0x04(); // vtable+0x04 + virtual LegoS32 VTable0x04(); // vtable+0x04 // FUNCTION: BETA10 0x1001c980 LegoU8 GetNumEdges() { return m_numEdges; } diff --git a/LEGO1/lego/sources/geom/legowegedge.cpp b/LEGO1/lego/sources/geom/legowegedge.cpp index afbe9ddb..6de4fd17 100644 --- a/LEGO1/lego/sources/geom/legowegedge.cpp +++ b/LEGO1/lego/sources/geom/legowegedge.cpp @@ -1,9 +1,14 @@ #include "legowegedge.h" +#include "legounkown100db7f4.h" + +#include <assert.h> + DECOMP_SIZE_ASSERT(LegoWEGEdge, 0x54) DECOMP_SIZE_ASSERT(LegoWEGEdge::PathWithTrigger, 0x0c) // FUNCTION: LEGO1 0x1009a730 +// FUNCTION: BETA10 0x101830ec LegoWEGEdge::LegoWEGEdge() { m_unk0x0d = 0; @@ -11,7 +16,7 @@ LegoWEGEdge::LegoWEGEdge() m_unk0x14.Clear(); m_edgeNormals = NULL; m_flags = 0; - m_unk0x48 = 0; + m_numTriggers = 0; m_pathTrigger = NULL; m_unk0x50 = NULL; } @@ -37,9 +42,241 @@ LegoWEGEdge::~LegoWEGEdge() } } -// STUB: LEGO1 0x1009a8c0 -LegoResult LegoWEGEdge::VTable0x04() +// FUNCTION: LEGO1 0x1009a8c0 +// FUNCTION: BETA10 0x101832f7 +LegoS32 LegoWEGEdge::VTable0x04() { - // TODO - return SUCCESS; + LegoS32 result = 0; + m_unk0x30.Clear(); + LegoWEEdge::VTable0x04(); + + assert(m_numEdges > 1); + + Vector3* local20; + if (IsEqual(m_edges[0]->m_faceA)) { + local20 = m_edges[0]->m_pointB; + } + else { + assert(IsEqual(m_edges[0]->m_faceB)); + local20 = m_edges[0]->m_pointA; + } + + Vector3 *local1c, *local14; + if (IsEqual(m_edges[1]->m_faceA)) { + local1c = m_edges[1]->m_pointB; + local14 = m_edges[1]->m_pointA; + } + else { + assert(IsEqual(m_edges[1]->m_faceB)); + local1c = m_edges[1]->m_pointA; + local14 = m_edges[1]->m_pointB; + } + + result = FUN_1009aea0(); + if (result != 0) { + result = -2; + } + + assert(m_edgeNormals == NULL); + m_edgeNormals = new Mx4DPointFloat[m_numEdges]; + assert(m_edgeNormals); + + LegoUnknown100db7f4* edge; + LegoS32 i; + + for (i = 0; i < m_numEdges; i++) { + edge = m_edges[i]; + m_unk0x30 += *edge->m_pointA; + m_unk0x30 += *edge->m_pointB; + } + + m_unk0x30 /= m_numEdges * 2; + m_unk0x44 = 0.0f; + + for (i = 0; i < m_numEdges; i++) { + Mx3DPointFloat local44; + edge = m_edges[i]; + + local44 = *edge->m_pointA; + local44 -= m_unk0x30; + float length = local44.LenSquared(); + + if (m_unk0x44 < length) { + m_unk0x44 = length; + } + + local44 = *edge->m_pointB; + local44 -= m_unk0x30; + length = local44.LenSquared(); + + if (m_unk0x44 < length) { + m_unk0x44 = length; + } + } + + m_unk0x44 = sqrt((double) m_unk0x44); + + for (i = 0; i < m_numEdges; i++) { + edge = m_edges[i]; + Vector3& local5c = edge->m_unk0x28; + + if (edge->m_unk0x3c == 0) { + local5c = *m_edges[i]->m_pointB; + local5c -= *m_edges[i]->m_pointA; + edge->m_unk0x3c = local5c.LenSquared(); + + if (edge->m_unk0x3c <= 0.0f) { + assert(0); + if (result == 0) { + result = -1; + } + } + + edge->m_unk0x3c = sqrt((double) edge->m_unk0x3c); + local5c /= edge->m_unk0x3c; + } + + Mx3DPointFloat local58; + Vector3 local64(&m_edgeNormals[i][0]); + edge->FUN_1002ddc0(*this, local58); + local64.EqualsCross(&local58, &m_unk0x14); + + m_edgeNormals[i][3] = -local64.Dot(m_edges[i]->m_pointA, &local64); + if (m_edgeNormals[i][3] + m_unk0x30.Dot(&m_unk0x30, &local64) < 0.0f) { + m_edgeNormals[i] *= -1.0f; + } + + if (edge->GetFaceA() != NULL && edge->GetFaceB() != NULL) { + edge->SetFlags(LegoUnknown100db7f4::c_bit1 | LegoUnknown100db7f4::c_bit2); + } + } + + if (m_numTriggers > 0) { + Vector3* vTrig1 = m_edges[0]->CCWVertex(*this); + Vector3* vTrig2 = m_edges[1]->CCWVertex(*this); + assert(vTrig1 && vTrig2); + + m_unk0x50 = new Mx3DPointFloat(); + *m_unk0x50 = *vTrig2; + *m_unk0x50 -= *vTrig1; + + if (m_unk0x50->Unitize() < 0) { + assert(0); + delete m_unk0x50; + m_unk0x50 = NULL; + } + + if (GetNumEdges() == 4) { + float local98 = 0.0f; + Mx3DPointFloat localb8(*m_edges[0]->CWVertex(*this)); + Mx3DPointFloat local80(*m_edges[2]->CCWVertex(*this)); + Mx3DPointFloat local94(*vTrig2); + + local94 -= *vTrig1; + float local9c = sqrt(local94.LenSquared()); + + localb8 -= *vTrig1; + local80 -= *vTrig1; + + float locala4 = localb8.Dot(m_unk0x50, &localb8); + if (local98 < locala4) { + local98 = locala4; + } + + locala4 = local80.Dot(m_unk0x50, &local80); + if (locala4 < local9c) { + local9c = locala4; + } + + if (local9c < local98) { + result = -3; + } + if (local9c - local98 < 0.0025) { + result = -4; + } + + local98 += 0.001; + local9c -= 0.001; + + for (LegoS32 j = 0; j < m_numTriggers; j++) { + if (m_pathTrigger[j].m_unk0x08 < local98) { + m_pathTrigger[j].m_unk0x08 = local98; + } + + if (m_pathTrigger[j].m_unk0x08 > local9c) { + m_pathTrigger[j].m_unk0x08 = local9c; + } + } + } + else { + result = -5; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1009aea0 +// FUNCTION: BETA10 0x10183e2a +LegoS32 LegoWEGEdge::FUN_1009aea0() +{ + LegoU32 localc = FALSE; + Mx3DPointFloat local24; + + if (m_numEdges < 3) { + return -1; + } + + Vector3** local8 = new Vector3*[m_numEdges]; + LegoS32 i; + + for (i = 0; i < m_numEdges; i++) { + local8[i] = m_edges[i]->CWVertex(*this); + } + + for (i = 2; i < m_numEdges; i++) { + Mx3DPointFloat local3c; + Mx3DPointFloat local50; + float local28 = 0.0f; + + local3c = *local8[i]; + local3c -= *local8[i - 1]; + local50 = *local8[i - 2]; + local50 -= *local8[i - 1]; + + local24.EqualsCross(&local50, &local3c); + local28 = local24.LenSquared(); + + if (local28 < 0.00001f) { + continue; + } + + float local58 = sqrt((double) local28); + local24 /= local58; + + if (localc) { + float local54 = local24.Dot(&m_unk0x14, &local24); + if (local54 < 0.98) { + delete[] local8; + return -2; + } + } + else { + m_unk0x14[0] = local24[0]; + m_unk0x14[1] = local24[1]; + m_unk0x14[2] = local24[2]; + m_unk0x14[3] = -local8[i]->Dot(local8[i], &local24); + localc = TRUE; + } + } + + if (local8 != NULL) { + delete[] local8; + } + + if (!localc) { + return -1; + } + + return 0; } diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index ef29db9b..77567bfe 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -38,7 +38,7 @@ public: LegoWEGEdge(); ~LegoWEGEdge() override; - LegoResult VTable0x04() override; // vtable+0x04 + LegoS32 VTable0x04() override; // vtable+0x04 // FUNCTION: BETA10 0x100270c0 LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } @@ -72,6 +72,8 @@ public: friend class LegoPathController; protected: + LegoS32 FUN_1009aea0(); + LegoU8 m_flags; // 0x0c LegoU8 m_unk0x0d; // 0x0d LegoChar* m_name; // 0x10 @@ -79,7 +81,7 @@ protected: Mx4DPointFloat* m_edgeNormals; // 0x2c Mx3DPointFloat m_unk0x30; // 0x30 float m_unk0x44; // 0x44 - LegoU8 m_unk0x48; // 0x48 + LegoU8 m_numTriggers; // 0x48 PathWithTrigger* m_pathTrigger; // 0x4c Mx3DPointFloat* m_unk0x50; // 0x50 };