Evaluate the midpoint candidate in the vertex0-relative coordinate
frame by halving the edge delta, then translate each result using the
matching vertex0 coordinate.
The previous calculation halved absolute vertex1 coordinates and used
vertex0's X coordinate when reconstructing Y and Z, which could produce
severely misplaced collapse points and mesh spikes.
The shared library libmmesh.so is currently installed without a SONAME
version number (SONAME = "libmmesh.so", same as the .so symlink name).
Well-behaved shared libraries on Linux follow the libfoo.so.MAJOR
convention so that:
- The dynamic linker records the SONAME (libmmesh.so.1) in the
dependent binary, not the unversioned name.
- Multiple API versions can coexist under the same prefix without
collisions.
- Package managers know which .so file represents the library ABI and
which is the development symlink.
The top-level CMakeLists.txt already declares project(mmesh VERSION 1.0.0),
so PROJECT_VERSION and PROJECT_VERSION_MAJOR are available. We just need
to apply them to the shared library target via set_target_properties.
Github Copilot spotted a couple of potential issues in planar input cases.
when using MD_FLAGS_PLANAR_MODE. This mode is designed for height fields where
XY coordinates are mostly planar and Z normal inversions should be prevented.
The first issue was in the planar normal inversion detection logic, which
checked if oldnormal[2] * newnormal[2] <= 0.0. For truly coplanar triangles
(both lying in the XY plane), both normal Z components are 0, making their
product 0. This triggered the <= 0.0 condition and incorrectly rejected valid
coplanar decimations.
Solution:
Changed the planar mode normal inversion condition from <= 0.0 to < 0.0 across
all implementations. This allows:
Coplanar triangles (Z product = 0) to be decimated
Actual inversions (Z product < 0) to still be rejected
Same-facing triangles (Z product > 0) to be decimated
The second issue was in the SSE (Streaming SIMD Extensions) optimized code for
planar mode normal inversion checking. In planar mode, the algorithm needs to
detect when triangle normal Z components would flip sign after an edge
collapse, which would indicate an invalid geometric transformation for height
field data.
The SSE code was using _MM_SHUFFLE(3,3,3,3) to extract what it assumed was the
Z component from the normal vector cross product, but this shuffle pattern
actually extracts the W component (index 3) instead of the Z component (index
2). This caused the planar mode normal inversion check to examine the wrong
vector component, leading to incorrect decisions about which triangle collapses
were geometrically valid.
Solution
Changed the SSE shuffle instruction from _MM_SHUFFLE(3,3,3,3) to
_MM_SHUFFLE(2,2,2,2) in both affected SSE functions
(mdEdgeCollapsePenaltyTriangleSSE4p1f and mdEdgeCollapsePenaltyTriangleSSE3f)
to correctly extract the Z component for planar mode normal inversion checks.
Note that there seems to be a broader issue where small triangles densely
packed on the interior of a planar face have unexpectedly high collapse costs,
preventing their decimation. This is counterintuitive since these triangles
should be the "lowest hanging fruit" for simplification, but apparently follows
from how mmesh is doing its penalty calculations. Noticed in initial DSP tests,
which generated very dense floor meshes but weren't simplified.