JavaFX中以编程方式生成的TriangleMesh的纹理坐标

时间:2014-02-24 19:54:06

标签: java 3d javafx textures mesh

我的程序读入ASCII编码的.stl文件并将其解析为TriangleMesh,以便在屏幕上显示它。只要我只需要整个几何体的单一颜色,它就可以正常工作。但现在我希望能够为网格上的不同多边形分配不同的颜色。接下来,我们将知道哪个面将被赋予什么颜色,但现在概念的证明就足够了。不幸的是我无法让它发挥作用。 以下是我到目前为止的情况:

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);

只需设置一个不同颜色的快速测试纹理。

    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]));    

是的,这不是一个好方法,但这只是第一次尝试。基本上,ASCII编码的网格数据串被分割成网格的面,然后每个面被分成3个点,然后每个点被分成3个向量,就像我们在3d中一样。每个都被解析为Float并添加到TriangleMesh的点数组中。

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

接下来,我为每个点指定一个纹理坐标。我尝试给每个点稍微不同的坐标,因为我认为这可能会有所帮助。 (但事实并非如此。)

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

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

只是一点家务。从点和纹理坐标构建面,实例化MeshView并为其提供纹理,以便可以返回纹理化的网格视图。

现在,问题在于,不是为面部分配不同的颜色,而是3d对象的整个表面似乎被赋予了整个纹理的混合。当我用一半的红色和一半的蓝色纹理进行测试时,整个几何体呈现为紫色。

2 个答案:

答案 0 :(得分:1)

呃...当我使用位于我的计算机上的.png而不是来自互联网的.gif时,它会起作用。

答案 1 :(得分:0)

在这里回答一个非常古老的问题,但我自己就摔倒了这个兔子洞。

它的长短是:使用外部程序在STL文件周围包裹纹理是不可行的。

原因是因为STL文件没有提供正确的纹理坐标映射(例如.getTexCoords())。

也就是说,法线贴图是独一无二的,所以我确实做了一些黑客攻击,从小平面剥离法线向量(例如[1]),计算小平面的数量和平方根数(假设我们将填充方形图像):

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

其中:lines是文件长度的String[],STL的页眉和页脚是2行,有7行描述每个方面。

然后取正常的矢量并滥用它:

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

其中:n是法线向量中的值,而+ 1 / / -2是关于将法线向量归一化为-1 - &gt; 0,到0 - &gt; 1(.getTexCoords())的可接受范围。

这很hacky,但它更可行。你至少可以做出纹理的正面和反面。

这里的真正解决方案是使用实际从Blender等程序输出UV映射的对象(例如obj&#39} vt导出值):{{3} }

[1]:

facet normal -0 0 1
  outer loop
    vertex -10 12 9
    vertex 10 0 9
    vertex 10 12 9
  endloop
endfacet