From 259d95e47ce5282a61b64a668d64b77d88d6094b Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 17 Jun 2022 01:53:08 -0600 Subject: [PATCH] testqbsp: add a first portal test --- include/common/polylib.hh | 51 +++++++++++++++++++++++++++++++++++++++ include/common/prtfile.hh | 4 ++- qbsp/test_qbsp.cc | 15 ++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/include/common/polylib.hh b/include/common/polylib.hh index a8c03873..fe43c13d 100644 --- a/include/common/polylib.hh +++ b/include/common/polylib.hh @@ -231,6 +231,9 @@ public: } } + // initializer list constructor + inline winding_base_t(std::initializer_list l) : winding_base_t(l.begin(), l.end()) {} + // copy constructor inline winding_base_t(const winding_base_t ©) : winding_base_t(copy.size()) { @@ -789,6 +792,54 @@ public: return result; } + + winding_base_t translate(const qvec3d& offset) const + { + winding_base_t result(*this); + + for (qvec3d& p : result) { + p += offset; + } + + return result; + } + + bool directional_equal(const winding_base_t& w, const vec_t &equal_epsilon = POINT_EQUAL_EPSILON) const + { + if (this->size() != w.size()) { + return false; + } + + const auto this_size = size(); + + // try different start offsets in `this` + for (int i = 0; i < this_size; ++i) { + bool all_equal = true; + + // index in `w` to compare + for (int j = 0; j < this_size; ++j) { + const qvec3d &our_point = (*this)[(i + j) % this_size]; + const qvec3d &their_point = w[j]; + + if (!qv::epsilonEqual(our_point, their_point, equal_epsilon)) { + all_equal = false; + break; + } + } + + if (all_equal) { + return true; + } + } + + return false; + } + + bool undirectional_equal(const winding_base_t& w, const vec_t &equal_epsilon = POINT_EQUAL_EPSILON) const + { + return directional_equal(w, equal_epsilon) + || directional_equal(w.flip(), equal_epsilon); + } }; // the default amount of points to keep on stack diff --git a/include/common/prtfile.hh b/include/common/prtfile.hh index 9c9eee48..16aaf11d 100644 --- a/include/common/prtfile.hh +++ b/include/common/prtfile.hh @@ -26,8 +26,10 @@ constexpr size_t PRT_MAX_WINDING_FIXED = 24; +using prtfile_winding_t = polylib::winding_base_t; + struct prtfile_portal_t { - polylib::winding_base_t winding; + prtfile_winding_t winding; int leafnums[2]; }; diff --git a/qbsp/test_qbsp.cc b/qbsp/test_qbsp.cc index a2363048..f142ddb3 100644 --- a/qbsp/test_qbsp.cc +++ b/qbsp/test_qbsp.cc @@ -892,6 +892,11 @@ TEST_CASE("features", "[testmaps_q1]") REQUIRE(prt.has_value()); } +bool PortalMatcher(const prtfile_winding_t& a, const prtfile_winding_t &b) +{ + return a.undirectional_equal(b); +} + TEST_CASE("qbsp_func_detail various types", "[testmaps_q1]") { const auto [bsp, bspx, prt] = LoadTestmapQ1("qbsp_func_detail.map"); @@ -923,6 +928,16 @@ TEST_CASE("qbsp_func_detail various types", "[testmaps_q1]") { CHECK(CONTENTS_SOLID == detail_wall_leaf->contents); CHECK(CONTENTS_EMPTY == detail_illusionary_leaf->contents); CHECK(CONTENTS_EMPTY == detail_illusionary_mirrorinside_leaf->contents); + + // portals + + REQUIRE(2 == prt->portals.size()); + + const auto p0 = prtfile_winding_t{{-160, -8, 352}, {56, -8, 352}, {56, -8, 96}, {-160, -8, 96}}; + const auto p1 = p0.translate({232, 0, 0}); + + CHECK(((PortalMatcher(prt->portals[0].winding, p0) && PortalMatcher(prt->portals[1].winding, p1)) + || (PortalMatcher(prt->portals[0].winding, p1) && PortalMatcher(prt->portals[1].winding, p0)))); } TEST_CASE("qbsp_angled_brush", "[testmaps_q1]") {