【问题标题】:How to render the front and back faces of triangles identically in JavaFX如何在JavaFX中相同地渲染三角形的正面和背面
【发布时间】:2014-10-01 03:51:34
【问题描述】:

我开始使用 JavaFX 来可视化 3D 非结构化网格,但遇到了渲染问题。

如 [1] 中所述,JavaFX 仅渲染三角形的正面,除非您使用 CullFace.NONE 选项。但是背面是黑色的。

由于 3D 网格是由外部工具生成的(例如 Gmsh http://geuz.org/gmsh/),我无法控制面的方向。使用网格的科学软件也不需要定向网格。

因此我不想在之后重新定位网格,只是为了相同地渲染三角形的正面和背面。 JavaFX 8可以做到这一点吗?怎么样?

感谢您的回答。

值得注意:我还在 Oracle 论坛 [2] 上发布了一个类似的问题,但它们似乎很空洞。如果你们中的一些人知道 JavaFX 社区在哪里活跃,那么链接会很有用。如果我有有用的答案要分享,我当然会更新这两个主题。

亲切的问候

[1]How to make sense of JavaFX triangle mesh?

[2]https://community.oracle.com/thread/3593434

【问题讨论】:

  • 你有想过这个吗?我有完全相同的问题。
  • 不。我只是放弃了,没有使用 JavaFX,而是使用了 VTK 及其 Java 包装。不知道最新版本是否解决了这个问题。
  • 该死。我在任何地方都找不到有关此主题的任何内容。
  • 那就试试VTK吧。抱歉,我帮不上忙
  • 或 jOGL。也许它可以提供帮助。

标签: 3d javafx rendering


【解决方案1】:

解决方案 1

您可以通过绘制两组具有不同面方向的网格来解决该问题。请参阅下面的结果和代码。但是,这会使数据量和处理时间增加一倍。

PS:还有一个问题值得一提。目前尚不清楚在当前版本的 JavaFX(@August 2014)中,您是否可以为网格边缘着色与面不同。如果您需要使平面拼贴的单个拼贴可见,这将是必要的。解决方案是再次添加两组网格对象。但这会使所需资源增加四倍。

另外,人们想剔除一些不必要的边缘。在下图中,只需要突出显示地板边缘,而不是对角线。

解决方案 2

用 3D 网格对象替换每个网格面,例如,您可以创建一个平板而不是矩形表面。因此,一个打开的盒子对象将由五块板组成,盒子的内部和外部将具有相同的颜色。与第一个解决方案一样,此解决方案仍然是一个 hack,并且仍然会产生处理开销。

数字

实际 JavaFX 渲染与所需渲染(在 Matlab 中生成)之间的比较:

http://s30.postimg.org/iuotogvgh/3d_tower.jpg

部分解决方案:

http://s30.postimg.org/83dcwtpkx/3d_boxes.png

代码

import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;

/**
// * Draw polygonal 3D box.
// * 
// * INPUT
// * - footprint: 2D polygon coordinates; 
// *   closed path (i.e. first and last coordinates are identical); ex:
// *   float[] footprint = {
// *       10, -1,
// *       -1, -1,
// *       -1, 5,
// *       10, 5,
// *       10, -1
// *   };
// * - zLevel: z-coordinate of actual floor level: int k; float zLevel = k * HEIGHT - HEIGHT;
// * - HEIGHT: height of the box: private static final float HEIGHT = (float) 50;
// * 
// * NOTE: we have to use the mesh method since the straightforward way
// * to construct a rectangle - "rectangle" method - produces blurry edges.
// *
// */
public class DrawPolygonalBox {

// Draw polygonal 3D box.
public static Group draw(float[] footprint, float zLevel, float HEIGHT) {

    Group box = new Group();
    int y = 0;

    // for each footprint coordinate make a rectangle
    int n = footprint.length - 2;

    // one side of the box
    for (int k = 0; k < n; k = k + 2) {

        float[] points = {
            footprint[k], y + zLevel, footprint[k + 1],
            footprint[k + 2], y + zLevel, footprint[k + 3],
            footprint[k + 2], y + zLevel + HEIGHT, footprint[k + 3],
            footprint[k], y + zLevel + HEIGHT, footprint[k + 1]
        };            
        float[] texCoords = {
            1, 1,
            1, 0,
            0, 1,
            0, 0
        };
        int[] faces = {
            0, 0, 2, 2, 1, 1,
            0, 0, 3, 3, 2, 2
        };
        int[] faces2 = {
            0, 0, 1, 1, 2, 2,
            0, 0, 2, 2, 3, 3
        };

        TriangleMesh mesh1 = new TriangleMesh();
        mesh1.getPoints().setAll(points);
        mesh1.getTexCoords().setAll(texCoords);
        mesh1.getFaces().setAll(faces);

        TriangleMesh mesh2 = new TriangleMesh();
        mesh2.getPoints().setAll(points);
        mesh2.getTexCoords().setAll(texCoords);
        mesh2.getFaces().setAll(faces2);

        final MeshView rectangle1 = new MeshView(mesh1);
        rectangle1.setMaterial(new PhongMaterial(Color.web("#FF0000",0.25)));
        rectangle1.setCullFace(CullFace.BACK);

        final MeshView rectangle2 = new MeshView(mesh2);
        rectangle2.setMaterial(new PhongMaterial(Color.web("#FF0000",0.25)));
        rectangle2.setCullFace(CullFace.BACK);

        final MeshView wire1 = new MeshView(mesh1);
        wire1.setMaterial(new PhongMaterial(Color.web("#000000",0.5)));
        wire1.setCullFace(CullFace.BACK);
        wire1.setDrawMode(DrawMode.LINE);

        final MeshView wire2 = new MeshView(mesh2);
        wire2.setMaterial(new PhongMaterial(Color.web("#000000",0.5)));
        wire2.setCullFace(CullFace.BACK);
        wire2.setDrawMode(DrawMode.LINE);

        // add to group
        box.getChildren().addAll(rectangle1, wire1, rectangle2, wire2);
    }

    return box;
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    相关资源
    最近更新 更多