javafx - 在javafx中向场景添加多个三角形网格的问题

标签 javafx mesh javafx-3d fxyz3d

希望有人能帮我解决这个问题。

我正在使用 javafx 和三角形网格来用三角形构造一个类似球体的对象(如足球)。形状的不同瓷砖通过颜色来区分,但我想在瓷砖之间添加线条。就像这个足球一样:

javafx提供的2D线条在3D空间中带来糟糕的性能。 因此我找到了FXyzLib提供 PolyLine3D 。这实际上只是另一个在 3D 空间中创建一条线的三角形网格。

用它我可以创建 3D 线条。但如果我想将它们添加到我原来的三角形网格中,其他所有东西都会变成黑色。反之亦然。我尝试了图书馆提供的示例,发现 here 。它创建了一条奇特的 3D 线,但当我尝试向场景添加一个简单的红色球体时,球体只是黑色,如下所示:

this .

我不是这方面的专家,而且是 javafx 的新手,在 PolyLine3D 的代码中找不到问题。 。将多个三角形网格添加到场景中应该不是问题。是否有一些我不知道的光线或相机效果?

最佳答案

虽然在场景中添加多个三角形网格体没有什么问题,但当您想要创建像足球图片中的网格体一样的网格体时,有一种更直接的方法,这样您就可以获得突出显示某些边缘但不是全部边缘的效果网格中的三角形。

可以使用将任何有效的封闭多边形作为面的 PolygonMesh 来完成。

此实现已存在于 3DViewer 项目中,该项目是开源的,可以在 here 中找到。 。有一个PolygonMeshView控件可以渲染PolygonMesh

请注意,如果您仅在项目中使用这两个类,则现在必须跳过分割网格。

这个answer已经使用四边形网格来渲染没有三角形网格对角边缘的盒子。

在底层,多边形网格使用三角形网格,并在内部将您提供的多边形转换为三角形。

截断二十面体网格

所以我们可以做类似的事情来生成 truncated icosahedron 的网格,这是我们可以用来生成简化足球模型的几何图形的名称。

它有 12 个正五边形面、20 个正六边形面和 60 个顶点。

我们需要这些顶点的 3D 坐标、纹理的 2D 坐标以及 32 个面中每个面的顶点和纹理的索引。

我使用了免费的在线沙箱 WolframCloud resource检索这些值。

例如,您可以运行:

Flatten[PolyhedronData["TruncatedIcosahedron","VertexCoordinates"]//N]

获取顶点坐标列表:

Out[1]= {-0.16246,-2.11803,1.27598,-0.16246,2.11803,...}

并且,您可以获得面孔:

PolyhedronData["TruncatedIcosahedron","FaceIndices"]
Out[2]= {{53,11,24,23,9},{51,39,40,52,30},...}

最后,您需要纹理坐标和索引,这可以通过 icosahedron 的网络检索。 :

PolyhedronData["TruncatedIcosahedron","Net"]
PolyhedronData["TruncatedIcosahedron","NetCoordinates"]

在本例中,您将获得 32 个面的 2D 坐标。鉴于我们希望所有五边形具有相同的纹理,所有六边形也具有相同的纹理,我对这些坐标进行了一些操作以得出此纹理图像:

只有 9 个顶点及其坐标(在 JavaFX 坐标系中)。

此方法包含创建网格所需的信息:

private PolygonMesh getTruncatedIcosahedron() {
    float[] points = new float[]{
        -0.16246f,-2.11803f,1.27598f,       -0.16246f,2.11803f,1.27598f, 
        0.16246f,-2.11803f,-1.27598f,       0.16246f,2.11803f,-1.27598f,
        -0.262866f,-0.809017f,-2.32744f,    -0.262866f,-2.42705f,-0.425325f,
        -0.262866f,0.809017f,-2.32744f,     -0.262866f,2.42705f,-0.425325f,
        0.262866f,-0.809017f,2.32744f,      0.262866f,-2.42705f,0.425325f, 
        0.262866f,0.809017f,2.32744f,       0.262866f,2.42705f,0.425325f,
        0.688191f,-0.5f,-2.32744f,          0.688191f,0.5f,-2.32744f,
        1.21392f,-2.11803f,0.425325f,       1.21392f,2.11803f,0.425325f,
        -2.06457f,-0.5f,1.27598f,           -2.06457f,0.5f,1.27598f,
        -1.37638f,-1.f,1.80171f,            -1.37638f,1.f,1.80171f,
        -1.37638f,-1.61803f,-1.27598f,      -1.37638f,1.61803f,-1.27598f,
        -0.688191f,-0.5f,2.32744f,          -0.688191f,0.5f,2.32744f,
        1.37638f,-1.f,-1.80171f,            1.37638f,1.f,-1.80171f,
        1.37638f,-1.61803f,1.27598f,        1.37638f,1.61803f,1.27598f,
        -1.7013f,0.f,-1.80171f,             1.7013f,0.f,1.80171f,
        -1.21392f,-2.11803f,-0.425325f,     -1.21392f,2.11803f,-0.425325f,
        -1.96417f,-0.809017f,-1.27598f,     -1.96417f,0.809017f,-1.27598f,
        2.06457f,-0.5f,-1.27598f,           2.06457f,0.5f,-1.27598f,
        2.22703f,-1.f,-0.425325f,           2.22703f,1.f,-0.425325f,
        2.38949f,-0.5f,0.425325f,           2.38949f,0.5f,0.425325f,
        -1.11352f,-1.80902f,1.27598f,       -1.11352f,1.80902f,1.27598f,
        1.11352f,-1.80902f,-1.27598f,       1.11352f,1.80902f,-1.27598f,
        -2.38949f,-0.5f,-0.425325f,         -2.38949f,0.5f,-0.425325f,
        -1.63925f,-1.80902f,0.425325f,      -1.63925f,1.80902f,0.425325f,
        1.63925f,-1.80902f,-0.425325f,      1.63925f,1.80902f,-0.425325f,
        1.96417f,-0.809017f,1.27598f,       1.96417f,0.809017f,1.27598f,
        0.850651f,0.f,2.32744f,             -2.22703f,-1.f,0.425325f,
        -2.22703f,1.f,0.425325f,            -0.850651f,0.f,-2.32744f,
        -0.525731f,-1.61803f,-1.80171f,     -0.525731f,1.61803f,-1.80171f,
        0.525731f,-1.61803f,1.80171f,       0.525731f,1.61803f,1.80171f};

    float[] texCoords = new float[]{0.904508f,0.820298f, 0.75f,0.529535f, 0.25f,0.529535f, 0.0954915f,0.820298f, 0.5f,1f, 
                                    1f,0.264767f, 0.75f,0f, 0.25f,0f, 0f,0.264767f};

    int faces[][] = new int[][]{{52,0,10,1,23,2,22,3,8,4},
                        {50,0,38,1,39,2,51,3,29,4},
                        {59,0,27,1,15,2,11,3,1,4},
                        {19,0,41,1,47,2,54,3,17,4},
                        {18,0,16,1,53,2,46,3,40,4},
                        {0,0,9,1,14,2,26,3,58,4},
                        {35,0,25,1,43,2,49,3,37,4},
                        {3,0,57,1,21,2,31,3,7,4},
                        {33,0,28,1,32,2,44,3,45,4},
                        {20,0,56,1,2,2,5,3,30,4},
                        {36,0,48,1,42,2,24,3,34,4},
                        {12,0,4,1,55,2,6,3,13,4},
                        {8,1,58,5,26,6,50,7,29,8,52,2},
                        {52,1,29,5,51,6,27,7,59,8,10,2},
                        {10,1,59,5,1,6,41,7,19,8,23,2},
                        {23,1,19,5,17,6,16,7,18,8,22,2},
                        {22,1,18,5,40,6,0,7,58,8,8,2},
                        {12,1,24,5,42,6,2,7,56,8,4,2},
                        {4,1,56,5,20,6,32,7,28,8,55,2},
                        {55,1,28,5,33,6,21,7,57,8,6,2},
                        {6,1,57,5,3,6,43,7,25,8,13,2},
                        {13,1,25,5,35,6,34,7,24,8,12,2},
                        {39,1,37,5,49,6,15,7,27,8,51,2},
                        {15,1,49,5,43,6,3,7,7,8,11,2},
                        {11,1,7,5,31,6,47,7,41,8,1,2},
                        {47,1,31,5,21,6,33,7,45,8,54,2},
                        {54,1,45,5,44,6,53,7,16,8,17,2},
                        {53,1,44,5,32,6,20,7,30,8,46,2},
                        {46,1,30,5,5,6,9,7,0,8,40,2},
                        {9,1,5,5,2,6,42,7,48,8,14,2},
                        {14,1,48,5,36,6,38,7,50,8,26,2},
                        {38,1,36,5,34,6,35,7,37,8,39,2}};

    int[] smooth = new int[] {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 
        31, 32
    };

    PolygonMesh mesh = new PolygonMesh(points, texCoords, faces);
    mesh.getFaceSmoothingGroups().addAll(smooth);
    return mesh;
}

现在您可以轻松地将其添加到场景中:

private double mouseOldX, mouseOldY = 0;
private final Rotate rotateX = new Rotate(0, Rotate.X_AXIS);
private final Rotate rotateY = new Rotate(0, Rotate.Y_AXIS);

@Override
public void start(Stage primaryStage) {

    PolygonMeshView meshView = new PolygonMeshView(getTruncatedIcosahedron());

    final PhongMaterial phongMaterial = new PhongMaterial();
    meshView.setDrawMode(DrawMode.LINE);
    meshView.setMaterial(phongMaterial);
    final Group group = new Group(meshView);
    group.getTransforms().add(new Scale(50, 50, 50));
    Scene scene = new Scene(group, 500, 300, true, SceneAntialiasing.BALANCED);
    scene.setOnMousePressed(event -> {
        mouseOldX = event.getSceneX();
        mouseOldY = event.getSceneY();
    });

    scene.setOnMouseDragged(event -> {
        rotateX.setAngle(rotateX.getAngle() - (event.getSceneY() - mouseOldY));
        rotateY.setAngle(rotateY.getAngle() + (event.getSceneX() - mouseOldX));
        mouseOldX = event.getSceneX();
        mouseOldY = event.getSceneY();
    });

    PerspectiveCamera camera = new PerspectiveCamera(false);
    camera.setNearClip(0.1);
    camera.setFarClip(1000.0);
    camera.getTransforms().addAll(rotateX, rotateY, new Translate(-250, -150, 0));
    scene.setCamera(camera);

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

将为您提供线框:

wireframe

如果你添加纹理图像,你就会得到你的足球:

phongMaterial.setDiffuseMap(new Image(getClass().getResourceAsStream("net3.png")));
meshView.setDrawMode(DrawMode.FILL);       

football

现在您可以根据自己的方便操作此信息,并将此网格修改为您要查找的网格。

关于javafx - 在javafx中向场景添加多个三角形网格的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52554535/

相关文章:

javafx - 在 javafx 中显示单 Pane 警报

javafx shape3d 纹理 : Don't strectch the image

c - 在 C 中显示 OpenGL 地形网格的问题

c - 如何对齐两个网格

geometry - 关于 BSpline 的问题

javafx-8 - javafx中3D场景上的静态2D文本

java - 在 JavaFX 中导入 STL 文件

java - 如何用 module-info.java 文件替换 VM 参数

javafx - 如何在JavaFX中使用JFoenix的JFXDialog创建对话框

java - 在 JavaFX 中动态添加组件