From 8f1a9a5f0f36ade0df3b6c923ec297faa8091a9a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 18 Mar 2024 00:22:12 +0000 Subject: Switch to using planes instead of triangles for deformaton cut Removes the hacky need for going a bit too far to account for rounding errors... which didn't really work anyway. --- game/geoData.cpp | 71 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 26 deletions(-) (limited to 'game') diff --git a/game/geoData.cpp b/game/geoData.cpp index 293cd2b..bf3192e 100644 --- a/game/geoData.cpp +++ b/game/geoData.cpp @@ -1,5 +1,6 @@ #include "geoData.h" #include "collections.h" +#include "geometricPlane.h" #include #include #include @@ -429,7 +430,7 @@ GeoData::setHeights(const std::span triangleStrip) const auto e1 = glm::normalize(vectorNormal(RelativePosition2D(p2 - p1))); const auto doExtrusion = [this](VertexHandle & extrusionVertex, Direction2D direction, - GlobalPosition3D boundaryVertex, RelativeDistance vert, GlobalDistance limit) { + GlobalPosition3D boundaryVertex, RelativeDistance vert) { const auto extrusionDir = glm::normalize(direction || vert); if (!extrusionVertex.is_valid()) { @@ -449,8 +450,7 @@ GeoData::setHeights(const std::span triangleStrip) } } - const auto extrusion - = extrusionDir * std::max(0.F, RelativeDistance(limit - boundaryVertex.z) / extrusionDir.z); + const auto extrusion = extrusionDir * 1000.F * MAX_SLOPE; return boundaryVertex + extrusion; }; // Previous half edge end to current half end start arc tangents @@ -461,16 +461,15 @@ GeoData::setHeights(const std::span triangleStrip) const auto direction = sincosf(arc.first + (step * inc)); VertexHandle extrusionVertex; extrusionExtents.emplace_back(boundaryVertex, extrusionVertex, - doExtrusion(extrusionVertex, direction, p1, -MAX_SLOPE, lowerExtent.z - 10), - doExtrusion(extrusionVertex, direction, p1, MAX_SLOPE, upperExtent.z + 10)); + doExtrusion(extrusionVertex, direction, p1, -MAX_SLOPE), + doExtrusion(extrusionVertex, direction, p1, MAX_SLOPE)); assert(extrusionVertex.is_valid()); } // Half edge start/end tangents for (const auto p : {boundaryVertex, nextBoundaryVertex}) { VertexHandle extrusionVertex; - extrusionExtents.emplace_back(p, extrusionVertex, - doExtrusion(extrusionVertex, e1, point(p), -MAX_SLOPE, lowerExtent.z - 10), - doExtrusion(extrusionVertex, e1, point(p), MAX_SLOPE, upperExtent.z + 10)); + extrusionExtents.emplace_back(p, extrusionVertex, doExtrusion(extrusionVertex, e1, point(p), -MAX_SLOPE), + doExtrusion(extrusionVertex, e1, point(p), MAX_SLOPE)); assert(extrusionVertex.is_valid()); } }); @@ -481,13 +480,26 @@ GeoData::setHeights(const std::span triangleStrip) std::adjacent_find(extrusionExtents.begin(), extrusionExtents.end(), [this, &boundaryFaces](const auto & first, const auto & second) { const auto p0 = point(first.boundaryVertex); - std::vector> triangles { - {p0, first.lowerLimit, second.lowerLimit}, {p0, first.upperLimit, second.upperLimit}}; const auto p1 = point(second.boundaryVertex); - if (first.boundaryVertex != second.boundaryVertex) { - triangles.emplace_back(p0, p1, second.lowerLimit); - triangles.emplace_back(p0, p1, second.upperLimit); - } + const auto make_normal = [](auto x, auto y, auto z) { + const auto cp = crossProduct(z - x, y - x); + const auto rcp = RelativePosition3D(cp); + const auto nrcp = glm::normalize(rcp); + return nrcp; + }; + const auto normals = ((first.boundaryVertex == second.boundaryVertex) + ? std::array {make_normal(p0, first.lowerLimit, second.lowerLimit), + make_normal(p0, first.upperLimit, second.upperLimit), + } + : std::array { + make_normal(p0, second.lowerLimit, p1), + make_normal(p0, second.upperLimit, p1), + }); + assert(normals.front().z > 0.F); + assert(normals.back().z > 0.F); + const auto planes = normals * [p0](const auto & normal) { + return GeometricPlaneT {p0, normal}; + }; auto & out = boundaryFaces.emplace_back(); out.emplace_back(first.boundaryVertex); @@ -500,28 +512,35 @@ GeoData::setHeights(const std::span triangleStrip) const auto nextVertex = to_vertex_handle(next); const auto startVertex = from_vertex_handle(next); if (nextVertex == *++out.rbegin()) { - // This half edge goes back to the previous vertex + // This half edge goes back to the previous vertex return false; } const auto edge = edge_handle(next); const auto ep0 = point(startVertex); const auto ep1 = point(nextVertex); + if (planes.front().getRelation(ep1) == GeometricPlane::PlaneRelation::Below + || planes.back().getRelation(ep1) == GeometricPlane::PlaneRelation::Above) { + return false; + } const auto diff = RelativePosition3D(ep1 - ep0); const auto length = glm::length(diff); const auto dir = diff / length; - const Ray r {ep0, dir}; - return std::any_of(triangles.begin(), triangles.end(), [&](const auto & triangle) { - BaryPosition bary; + const Ray r {ep1, -dir}; + const auto dists = planes * [r](const auto & plane) { RelativeDistance dist {}; - - if (r.intersectTriangle(triangle.x, triangle.y, triangle.z, bary, dist) - && dist <= length - 1 && dist >= 1) { - const auto splitPos = triangle * bary; - currentVertex = out.emplace_back(split(edge, splitPos)); - return true; + if (r.intersectPlane(plane.origin, plane.normal, dist)) { + return dist; } - return false; - }); + return INFINITY; + }; + const auto dist = *std::min_element(dists.begin(), dists.end()); + const auto splitPos = ep1 - (dir * dist); + if (dist <= length) { + currentVertex = split(edge, splitPos); + out.emplace_back(currentVertex); + return true; + } + return false; }); assert(n); } -- cgit v1.2.3