2

My program reads in an ASCII encoded .stl file and parses it to a TriangleMesh, in order to display it on the screen. It works fine as long as I only want a single colour for the entire geometry. But now I want to be able to assign different colours to different polygons on the mesh. Later down the line we are going to know which face will have to be given what colour but right now a prove of concept is sufficient. Unfortunately I can't get it to work. Here is what I have thus far:

public static MeshView parseSTLwithColor(String stlString){
    TriangleMesh mesh = new TriangleMesh();

    PhongMaterial textureMaterial = new PhongMaterial();
    Image texture = new Image("http://nikijacob.com/wp-content/uploads/2011/01/Mosaic.jpg");
    textureMaterial.setDiffuseMap(texture);

Just setting up a quick test texture with different colours in it.

    String withoutHeader = stlString.substring(12);
    String[] facetsArray = withoutHeader.split("endfacet");
    for(int h=0;h<facetsArray.length;h++){
        if(facetsArray[h].contains("endloop")){
        facetsArray[h] = facetsArray[h].substring(0,facetsArray[h].indexOf("endloop"));
        }
    }
    for(int i= 0 ; i<facetsArray.length;i++){
        int facetOffset = i*3; 
        String[] verticesArray = facetsArray[i].split("vertex");
        if(verticesArray.length != 4) break;
        for(int j=1;j<4;j++){
            String[] vectorArray = verticesArray[j].split(" ");
            for(int k=1;k<4;k++) mesh.getPoints().addAll(Float.parseFloat(vectorArray[k]));    

Yeah, not that great a way to do it but it was just a first try. Basically, The string of ASCII encoded mesh data is split into the mesh's faces, then each face is split into its 3 points, then each point gets split into 3 vectors, as we are in 3d. Each of those gets parsed into a Float and added to the TriangleMesh's points array.

            mesh.getTexCoords().addAll(1/(100+j),1/(100+j));
        }

Next I assign each point a texture coordinate. I tried giving each point slightly different coordinates, because I thought that might help. (But it didn't.)

        mesh.getFaces().addAll((facetOffset), (facetOffset),(1+facetOffset), (1+facetOffset),(2+facetOffset), (2+facetOffset));  
    }

    MeshView meshView = new MeshView(mesh);
    meshView.setMaterial(textureMaterial);
    return meshView;
}

And just a little bit of housekeeping. Build the faces from the points and texture coordinates, instantiate a MeshView and give it the texture, so that a textured Meshview can be returned.

Now, the problem manifests in the way that instead of assigning different colours to the faces, the entire surface of the 3d object seems to be given a mix of the entire texture. When I tested with a halve red and halve blue texture, the entire geometry was rendered purple.

2 Answers2

1

Uh... turns out it works when I use a .png located on my computer instead of a .gif from the internet.

0

Answering a very old question here, but just fell down this rabbit hole myself.

The long and short of it is: wrapping a texture around an STL file is not feasible with external programs.

The reason is because the STL file doesn't provide correct texture coordinate mapping (e.g. for .getTexCoords()).

That said, the normal maps are rougly unique, so I did do a bit of hacking with stripping out the normal vector from the facet (e.g. [1]), calculating the number of facets and square rooting that number (assuming we will fill a square image):

int facets = (int)Math.sqrt((lines.size() - 2) / 7);

Where: lines is a String[] of file length, the header and footer of the STL is 2 lines and there are 7 lines to describe each facet.

Then taking the normal vector and abusing it:

mesh.getTexCoords().addAll(((Float.parseFloat(n) + 1) / -2));

Where: n is a value in the normal vector and the + 1// -2 is about normalizing the normal vector from -1 -> 0, to 0 -> 1 (the accepted range for .getTexCoords()).

It's hacky, but it's a little more workable. You can at least make heads and tails of the texture.


The real solution here is to use an object (such as obj's vt export values) that actually outputs the UV mapping from a program such as Blender: https://blender.stackexchange.com/a/18428

[1]:

facet normal -0 0 1
  outer loop
    vertex -10 12 9
    vertex 10 0 9
    vertex 10 12 9
  endloop
endfacet
Dan
  • 501
  • 4
  • 8