From 25e1e2e5f7f097a81810154a337d1672d561118a Mon Sep 17 00:00:00 2001 From: Robin Kisman <99972691+KcRobin9@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:55:39 +0100 Subject: [PATCH 1/3] Implement Multiple Polygon Functions The aim is to understand how the collision table is generated, such that this knowledge can be applied when creating the `_HITID.BND` from scratch. --- code/midtown/mmdyna/bndtmpl.h | 2 +- code/midtown/mmdyna/poly.cpp | 190 ++++++++++++++++++++++++++++++++++ code/midtown/mmdyna/poly.h | 14 +-- 3 files changed, 198 insertions(+), 8 deletions(-) diff --git a/code/midtown/mmdyna/bndtmpl.h b/code/midtown/mmdyna/bndtmpl.h index 4317b209..d48f202e 100644 --- a/code/midtown/mmdyna/bndtmpl.h +++ b/code/midtown/mmdyna/bndtmpl.h @@ -248,7 +248,7 @@ class mmBoundTemplate // ?WinID@mmBoundTemplate@@2HA | mmdyna:bndtmpl2 ARTS_IMPORT static i32 WinID; -private: +public: // ?DoMakeTable@mmBoundTemplate@@AAEXHHH@Z | mmdyna:bndtmpl2 ARTS_IMPORT void DoMakeTable(i32 arg1, i32 arg2, i32 arg3); diff --git a/code/midtown/mmdyna/poly.cpp b/code/midtown/mmdyna/poly.cpp index 2cf1fcae..2418232e 100644 --- a/code/midtown/mmdyna/poly.cpp +++ b/code/midtown/mmdyna/poly.cpp @@ -19,3 +19,193 @@ define_dummy_symbol(mmdyna_poly); #include "poly.h" + +#include "mmdyna/bndtmpl.h" + +f32 mmPolygon::CheckCellXSide(f32 x_plane, f32 z_min, f32 z_max) +{ + f32 max_y = -999999.0f; + i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + + for (i32 i = 0; i < vert_count; ++i) + { + const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i % vert_count]]; + const Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; + + if ((cur_vert.x < x_plane && next_vert.x > x_plane) || (cur_vert.x > x_plane && next_vert.x < x_plane)) + { + f32 factor = (x_plane - cur_vert.x) / (next_vert.x - cur_vert.x); + f32 z_int = (next_vert.z - cur_vert.z) * factor + cur_vert.z; + + if (z_int >= z_min && z_int <= z_max) + { + f32 y_int = (next_vert.y - cur_vert.y) * factor + cur_vert.y; + + if (y_int > max_y) + { + max_y = y_int; + } + } + } + } + + return max_y; +} + +f32 mmPolygon::CheckCellZSide(f32 z_plane, f32 x_min, f32 x_max) +{ + f32 max_y = -999999.0f; + i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + + for (i32 i = 0; i < vert_count; ++i) + { + const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i % vert_count]]; + const Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; + + if ((cur_vert.z < z_plane && next_vert.z > z_plane) || (cur_vert.z > z_plane && next_vert.z < z_plane)) + { + f32 factor = (z_plane - cur_vert.z) / (next_vert.z - cur_vert.z); + f32 x_int = (next_vert.x - cur_vert.x) * factor + cur_vert.x; + + if (x_int >= x_min && x_int <= x_max) + { + f32 y_int = (next_vert.y - cur_vert.y) * factor + cur_vert.y; + + if (y_int > max_y) + { + max_y = y_int; + } + } + } + } + + return max_y; +} + +f32 mmPolygon::CheckCorner(f32 x, f32 z, f32* x_plane, f32* z_plane, f32* const_plane) +{ + if (PlaneN.y == 0.0f) + { + return -999999.0f; + } + + i32 vert_count = (Flags & 4) ? 4 : 3; + + for (i32 i = 0; i < vert_count; ++i) + { + if (x * x_plane[i] + z * z_plane[i] + const_plane[i] < 0.0f) + { + return -999999.0f; + } + } + + return -(PlaneN.x * x + PlaneD + PlaneN.z * z) / PlaneN.y; +} + +f32 mmPolygon::CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2) +{ + f32 max_y = -999999.0f; + i32 vert_count = (Flags & 4) ? 4 : 3; + f32 adjusted_sign = (PlaneN.y <= 0.0f) ? 1.0f : -1.0f; + f32 x_plane[4], z_plane[4], const_plane[4], length, inverse_length; + + for (i32 i = 0; i < vert_count; ++i) + { + Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i]]; + Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; + + x_plane[i] = -(next_vert.z - cur_vert.z) * adjusted_sign; + z_plane[i] = (next_vert.x - cur_vert.x) * adjusted_sign; + const_plane[i] = -(x_plane[i] * cur_vert.x + z_plane[i] * cur_vert.z); + + length = std::sqrt(x_plane[i] * x_plane[i] + z_plane[i] * z_plane[i]); + + if (length < 1e-9) + return -999999.0f; + + inverse_length = 1.0f / length; + x_plane[i] *= inverse_length; + z_plane[i] *= inverse_length; + const_plane[i] *= inverse_length; + } + + for (i32 i = 0; i < 4; ++i) + { + f32 corner_height; + + corner_height = CheckCorner(x1, z1, x_plane, z_plane, const_plane); + max_y = std::max(max_y, corner_height); + + corner_height = CheckCorner(x1, z2, x_plane, z_plane, const_plane); + max_y = std::max(max_y, corner_height); + + corner_height = CheckCorner(x2, z1, x_plane, z_plane, const_plane); + max_y = std::max(max_y, corner_height); + + corner_height = CheckCorner(x2, z2, x_plane, z_plane, const_plane); + max_y = std::max(max_y, corner_height); + } + + return max_y; +} + +f32 mmPolygon::MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max) +{ + f32 max_y = -999999.0f; + i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + + for (i32 i = 0; i < vert_count; ++i) + { + Vector3& vert = mmBoundTemplate::VertPtr[VertIndices[i]]; + + if (vert.x >= x_min && vert.x <= x_max && vert.z >= z_min && vert.z <= z_max) + { + max_y = std::max(max_y, vert.y); + } + } + + f32 corner_height = CornersHeight(x_min, z_min, x_max, z_max); + max_y = std::max(max_y, corner_height); + + f32 cell_x_side_min = CheckCellXSide(x_min, z_min, z_max); + max_y = std::max(max_y, cell_x_side_min); + + f32 cell_x_side_max = CheckCellXSide(x_max, z_min, z_max); + max_y = std::max(max_y, cell_x_side_max); + + f32 cell_z_side_min = CheckCellZSide(z_min, x_min, x_max); + max_y = std::max(max_y, cell_z_side_min); + + f32 cell_z_side_max = CheckCellZSide(z_max, x_min, x_max); + max_y = std::max(max_y, cell_z_side_max); + + return max_y; +} + +void mmPolygon::Plot(mmBoundTemplate* t, i32 poly_index) +{ + if (Flags & 4) + { + PlotTriangle(0, 1, 2, t, poly_index); + PlotTriangle(0, 2, 3, t, poly_index); + } + else + { + PlotTriangle(0, 1, 2, t, poly_index); + } +} + +void mmPolygon::PlotScan(i32 x1, i32 x2, i32 z, mmBoundTemplate* t, i32 poly_index) +{ + if (!t) + return; + + z = std::clamp(z, 0, t->ZDim - 1); + x1 = std::clamp(x1, 0, t->XDim - 1); + x2 = std::clamp(x2, 0, t->XDim - 1); + + for (i32 x = x1; x <= x2; ++x) + { + t->AddIndex(x, z, poly_index); + } +} \ No newline at end of file diff --git a/code/midtown/mmdyna/poly.h b/code/midtown/mmdyna/poly.h index b9932346..a52b349f 100644 --- a/code/midtown/mmdyna/poly.h +++ b/code/midtown/mmdyna/poly.h @@ -54,16 +54,16 @@ class mmPolygon private: // ?CheckCellXSide@mmPolygon@@AAEMMMM@Z - ARTS_IMPORT f32 CheckCellXSide(f32 arg1, f32 arg2, f32 arg3); + ARTS_EXPORT f32 CheckCellXSide(f32 x_plane, f32 z_min, f32 z_max); // ?CheckCellZSide@mmPolygon@@AAEMMMM@Z - ARTS_IMPORT f32 CheckCellZSide(f32 arg1, f32 arg2, f32 arg3); + ARTS_EXPORT f32 CheckCellZSide(f32 z_plane, f32 x_min, f32 x_max); // ?CheckCorner@mmPolygon@@AAEMMMPAM00@Z - ARTS_IMPORT f32 CheckCorner(f32 arg1, f32 arg2, f32* arg3, f32* arg4, f32* arg5); + ARTS_EXPORT f32 CheckCorner(f32 x, f32 z, f32* x_plane, f32* z_plane, f32* const_plane); // ?CornersHeight@mmPolygon@@AAEMMMMM@Z - ARTS_IMPORT f32 CornersHeight(f32 arg1, f32 arg2, f32 arg3, f32 arg4); + ARTS_EXPORT f32 CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2); #ifdef ARTS_DEV_BUILD // ?Draw@mmPolygon@@AAEXXZ @@ -90,13 +90,13 @@ class mmPolygon ARTS_IMPORT void Init(); // ?MaxY@mmPolygon@@AAEMMMMM@Z - ARTS_IMPORT f32 MaxY(f32 arg1, f32 arg2, f32 arg3, f32 arg4); + ARTS_EXPORT f32 MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max); // ?Plot@mmPolygon@@AAEXPAVmmBoundTemplate@@H@Z - ARTS_IMPORT void Plot(mmBoundTemplate* arg1, i32 arg2); + ARTS_EXPORT void Plot(mmBoundTemplate* t, i32 poly_index); // ?PlotScan@mmPolygon@@AAEXHHHPAVmmBoundTemplate@@H@Z - ARTS_IMPORT void PlotScan(i32 arg1, i32 arg2, i32 arg3, mmBoundTemplate* arg4, i32 arg5); + ARTS_EXPORT void PlotScan(i32 x1, i32 x2, i32 z, mmBoundTemplate* t, i32 poly_index); // ?PlotTriangle@mmPolygon@@AAEXHHHPAVmmBoundTemplate@@H@Z ARTS_IMPORT void PlotTriangle(i32 arg1, i32 arg2, i32 arg3, mmBoundTemplate* arg4, i32 arg5); From 408fc053235e406771948262cdf5eb1079ffa484 Mon Sep 17 00:00:00 2001 From: Robin Kisman <99972691+KcRobin9@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:02:15 +0100 Subject: [PATCH 2/3] Run format_full.py --- code/midtown/mmdyna/poly.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/midtown/mmdyna/poly.cpp b/code/midtown/mmdyna/poly.cpp index 2418232e..aefb3d34 100644 --- a/code/midtown/mmdyna/poly.cpp +++ b/code/midtown/mmdyna/poly.cpp @@ -151,8 +151,8 @@ f32 mmPolygon::CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2) f32 mmPolygon::MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max) { - f32 max_y = -999999.0f; - i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + f32 max_y = -999999.0f; + i32 vert_count = (Flags & 4) != 0 ? 4 : 3; for (i32 i = 0; i < vert_count; ++i) { @@ -160,7 +160,7 @@ f32 mmPolygon::MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max) if (vert.x >= x_min && vert.x <= x_max && vert.z >= z_min && vert.z <= z_max) { - max_y = std::max(max_y, vert.y); + max_y = std::max(max_y, vert.y); } } From 20e8bcd1bd0301ec881758de3026847e1bd1dc00 Mon Sep 17 00:00:00 2001 From: Robin Kisman <99972691+KcRobin9@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:54:54 +0100 Subject: [PATCH 3/3] Incorporated Review Changes Hopefully all points are addressed adequately --- code/midtown/mmdyna/poly.cpp | 95 +++++++++++++----------------------- code/midtown/mmdyna/poly.h | 16 ++++-- 2 files changed, 48 insertions(+), 63 deletions(-) diff --git a/code/midtown/mmdyna/poly.cpp b/code/midtown/mmdyna/poly.cpp index aefb3d34..fcd15222 100644 --- a/code/midtown/mmdyna/poly.cpp +++ b/code/midtown/mmdyna/poly.cpp @@ -22,29 +22,25 @@ define_dummy_symbol(mmdyna_poly); #include "mmdyna/bndtmpl.h" -f32 mmPolygon::CheckCellXSide(f32 x_plane, f32 z_min, f32 z_max) +f32 mmPolygon::CheckCellXSide(f32 plane_x, f32 z_min, f32 z_max) { f32 max_y = -999999.0f; - i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + i32 vert_count = GetNumVerts(); for (i32 i = 0; i < vert_count; ++i) { - const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i % vert_count]]; + const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i]]; const Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; - if ((cur_vert.x < x_plane && next_vert.x > x_plane) || (cur_vert.x > x_plane && next_vert.x < x_plane)) + if ((cur_vert.x < plane_x && next_vert.x > plane_x) || (cur_vert.x > plane_x && next_vert.x < plane_x)) { - f32 factor = (x_plane - cur_vert.x) / (next_vert.x - cur_vert.x); + f32 factor = (plane_x - cur_vert.x) / (next_vert.x - cur_vert.x); f32 z_int = (next_vert.z - cur_vert.z) * factor + cur_vert.z; if (z_int >= z_min && z_int <= z_max) { f32 y_int = (next_vert.y - cur_vert.y) * factor + cur_vert.y; - - if (y_int > max_y) - { - max_y = y_int; - } + max_y = std::max(max_y, y_int); } } } @@ -52,29 +48,25 @@ f32 mmPolygon::CheckCellXSide(f32 x_plane, f32 z_min, f32 z_max) return max_y; } -f32 mmPolygon::CheckCellZSide(f32 z_plane, f32 x_min, f32 x_max) +f32 mmPolygon::CheckCellZSide(f32 plane_z, f32 x_min, f32 x_max) { f32 max_y = -999999.0f; - i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + i32 vert_count = GetNumVerts(); for (i32 i = 0; i < vert_count; ++i) { - const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i % vert_count]]; + const Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i]]; const Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; - if ((cur_vert.z < z_plane && next_vert.z > z_plane) || (cur_vert.z > z_plane && next_vert.z < z_plane)) + if ((cur_vert.z < plane_z && next_vert.z > plane_z) || (cur_vert.z > plane_z && next_vert.z < plane_z)) { - f32 factor = (z_plane - cur_vert.z) / (next_vert.z - cur_vert.z); + f32 factor = (plane_z - cur_vert.z) / (next_vert.z - cur_vert.z); f32 x_int = (next_vert.x - cur_vert.x) * factor + cur_vert.x; if (x_int >= x_min && x_int <= x_max) { f32 y_int = (next_vert.y - cur_vert.y) * factor + cur_vert.y; - - if (y_int > max_y) - { - max_y = y_int; - } + max_y = std::max(max_y, y_int); } } } @@ -82,18 +74,18 @@ f32 mmPolygon::CheckCellZSide(f32 z_plane, f32 x_min, f32 x_max) return max_y; } -f32 mmPolygon::CheckCorner(f32 x, f32 z, f32* x_plane, f32* z_plane, f32* const_plane) +f32 mmPolygon::CheckCorner(f32 x, f32 z, f32* plane_x, f32* plane_z, f32* plane_d) { if (PlaneN.y == 0.0f) { return -999999.0f; } - i32 vert_count = (Flags & 4) ? 4 : 3; + i32 vert_count = GetNumVerts(); for (i32 i = 0; i < vert_count; ++i) { - if (x * x_plane[i] + z * z_plane[i] + const_plane[i] < 0.0f) + if (x * plane_x[i] + z * plane_z[i] + plane_d[i] < 0.0f) { return -999999.0f; } @@ -105,45 +97,35 @@ f32 mmPolygon::CheckCorner(f32 x, f32 z, f32* x_plane, f32* z_plane, f32* const_ f32 mmPolygon::CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2) { f32 max_y = -999999.0f; - i32 vert_count = (Flags & 4) ? 4 : 3; + i32 vert_count = GetNumVerts(); f32 adjusted_sign = (PlaneN.y <= 0.0f) ? 1.0f : -1.0f; - f32 x_plane[4], z_plane[4], const_plane[4], length, inverse_length; + f32 plane_x[4], plane_z[4], plane_d[4]; for (i32 i = 0; i < vert_count; ++i) { Vector3& cur_vert = mmBoundTemplate::VertPtr[VertIndices[i]]; Vector3& next_vert = mmBoundTemplate::VertPtr[VertIndices[(i + 1) % vert_count]]; - x_plane[i] = -(next_vert.z - cur_vert.z) * adjusted_sign; - z_plane[i] = (next_vert.x - cur_vert.x) * adjusted_sign; - const_plane[i] = -(x_plane[i] * cur_vert.x + z_plane[i] * cur_vert.z); + plane_x[i] = -(next_vert.z - cur_vert.z) * adjusted_sign; + plane_z[i] = (next_vert.x - cur_vert.x) * adjusted_sign; + plane_d[i] = -(plane_x[i] * cur_vert.x + plane_z[i] * cur_vert.z); - length = std::sqrt(x_plane[i] * x_plane[i] + z_plane[i] * z_plane[i]); + f32 length = std::sqrt(plane_x[i] * plane_x[i] + plane_z[i] * plane_z[i]); if (length < 1e-9) return -999999.0f; - inverse_length = 1.0f / length; - x_plane[i] *= inverse_length; - z_plane[i] *= inverse_length; - const_plane[i] *= inverse_length; + plane_x[i] *= 1.0f / length; + plane_z[i] *= 1.0f / length; + plane_d[i] *= 1.0f / length; } for (i32 i = 0; i < 4; ++i) { - f32 corner_height; - - corner_height = CheckCorner(x1, z1, x_plane, z_plane, const_plane); - max_y = std::max(max_y, corner_height); - - corner_height = CheckCorner(x1, z2, x_plane, z_plane, const_plane); - max_y = std::max(max_y, corner_height); - - corner_height = CheckCorner(x2, z1, x_plane, z_plane, const_plane); - max_y = std::max(max_y, corner_height); - - corner_height = CheckCorner(x2, z2, x_plane, z_plane, const_plane); - max_y = std::max(max_y, corner_height); + max_y = std::max(max_y, CheckCorner(x1, z1, plane_x, plane_z, plane_d)); + max_y = std::max(max_y, CheckCorner(x1, z2, plane_x, plane_z, plane_d)); + max_y = std::max(max_y, CheckCorner(x2, z1, plane_x, plane_z, plane_d)); + max_y = std::max(max_y, CheckCorner(x2, z2, plane_x, plane_z, plane_d)); } return max_y; @@ -152,7 +134,7 @@ f32 mmPolygon::CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2) f32 mmPolygon::MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max) { f32 max_y = -999999.0f; - i32 vert_count = (Flags & 4) != 0 ? 4 : 3; + i32 vert_count = GetNumVerts(); for (i32 i = 0; i < vert_count; ++i) { @@ -164,27 +146,20 @@ f32 mmPolygon::MaxY(f32 x_min, f32 z_min, f32 x_max, f32 z_max) } } - f32 corner_height = CornersHeight(x_min, z_min, x_max, z_max); - max_y = std::max(max_y, corner_height); - - f32 cell_x_side_min = CheckCellXSide(x_min, z_min, z_max); - max_y = std::max(max_y, cell_x_side_min); - - f32 cell_x_side_max = CheckCellXSide(x_max, z_min, z_max); - max_y = std::max(max_y, cell_x_side_max); + max_y = std::max(max_y, CornersHeight(x_min, z_min, x_max, z_max)); - f32 cell_z_side_min = CheckCellZSide(z_min, x_min, x_max); - max_y = std::max(max_y, cell_z_side_min); + max_y = std::max(max_y, CheckCellXSide(x_min, z_min, z_max)); + max_y = std::max(max_y, CheckCellXSide(x_max, z_min, z_max)); - f32 cell_z_side_max = CheckCellZSide(z_max, x_min, x_max); - max_y = std::max(max_y, cell_z_side_max); + max_y = std::max(max_y, CheckCellZSide(z_min, x_min, x_max)); + max_y = std::max(max_y, CheckCellZSide(z_max, x_min, x_max)); return max_y; } void mmPolygon::Plot(mmBoundTemplate* t, i32 poly_index) { - if (Flags & 4) + if (IsQuad()) { PlotTriangle(0, 1, 2, t, poly_index); PlotTriangle(0, 2, 3, t, poly_index); diff --git a/code/midtown/mmdyna/poly.h b/code/midtown/mmdyna/poly.h index a52b349f..5c1d5e4f 100644 --- a/code/midtown/mmdyna/poly.h +++ b/code/midtown/mmdyna/poly.h @@ -54,13 +54,13 @@ class mmPolygon private: // ?CheckCellXSide@mmPolygon@@AAEMMMM@Z - ARTS_EXPORT f32 CheckCellXSide(f32 x_plane, f32 z_min, f32 z_max); + ARTS_EXPORT f32 CheckCellXSide(f32 plane_x, f32 z_min, f32 z_max); // ?CheckCellZSide@mmPolygon@@AAEMMMM@Z - ARTS_EXPORT f32 CheckCellZSide(f32 z_plane, f32 x_min, f32 x_max); + ARTS_EXPORT f32 CheckCellZSide(f32 plane_z, f32 x_min, f32 x_max); // ?CheckCorner@mmPolygon@@AAEMMMPAM00@Z - ARTS_EXPORT f32 CheckCorner(f32 x, f32 z, f32* x_plane, f32* z_plane, f32* const_plane); + ARTS_EXPORT f32 CheckCorner(f32 x, f32 z, f32* plane_x, f32* plane_z, f32* plane_d); // ?CornersHeight@mmPolygon@@AAEMMMMM@Z ARTS_EXPORT f32 CornersHeight(f32 x1, f32 z1, f32 x2, f32 z2); @@ -101,6 +101,16 @@ class mmPolygon // ?PlotTriangle@mmPolygon@@AAEXHHHPAVmmBoundTemplate@@H@Z ARTS_IMPORT void PlotTriangle(i32 arg1, i32 arg2, i32 arg3, mmBoundTemplate* arg4, i32 arg5); + i32 GetNumVerts() const + { + return IsQuad() ? 4 : 3; + } + + b32 IsQuad() const + { + return (Flags & 4) != 0; + } + public: u16 RoomId; u8 MtlIndex;