Summary I am currently on a new implementation of a Quadric based mesh simplification algorithm. Its quite short (130 lines for the main part) , but apparently there is a bug somewhere. I searched already a while but couldnt find it yet. If one of you can spot it, any help is appreciated.

In turn, everyone gets a great mesh simplification method for free once it works

Its able to reduce 90% of 650.000 triangles in about 1 sec. (Single threaded) by using less memory than most other methods.

Algorithm Different from the original method, it does not store the per-edge-error in an edges list, but per triangle. This avoids the edges list completely as the edge list is slow creating and updating. On the other hand, every error is computed twice - but that's not so serious.

Methods :

calculate_error calculates the error between two vertices and output the vertex an edge might be reduced to.

reduce_polygons main function to reduce the mesh

The Problem Here a screenshot of the bug: Some faces are flipped and look displaced..

Share this post

Link to post

Share on other sites

If you use a proper data structure (custom heap) for the edge list, you can get similar performance to your implementation, but with much better quality. This keeps the edge list sorted automatically, and if you store the position in the (array-based) heap along with the edge, you can get O(log(N)) updates/removals with each iteration. The problem with not updating the list of edges on each iteration is that the algorithm no longer optimally picks the edge with the least error, so your results will not be as good as the original quadric-error edge collapse algorithm.

The problem you're probably seeing is that triangles can flip over during an edge collapse, causing overlap of mostly coplanar triangles. You can fix this by checking each triangle that shares the edge vertices to make sure that its normal does not change sign (dot product with old normal < 0).

Share this post

Link to post

Share on other sites

Based on what criteria do you prioritize one contraction over the other? I don't see you (re-)sorting the list of triangles.

Its threshold based - one threshold for the edge length, and one for the quadric error. Once the triangle error problem is solved, I will try a sorted list for better quality.

Currently, the decision if a triangle is removed is performed in line 60 in the code above.

If you use a proper data structure (custom heap) for the edge list, you can get similar performance to your implementation, but with much better quality. This keeps the edge list sorted automatically, and if you store the position in the (array-based) heap along with the edge, you can get O(log(N)) updates/removals with each iteration. The problem with not updating the list of edges on each iteration is that the algorithm no longer optimally picks the edge with the least error, so your results will not be as good as the original quadric-error edge collapse algorithm.

The problem you're probably seeing is that triangles can flip over during an edge collapse, causing overlap of mostly coplanar triangles. You can fix this by checking each triangle that shares the edge vertices to make sure that its normal does not change sign (dot product with old normal < 0).

The triangle flipping is a good point. I have spend a lot of time now to figure out how to efficiently do this test without slowing down the method too much. The result is a modified method that stores a list of triangles for each vertex, where each of these triangles has one reference to this vertex. It allows to efficiently test for flipping and collapsing one vertex.

In the code below, the list with ids named refs. It is referred to by tstart,tcount from vertex and contains the triangle ID (tid) and vertex offset inside the triangle (tvertex). (In the current version it just grows - but in the final version it needs to be re-initialized every couple of iterations to avoid using too much ram)

The problem is that even it prevents some errors, still flipped triangles occur somehow. I could not yet resolve the problem. Is there anything else that can cause the flipping error ? Or can you spot an error in the flipping test below ? ( function flipped )

Edit: Seems I found a hint: the problem seems to arise when the triangles get almost line - shaped, so all 3 points are along one line.

For the speed, the method can basically be even faster as it doesnt require so many iterations.

I first need to resolve the error however, before speeding up and improving the quality by sorting.

For the edge based structure, I have tried a edge based structure before, but since I had referenced to the triangles in the edges it got quite messy to update them after one triangle was removed. The speed might be equal, yes.

Share this post

Link to post

Share on other sites

That's why you need to update the error for neighboring edges after each collapse and re-sort the edge collapse list at each iteration after adding newly created edges - there are collapses that you could still make but you don't know about them because they're not at the top of the heap, or they correspond to new edges that weren't in the original mesh, and therefore don't even exist in the collapse list.

Here's my working edge collapse code (won't compile as-is), but it's well-commented and should give you an idea of how to handle the resorting efficiently.

Share this post

Link to post

Share on other sites

I have downloaded the file and have a quick test. I noticed that there are executable files and I run the file .\bin64\PolygonSimplification.exe by double click it. I will load the wall.obj automatically and simplify it. However, it crashed latter. I tested another file but it also failed. Is there anything wrong?

In addition, can the program simplify the surface meshes which form several sub-domains? Currently I put two reverse ordered triangles in the surface which are common boundary of two neighbor sub-domains. Is it correct? If not, how to form the model with multiple sub-domains?