From 1f42cf022014868369447af3a06b025c14a06507 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 24 Jun 2024 09:49:45 -0700 Subject: [PATCH] simplify: Make hasTriangleFlip predicate use an angle cutoff Instead of checking if the dot product is 0 or negative (90 degree limit on triangle rotations), use a cutoff of ~75 degrees. The motivation here is that meshes with complex curvature can end up flipping triangles through a series of collapses, and since we always evaluate flips compared to the current mesh we miss that. Technically this can happen even with a 75 degree limit, but in practice this solves cases of flips that have been reported before, and doesn't noticeably constrain simplification or slow it down. For numerical stability, we avoid dividing by the triangle areas (as they can be close to zero) and instead use the areas to compute a bound for dot product. Even if the area product underflows, we just get the same check that we used to have -- areas should be in [0..1] so there should be no risk of overflow. --- src/simplifier.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/simplifier.cpp b/src/simplifier.cpp index 84efaab6e..e59b4afcd 100644 --- a/src/simplifier.cpp +++ b/src/simplifier.cpp @@ -892,7 +892,13 @@ static bool hasTriangleFlip(const Vector3& a, const Vector3& b, const Vector3& c Vector3 nbc = {eb.y * ec.z - eb.z * ec.y, eb.z * ec.x - eb.x * ec.z, eb.x * ec.y - eb.y * ec.x}; Vector3 nbd = {eb.y * ed.z - eb.z * ed.y, eb.z * ed.x - eb.x * ed.z, eb.x * ed.y - eb.y * ed.x}; - return nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z <= 0; + float ndp = nbc.x * nbd.x + nbc.y * nbd.y + nbc.z * nbd.z; + float abc = nbc.x * nbc.x + nbc.y * nbc.y + nbc.z * nbc.z; + float abd = nbd.x * nbd.x + nbd.y * nbd.y + nbd.z * nbd.z; + + // scale is cos(angle); somewhat arbitrarily set to ~75 degrees + // note that the "pure" check is ndp <= 0 (90 degree cutoff) but that allows flipping through a series of close-to-90 collapses + return ndp <= 0.25f * sqrtf(abc * abd); } static bool hasTriangleFlips(const EdgeAdjacency& adjacency, const Vector3* vertex_positions, const unsigned int* collapse_remap, unsigned int i0, unsigned int i1)