sp4cerat/Fast-Quadric-Mesh-Simplification

Strange pits and bumps in certain meshes

Maeyanie opened this issue · 4 comments

I have noticed running a simplification over certain meshes (but not all) creates strange one-vertex pits and bumps, even in lossless mode. On the left is the original, on the right is the result of "simplify.exe face.obj face-out.obj 0.9" (using the simplify.exe from your bin.Windows directory to make sure it wasn't my code's fault).
image

The fun part is... it's much more prone to happening on Windows than Linux, even with the same file and settings. It also seems to be worse with a 64-bit compile than 32-bit.
There's no difference if it's compiled with GCC or Visual Studio, or if compiler optimizations are on or off.
Changing Simplify.h's internal types from "double" to "float" caused far more of them to appear, changing them to "long double" reduced the number significantly, however the size of them didn't change.

Here is the file used in that test: face.zip
(Originally from https://www.thingiverse.com/thing:4824024 but it has been slightly modified for the purpose of this bug.)

As I recall, Windows 64-bit defaults to 64-bit double (SSE compatible) precision for floating point calculations, while Windows 32-bit and Linux default to 80-bit long double (fpu compatible) precision. So for Linux, defining a value as double may make a variable take 64-bits, but the rounding errors for calculations may be done at 80-bits. The wiki for long double notes An exception is Microsoft Visual C++ for x86, which makes long double a synonym for double.

These notes sound relevant.

I wonder if /fp switch makes a difference

I wonder if /fp switch makes a difference

It didn't, but it was worth trying. All of /fp:precise, /fp:strict, and /fp:fast gave an identical result on Win64 with VC2019.

Edit: However, in MinGW GCC on Windows, using "-mfpmath=387" (instead of -mfpmath=sse) did cause improvements using doubles, but not as much as using long doubles. So I think you're right about the calculation bit depth being the difference across platforms.

@Maeyanie I have submitted a pull request that addresses this issue. You can test the example from my repository. For a Unix computer, you can test as follows:

g++ Main.cpp -O3 -o simplify
./simplify ~/face.obj ~/xface.obj 0.8 3

I'd actually given up on this getting fixed after a while and switched to a different library, but the fix is appreciated anyhow. I may switch back at some point in the future.