From 92833b185adb4c2e87f6d66d27a11403c8c6d8c4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 31 Mar 2020 06:16:04 -0400 Subject: [PATCH] CMapWorld: Move internally linked entities into an anonymous namespace Same behavior, but prevents any potential ODR violations from occurring. --- Runtime/AutoMapper/CMapWorld.cpp | 490 ++++++++++++++++--------------- 1 file changed, 248 insertions(+), 242 deletions(-) diff --git a/Runtime/AutoMapper/CMapWorld.cpp b/Runtime/AutoMapper/CMapWorld.cpp index 481474da1..7d3f389c4 100644 --- a/Runtime/AutoMapper/CMapWorld.cpp +++ b/Runtime/AutoMapper/CMapWorld.cpp @@ -9,6 +9,254 @@ #include "Runtime/World/CWorld.hpp" namespace urde { +namespace { +struct Support { + int x0_; + int x4_[3]; +}; + +struct Circle2 { + zeus::CVector2f x0_point; + float x8_radiusSq; +}; + +struct Circle { + zeus::CVector2f x0_point; + float x8_radius; + Circle(const Circle2& circ2) : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {} +}; + +Circle2 ExactCircle1(const zeus::CVector2f* a) { return {*a, 0.f}; } + +Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) { + Circle2 ret = {}; + ret.x0_point = 0.5f * (*a + *b); + ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f; + return ret; +} + +Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) { + Circle2 ret = {}; + zeus::CVector2f d1 = *b - *a; + zeus::CVector2f d2 = *c - *a; + float cross = d1.cross(d2); + zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f); + if (std::fabs(cross) > 0.01f) { + zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross, + (d1.x() * magVec.y() - d2.x() * magVec.x()) / cross); + ret.x0_point = *a + tmp; + ret.x8_radiusSq = tmp.magSquared(); + } else { + ret.x8_radiusSq = FLT_MAX; + } + return ret; +} + +bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) { + intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq; + return intersect <= 0.f; +} + +Circle2 UpdateSupport1(int idx, const zeus::CVector2f** list, Support& support) { + Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]); + support.x0_ = 2; + support.x4_[1] = idx; + return ret; +} + +Circle2 UpdateSupport2(int idx, const zeus::CVector2f** list, Support& support) { + Circle2 circs[3] = {}; + float intersect; + int circIdx = -1; + float minRad = FLT_MAX; + + circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); + if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { + minRad = circs[0].x8_radiusSq; + circIdx = 0; + } + + circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); + if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { + circIdx = 1; + } + + Circle2 ret; + if (circIdx != -1) { + ret = circs[circIdx]; + support.x4_[1 - circIdx] = idx; + } else { + ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); + support.x0_ = 3; + support.x4_[2] = idx; + } + return ret; +} + +Circle2 UpdateSupport3(int idx, const zeus::CVector2f** list, Support& support) { + Circle2 circs[6] = {}; + float intersect; + int circIdxA = -1; + int circIdxB = -1; + float minRadA = FLT_MAX; + float minRadB = FLT_MAX; + + circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); + if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { + if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) { + minRadA = circs[0].x8_radiusSq; + circIdxA = 0; + } else { + minRadB = intersect; + circIdxB = 0; + } + } else { + minRadB = intersect; + circIdxB = 0; + } + + circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); + if (circs[1].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { + if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) { + minRadA = circs[1].x8_radiusSq; + circIdxA = 1; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 1; + } + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 1; + } + } + + circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]); + if (circs[2].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) { + if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) { + minRadA = circs[2].x8_radiusSq; + circIdxA = 2; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 2; + } + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 2; + } + } + + circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); + if (circs[3].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) { + minRadA = circs[3].x8_radiusSq; + circIdxA = 3; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 3; + } + } + + circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]); + if (circs[4].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) { + minRadA = circs[4].x8_radiusSq; + circIdxA = 4; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 4; + } + } + + circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]); + if (circs[5].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) { + circIdxA = 5; + } else if (intersect < minRadB) { + circIdxB = 5; + } + } + + if (circIdxA == -1) + circIdxA = circIdxB; + + switch (circIdxA) { + case 0: + support.x0_ = 2; + support.x4_[1] = idx; + break; + case 1: + support.x0_ = 2; + support.x4_[0] = idx; + break; + case 2: + support.x0_ = 2; + support.x4_[0] = support.x4_[2]; + support.x4_[1] = idx; + break; + case 3: + support.x4_[2] = idx; + break; + case 4: + support.x4_[1] = idx; + break; + case 5: + support.x4_[0] = idx; + break; + default: + break; + } + + return circs[circIdxA]; +} + +using FSupport = Circle2 (*)(int idx, const zeus::CVector2f** list, Support& support); +constexpr FSupport SupportFuncs[] = { + nullptr, + UpdateSupport1, + UpdateSupport2, + UpdateSupport3, +}; + +Circle MinCircle(const std::vector& coords) { + Circle2 ret = {}; + if (coords.size() >= 1) { + std::unique_ptr randArr(new const zeus::CVector2f*[coords.size()]); + for (size_t i = 0; i < coords.size(); ++i) + randArr[i] = &coords[i]; + for (int i = coords.size() - 1; i >= 0; --i) { + int shuf = rand() % (i + 1); + if (shuf != i) + std::swap(randArr[i], randArr[shuf]); + } + ret = ExactCircle1(randArr[0]); + + Support support = {}; + support.x0_ = 1; + for (size_t i = 1; i < coords.size();) { + bool broke = false; + for (int j = 0; j < support.x0_; ++j) { + if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f) { + broke = true; + break; + } + } + float intersect; + if (!broke && !PointInsideCircle(*randArr[i], ret, intersect)) { + Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support); + if (circ.x8_radiusSq > ret.x8_radiusSq) { + i = 0; + ret = circ; + continue; + } + } + ++i; + } + } + return ret; +} +} // Anonymous namespace CMapWorld::CMapAreaData::CMapAreaData(CAssetId areaRes, EMapAreaList list, CMapAreaData* next) : x0_area(g_SimplePool->GetObj(SObjectTag{FOURCC('MAPA'), areaRes})), x10_list(list), x14_next(next) {} @@ -378,248 +626,6 @@ void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selAre } } -struct Support { - int x0_; - int x4_[3]; -}; - -struct Circle2 { - zeus::CVector2f x0_point; - float x8_radiusSq; -}; - -struct Circle { - zeus::CVector2f x0_point; - float x8_radius; - Circle(const Circle2& circ2) : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {} -}; - -static Circle2 ExactCircle1(const zeus::CVector2f* a) { return {*a, 0.f}; } - -static Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) { - Circle2 ret = {}; - ret.x0_point = 0.5f * (*a + *b); - ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f; - return ret; -} - -static Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) { - Circle2 ret = {}; - zeus::CVector2f d1 = *b - *a; - zeus::CVector2f d2 = *c - *a; - float cross = d1.cross(d2); - zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f); - if (std::fabs(cross) > 0.01f) { - zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross, - (d1.x() * magVec.y() - d2.x() * magVec.x()) / cross); - ret.x0_point = *a + tmp; - ret.x8_radiusSq = tmp.magSquared(); - } else { - ret.x8_radiusSq = FLT_MAX; - } - return ret; -} - -static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) { - intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq; - return intersect <= 0.f; -} - -static Circle2 UpdateSupport1(int idx, const zeus::CVector2f** list, Support& support) { - Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]); - support.x0_ = 2; - support.x4_[1] = idx; - return ret; -} - -static Circle2 UpdateSupport2(int idx, const zeus::CVector2f** list, Support& support) { - Circle2 circs[3] = {}; - float intersect; - int circIdx = -1; - float minRad = FLT_MAX; - - circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); - if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { - minRad = circs[0].x8_radiusSq; - circIdx = 0; - } - - circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); - if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { - circIdx = 1; - } - - Circle2 ret; - if (circIdx != -1) { - ret = circs[circIdx]; - support.x4_[1 - circIdx] = idx; - } else { - ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); - support.x0_ = 3; - support.x4_[2] = idx; - } - return ret; -} - -static Circle2 UpdateSupport3(int idx, const zeus::CVector2f** list, Support& support) { - Circle2 circs[6] = {}; - float intersect; - int circIdxA = -1; - int circIdxB = -1; - float minRadA = FLT_MAX; - float minRadB = FLT_MAX; - - circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); - if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { - if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) { - minRadA = circs[0].x8_radiusSq; - circIdxA = 0; - } else { - minRadB = intersect; - circIdxB = 0; - } - } else { - minRadB = intersect; - circIdxB = 0; - } - - circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); - if (circs[1].x8_radiusSq < minRadA) { - if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { - if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) { - minRadA = circs[1].x8_radiusSq; - circIdxA = 1; - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 1; - } - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 1; - } - } - - circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]); - if (circs[2].x8_radiusSq < minRadA) { - if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) { - if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) { - minRadA = circs[2].x8_radiusSq; - circIdxA = 2; - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 2; - } - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 2; - } - } - - circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); - if (circs[3].x8_radiusSq < minRadA) { - if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) { - minRadA = circs[3].x8_radiusSq; - circIdxA = 3; - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 3; - } - } - - circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]); - if (circs[4].x8_radiusSq < minRadA) { - if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) { - minRadA = circs[4].x8_radiusSq; - circIdxA = 4; - } else if (intersect < minRadB) { - minRadB = intersect; - circIdxB = 4; - } - } - - circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]); - if (circs[5].x8_radiusSq < minRadA) { - if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) { - circIdxA = 5; - } else if (intersect < minRadB) { - circIdxB = 5; - } - } - - if (circIdxA == -1) - circIdxA = circIdxB; - - switch (circIdxA) { - case 0: - support.x0_ = 2; - support.x4_[1] = idx; - break; - case 1: - support.x0_ = 2; - support.x4_[0] = idx; - break; - case 2: - support.x0_ = 2; - support.x4_[0] = support.x4_[2]; - support.x4_[1] = idx; - break; - case 3: - support.x4_[2] = idx; - break; - case 4: - support.x4_[1] = idx; - break; - case 5: - support.x4_[0] = idx; - break; - default: - break; - } - - return circs[circIdxA]; -} - -typedef Circle2 (*FSupport)(int idx, const zeus::CVector2f** list, Support& support); -static const FSupport SupportFuncs[] = {nullptr, UpdateSupport1, UpdateSupport2, UpdateSupport3}; - -static Circle MinCircle(const std::vector& coords) { - Circle2 ret = {}; - if (coords.size() >= 1) { - std::unique_ptr randArr(new const zeus::CVector2f*[coords.size()]); - for (size_t i = 0; i < coords.size(); ++i) - randArr[i] = &coords[i]; - for (int i = coords.size() - 1; i >= 0; --i) { - int shuf = rand() % (i + 1); - if (shuf != i) - std::swap(randArr[i], randArr[shuf]); - } - ret = ExactCircle1(randArr[0]); - - Support support = {}; - support.x0_ = 1; - for (size_t i = 1; i < coords.size();) { - bool broke = false; - for (int j = 0; j < support.x0_; ++j) { - if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f) { - broke = true; - break; - } - } - float intersect; - if (!broke && !PointInsideCircle(*randArr[i], ret, intersect)) { - Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support); - if (circ.x8_radiusSq > ret.x8_radiusSq) { - i = 0; - ret = circ; - continue; - } - } - ++i; - } - } - return ret; -} - void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) { std::vector coords; coords.reserve(x0_areas.size() * 8);