deadsy / sdfx

A simple CAD package using signed distance functions
MIT License
541 stars 52 forks source link

New dual contouring 3D mesh generator with support sharp edges and simplification. #41

Closed Yeicor closed 2 years ago

Yeicor commented 2 years ago

This should solve #6, building simpler meshes with support for sharp edges, at the cost of slower generation (but also less cells are needed).

This commit also generalizes the STL renderer, while keeping backwards compatibility with the previous public API (#22). In addition to selecting and configuring a mesher implementation, it allows library users to:

Demo

This is the scene at examples/pool/main.go, rendered with a maximum of 32 cells (differences are clearer with less cells, as dual contouring does not need as many cells as marching cubes for producing a high quality mesh)

Marching cubes (octree)

tmp1

Dual contouring

tmp2

deadsy commented 2 years ago

Do a pull. I've hacked away a bit at the way the rendering API is arranged but haven't touched the dc3.go code. It seems promising, but is ill behaved at the moment.

Observations:

The marching cubes use the meshCells parameter to work out the finest cube used for rendering. What does this mean for dual contouring? Upping the parameter for the pool example takes longer and produces a less accurate output.

If you try DC on a more challenging example (e.g. cylinder_head) the output is messed up (in interesting ways...).

render.ToSTL(pool, 100, "pool2.stl", &render.DualContouring{})

Screenshot_20211219_111227

render.ToSTL(pool, 300, "pool1.stl", &render.MarchingCubesOctree{})

Screenshot_20211219_111429

Yeicor commented 2 years ago

The error that you see is related to simplification code and goes away if you disable simplification (&render.DualContouring{Simplify: -1}). You may make this the default with code similar to the default of the RCond parameter.

I can't figure out what I messed up with simplification :sweat_smile:. Maybe someone can figure it out comparing it to the original (https://github.com/nickgildea/DualContouringSample). However, https://github.com/nickgildea/fast_dual_contouring claims that it is better to just simplify the mesh afterwards, using dual contouring only for sharp edges.

Here is cylinder_head properly generated without simplification: Screenshot_20211219_202513

I used meshCells in a similar way, as the number of vertices to generate in each axis (that can later be simplified, if enabled). But, to avoid issues with the octree, I take the next power of two as the number of cells on each axis e.g., 300 -> 512. It should produce more detailed output: if it produces less accurate output is probably due to simplification errors.

Note that if meshCells is too low to describe the surface, some operations may be unstable and create large invalid triangles. In that case, setting LockVertices: true will fix the problems. However, this may reduce accuracy of sharp edges when meshCells is big enough, so it is something that users should test for their use case. For example, here is cylinder_head with:

deadsy commented 2 years ago

Ok - so there are some bugs with "simplify".

Even with that off, there appear to be other bugs: Lots of little sores...

Screenshot_20211219_122847

and on the pool example:

Screenshot_20211219_123133

Yeicor commented 2 years ago

Those smooth shading errors are caused by slightly intersecting faces. I guess they are generated by numerical errors when determining the position of vertices. It does not affect flat shading.

deadsy commented 2 years ago

numerical errors

You mean bugs :-)

Yeicor commented 2 years ago

Yes, I'll take a look soon to see if I can fix it