Toxiclibs mesh glitches

edited May 2014 in Library Questions

I'm generating a mesh using Toxiclibs and the IsoSurface class, which works quite well. Once in a while I get some strange lines, as shown in the image:

img

This worries me, since the designs generated using the software will be 3D-printed and such inconsistencies might affect the fabrication process. Any ideas on what might be causing this? Would the mesh still be printable if this happens?

Answers

  • Maybe it's your data. Maybe it's your code. Maybe it's the library. Maybe it's the combination. I have used almost every marching cubes implementation (toxiclibs, hemesh, my own custom code and others) and I have never encountered such an issue. So my guess is that the problem is related to something you are doing. Try sending the same data into HE_Mesh and compare the results.

  • edited September 2014

    Okay so after a lot of testing and trial and error, I've found the source and cause of the problem.

    The glitches are caused by the LaplacianSmooth filter. The lines only occur when the mesh is smoothed with multiple passes as follows:

    LaplacianSmooth smoother = new LaplacianSmooth();
    WETriangleMesh w_mesh = mesh.toWEMesh();
    for(int i = 0; i < smoothing_passes; i++)
             smoother.filter(w_mesh, 2);
    

    The filter function has a numIterations argument, but the program throws a null pointer exception whenever I input more than 2 as numIterations. So that is why I was using a multiple smoothing pass approach in the first place.

    Any ideas on this?

  • Look at the source code: http://hg.postspectacular.com/toxiclibs/src/689ddcd9bea39d1f8dddad26e971ae4c12b1198e/src.core/toxi/geom/mesh/LaplacianSmooth.java?at=default

    Copy/paste/customize it/add println's to find out more information.

    My guess: meshes that are too small resulting in limitations of floating point accuracy, try scaling the mesh by a factor 1000, before applying smooth filters.

  • Thanks for the reply :) It seems there is an indexing problem. The nullpointer is thrown on line 63:

                for (Vertex v : filtered.keySet()) {
                    mesh.vertices.get(v).set(filtered.get(v));
                }
    

    I suppose this is because the vertices in the selection Collection become inconsistent with the mesh indexing after a few iterations.

    Updating the selection Collection with each iteration seemed to fix the null-pointer problem for me.

    I am still getting the lines once in while though, I guess it might be related to the indexing problem. Scaling doesn't help either.

    My fix:

    public class LaplacianSmooth implements WEMeshFilterStrategy {
    
        public void filter(VertexSelector selector, int numIterations) {
            Collection<Vertex> selection = selector.getSelection();
            if (!(selector.getMesh() instanceof WETriangleMesh)) {
                throw new IllegalArgumentException(
                        "This filter requires a WETriangleMesh");
            }
    
            final WETriangleMesh mesh = (WETriangleMesh) selector.getMesh();
            final HashMap<Vertex, Vec3D> filtered = new HashMap<Vertex, Vec3D>(
                    selection.size());
            for (int i = 0; i < numIterations; i++) {
                filtered.clear();
                selection = mesh.getVertices();
    
                for (Vertex v : selection) {
                    final Vec3D laplacian = new Vec3D();
                    final List<WEVertex> neighbours = ((WEVertex) v).getNeighbors();
                    for (WEVertex n : neighbours) {
                        laplacian.addSelf(n);
                    }
                    laplacian.scaleSelf(1f / neighbours.size());
                    filtered.put(v, laplacian);
                }
                for (Vertex v : filtered.keySet()) {
                    mesh.vertices.get(v).set(filtered.get(v));
                }
    
                mesh.rebuildIndex();
            }
            mesh.computeFaceNormals();
            mesh.computeVertexNormals();
        }
    
        public void filter(WETriangleMesh mesh, int numIterations) {
            filter(new DefaultSelector(mesh).selectVertices(), numIterations);
        }
    }
    
Sign In or Register to comment.