Yep, overall your results don't suprise me, the decimation is definatly one of the slow parts of PolyVox.
When I wrote the MeshDecimator I made two decisions which with the benefit of hindsight did not work out that well. The first decision is that the MeshDecimator is completely decoupled from the surface extractors. This seemed sensible (so that data can potentially come from different sources) but it results in a lot of wasted effort. One of the frst things the MeshDecimator has to do is compute the connentivity between the vertices and this is a pretty slow process (it's the call to buildConnectivityData()). But during surface extraction this information is much more readily available, it's just we already threw it away.
Secondly, the MeshDecimator is generic for the different mesh types (PositionMaterial and PositionMaterialNormal). Again this was to cut down on code but it throws away optimisation oppertunities. For example, it should be very fast to check whether a Minecraft style mesh can collapse was it it constrained to three axes, but it is more complex for a generic marching cubes mesh. Also, the 'collapseChangesFaceNormals()' function is pretty horrible.
The other issue is that I'm not using any of this decimation stuff myself simply because I haven't had a need for it. Have you tried
this demo? The large hills map is 1024x1024x256 and runs at 35FPS on my NVidia GTX 280. The result of this is that there hasn't been much incentive to improve the MeshDecimator. In your case, when you do perform the decimation, how much do you find it helps the framerate?
I might need it eventually for physics integration, and when that happens I will probably reimplement it very differently. If you want a crack at it your self this is what I would do:
- Change the surface extractor to generate quads instead of triangles. Keep track of the connectivity.
- Within the same function, perform the decimation by collapsing quads. Use fast tests designed just for cubic maps.
- Trianglulate the result.
Also, you might want to check out this thread:
http://www.thermite3d.org/phpBB3/viewtopic.php?t=98. I would aim to do something like that but inside the surface extractor.
One other thing I should point out is that the MeshDecimator currently get very expensive as the number of vertices increases (it is not a linear relationship). So if you wish to decimate a 32x32x32 region you might be better off generating 8 16x16x16 meshes, decimating those, and then stitching the results together. The result won't be quite the same (because of the stitching boundary) but it might be faster.