在javafx上的三角形网格中着色单个三角形 [英] Coloring individual triangles in a triangle mesh on javafx

查看:2254
本文介绍了在javafx上的三角形网格中着色单个三角形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JAVAFX中有一个三角形网格对象,并且想要


  1. 为三角形网格单独绘制三角形


  1. 每个三角形并根据每个顶点的颜色的插值(例如用Gouraud阴影表示)对三角形着色。

特定的三角形网格对象是一个有数百万个面的icosphere(这就是为什么我使用三角形网格:我需要速度)。



我没有使用纹理坐标因为我一直无法使用JAVAFX找到一个清楚的解释,加上我希望有一个更简单的方法。

解决方案

JavaFX 3D网格中的着色方式是由您分配它们的材质。对于一个网格,有一种材料,并且不可能将不同的材料分配给相同网格的不同三角形。



因此,如果你想避免纹理,恐怕唯一的方法是在同一个网格中将相同颜色的三角形分组,并创建如此多的网格作为颜色。



相反,纹理相对容易...因为你只有一个网格,一个材料和一个图像与所有的着色。



我举了一个二十面体的例子,建立了一个三角形)



请注意,映射是从(0,0)到(1,1)归一化坐标到图像(左,上)到(右,下)像素。



让我们终于创建场景,加载网格并将纹理添加到材质中:

  @Override 
public void start(Stage primaryStage)throws Exception {
Group sceneRoot = new Group();
场景scene =新场景(sceneRoot,600,600,true,SceneAntialiasing.BALANCED);
scene.setFill(Color.BLACK);
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
camera.setTranslateZ(-4);
scene.setCamera(camera);

二十面体Mesh网格=新的二十面体Mesh();
mesh.setCullFace(CullFace.FRONT);
PhongMaterial mat = new PhongMaterial();
mat.setDiffuseMap(new Image(getClass()。getResourceAsStream(icosah_net.png)));
mesh.setMaterial(mat);
旋转rotateY =新旋转(0,0,0,0,Rotate.Y_AXIS);
mesh.getTransforms()。addAll(new Rotate(30,Rotate.X_AXIS),rotateY);

sceneRoot.getChildren()。addAll(mesh,new AmbientLight(Color.WHITE));

primaryStage.setTitle(JavaFX 3D - Icosahedron);
primaryStage.setScene(scene);
primaryStage.show();
}

这是它的样子:





EDIT



现在,如果您考虑纹理的应用方式,您可以使用所需的颜色调色板将图像简化为多个方格:





纹理坐标可以真正简化:

  m.getTexCoords()。addAll 
0.1f,0.5f,// 0 red
0.3f,0.5f,// 1 green
0.5f,0.5f,// 2 blue
0.7f,0.5 f,// 3 yellow
0.9f,0.5f // 4 orange
);

最后,我们必须在我们的面上映射这些点。按照与网络图像相同的模式:

  m.getFaces()。addAll(
1,0,11 ,0,7,0,
1,4,7,4,6​​,4,
1,4,6,4,10,4,
1,2,10,2 ,3,2,
1,2,3,2,11,2,
4,3,8,3,0,3,
5,3,4,3,0 ,3,
9,1,5,1,0,1,
2,1,9,1,0,1,
8,0,2,0,0,0 ,

11,3,9,3,7,3,
7,1,2,1,6,1,
6,1,8,1,10 ,1,
10,0,4,0,3,0,
3,0,5,0,11,0,

4,4,10,4 ,8,4,
5,4,3,4,4,4,
9,2,11,2,5,2,
2,2,7,2,9 ,2,
8,3,6,3,2,3
);

现在我们将有一个非常整洁的二十面体,因为我们摆脱了边界和坏的分辨率图片:





这可以扩展到任何三角形网格,或使用任何 algorithm 来细化三角形。


I have a triangle mesh object in JAVAFX and would like to either

  1. color individual triangles of the triangle mesh

or

  1. color individual vertices of each triangle and have the triangle be colored according to an interpolation of the colors of each vertex (say for instance with a Gouraud shading).

The particular triangle mesh object is an icosphere with millions of faces (that is why I am using a triangle mesh: I need speed).

I have NOT used texture coordinates since I have been unable to find a clear explanation to it using JAVAFX, plus I am hoping that there is a easier way.

解决方案

The way coloring works in JavaFX 3D meshes is by the material you assign them. For one mesh there's one material, and it's not possible to assing different materials to different triangles of the same mesh.

So if you want to avoid textures, I'm afraid the only way is grouping triangles with the same color in the same mesh, and creating so many meshes as colors.

On the contrary, with textures is relatively easy..., since you have just one mesh, one material and one image with all the coloring.

I've made an example of an icosahedron, built a triangle mesh for it and added a single texture to color all the faces.

For that, we need:

  • the 3D coordinates of the 12 vertex,
  • the 2D normalized coordinates of the uv mapping for the textures.
  • and the 20 faces. Each face is defined by 6 indices p0, t0, p1, t1, p3, t3, where p0, p1, p2 and p3 are indices into the points array, and t0, t1, t2 and t3 are indices into the texCoords array.

    public class IcosahedronMesh extends MeshView {

    public IcosahedronMesh(){
        setMesh(createCube());
    }
    private TriangleMesh createCube() {
        TriangleMesh m = new TriangleMesh();
    
        // POINTS
        m.getPoints().addAll(
            0f, 0f, -0.951057f, 
            0f, 0f, 0.951057f, 
            -0.850651f, 0f, -0.425325f, 
            0.850651f, 0f, 0.425325f, 
            0.688191f, -0.5f, -0.425325f, 
            0.688191f, 0.5f, -0.425325f, 
            -0.688191f, -0.5f, 0.425325f, 
            -0.688191f, 0.5f, 0.425325f, 
            -0.262866f, -0.809017f, -0.425325f, 
            -0.262866f, 0.809017f, -0.425325f, 
            0.262866f, -0.809017f, 0.425325f, 
            0.262866f, 0.809017f, 0.425325f
        );
    
        // TEXTURES
        m.getTexCoords().addAll(
                0.181818f, 0f, 
                0.363636f, 0f, 
                0.545455f, 0f, 
                0.727273f, 0f, 
                0.909091f, 0f,
                0.0909091f, 0.333333f,
                0.272727f, 0.333333f, 
                0.454545f, 0.333333f, 
                0.636364f, 0.333333f, 
                0.818182f, 0.333333f, 
                1f, 0.333333f, 
                0f, 0.666667f, 
                0.181818f, 0.666667f, 
                0.363636f, 0.666667f, 
                0.545455f, 0.666667f, 
                0.727273f, 0.666667f, 
                0.909091f, 0.666667f, 
                0.0909091f, 1f, 
                0.272727f, 1f, 
                0.454545f, 1f, 
                0.636364f, 1f, 
                0.818182f, 1f
        );
    
        // FACES
        m.getFaces().addAll(
                1, 6, 11, 5, 7, 0, 
                1, 12, 7, 11, 6, 5, 
                1, 7, 6, 6, 10, 1, 
                1, 13, 10, 12, 3, 6, 
                1, 8, 3, 7, 11, 2,
                4, 14, 8, 13, 0, 7, 
                5, 9, 4, 8, 0, 3, 
                9, 15, 5, 14, 0, 8, 
                2, 10, 9, 9, 0, 4, 
                8, 16, 2, 15, 0, 9,
                11, 5, 9, 6, 7, 12,
                7, 11, 2, 12, 6, 17, 
                6, 6, 8, 7, 10, 13, 
                10, 12, 4, 13, 3, 18, 
                3, 7, 5, 8, 11, 14,
                4, 13, 10, 14, 8, 19, 
                5, 8, 3, 9, 4, 15, 
                9, 14, 11, 15, 5, 20, 
                2, 9, 7, 10, 9, 16, 
                8, 15, 6, 16, 2, 21
        );
        return m;
    }
    

    }

Now we need an image with the coloring for each face, based on the net of an icosahedron, like this:

(Image found here)

Note that the mapping is done from the (0,0) to (1,1) normalized coordinates to the image (left,top) to (right, bottom) pixels.

Let's finally create the scene, load the mesh and add the texture to its material:

@Override
public void start(Stage primaryStage) throws Exception {
    Group sceneRoot = new Group();
    Scene scene = new Scene(sceneRoot, 600, 600, true, SceneAntialiasing.BALANCED);
    scene.setFill(Color.BLACK);
    PerspectiveCamera camera = new PerspectiveCamera(true);
    camera.setNearClip(0.1);
    camera.setFarClip(10000.0);
    camera.setTranslateZ(-4);
    scene.setCamera(camera);

    IcosahedronMesh mesh = new IcosahedronMesh();
    mesh.setCullFace(CullFace.FRONT);
    PhongMaterial mat = new PhongMaterial();
    mat.setDiffuseMap(new Image(getClass().getResourceAsStream("icosah_net.png")));
    mesh.setMaterial(mat);
    Rotate rotateY = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS);
    mesh.getTransforms().addAll(new Rotate(30,Rotate.X_AXIS),rotateY);

    sceneRoot.getChildren().addAll(mesh, new AmbientLight(Color.WHITE));

    primaryStage.setTitle("JavaFX 3D - Icosahedron");
    primaryStage.setScene(scene);
    primaryStage.show();        
}

This is how it looks like:

EDIT

Now, if you think about how the texture is applied, you could simplify the image up to several squares with the palette of colors you need:

And the texture coordinates can be really simplified:

m.getTexCoords().addAll(
        0.1f, 0.5f, // 0 red
        0.3f, 0.5f, // 1 green
        0.5f, 0.5f, // 2 blue
        0.7f, 0.5f, // 3 yellow
        0.9f, 0.5f  // 4 orange
);

Finally, we have to map those points in our faces. Following the same pattern as the net image:

m.getFaces().addAll(
        1, 0, 11, 0, 7, 0, 
        1, 4, 7, 4, 6, 4, 
        1, 4, 6, 4, 10, 4, 
        1, 2, 10, 2, 3, 2, 
        1, 2, 3, 2, 11, 2,                
        4, 3, 8, 3, 0, 3, 
        5, 3, 4, 3, 0, 3, 
        9, 1, 5, 1, 0, 1, 
        2, 1, 9, 1, 0, 1, 
        8, 0, 2, 0, 0, 0, 

        11, 3, 9, 3, 7, 3,
        7, 1, 2, 1, 6, 1, 
        6, 1, 8, 1, 10, 1, 
        10, 0, 4, 0, 3, 0, 
        3, 0, 5, 0, 11, 0,

        4, 4, 10, 4, 8, 4, 
        5, 4, 3, 4, 4, 4, 
        9, 2, 11, 2, 5, 2, 
        2, 2, 7, 2, 9, 2, 
        8, 3, 6, 3, 2, 3
);

Now we'll have a very neat icosahedron, since we get rid of the borders and bad resolution of the image:

This can be extended to any triangle mesh, or use any algorithm to refine the triangles.

这篇关于在javafx上的三角形网格中着色单个三角形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆