【问题标题】:How to make sense of JavaFX triangle mesh?如何理解 JavaFX 三角形网格?
【发布时间】:2013-11-13 17:25:22
【问题描述】:

只是试图理解 JavaFX 文档重新三角形网格。 此代码有效并绘制了一个矩形。

public class Shape3DRectangle extends TriangleMesh {

    public Shape3DRectangle(float Width, float Height) {
        float[] points = {
            -Width/2,  Height/2, 0, // idx p0
            -Width/2, -Height/2, 0, // idx p1
             Width/2,  Height/2, 0, // idx p2
             Width/2, -Height/2, 0  // idx p3
        };
        float[] texCoords = {
            1, 1, // idx t0
            1, 0, // idx t1
            0, 1, // idx t2
            0, 0  // idx t3
        };
        /**
         * points:
         * 1      3
         *  -------   texture:
         *  |\    |  1,1    1,0
         *  | \   |    -------
         *  |  \  |    |     |
         *  |   \ |    |     |
         *  |    \|    -------
         *  -------  0,1    0,0
         * 0      2
         *
         * texture[3] 0,0 maps to vertex 2
         * texture[2] 0,1 maps to vertex 0
         * texture[0] 1,1 maps to vertex 1
         * texture[1] 1,0 maps to vertex 3
         * 
         * Two triangles define rectangular faces:
         * p0, t0, p1, t1, p2, t2 // First triangle of a textured rectangle 
         * p0, t0, p2, t2, p3, t3 // Second triangle of a textured rectangle
         */
        int[] faces = {
            2, 2, 1, 1, 0, 0,
            2, 2, 3, 3, 1, 1
        };

        this.getPoints().setAll(points);
        this.getTexCoords().setAll(texCoords);
        this.getFaces().setAll(faces);
    }
}

评论的最后 3 行来自Class TriangleMesh。我的问题是我在代码中看不到他们对 faces 数组的定义和 faces 数组之间的匹配。因此,不明白如何在其他情况下一般使用 faces 数组。不应该是这样吗:

        int[] faces = {
            2, 3, 0, 2, 1, 0,
            2, 3, 1, 0, 3, 1
        };

然后没有渲染矩形。 我缺少什么以及一般应该进入 faces 数组的内容?

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    面部方向如何工作的解释

    定义面部的方向很重要。在工作示例中,第一个面的点是 2、1、0(即,三角形是按逆时针顺序定义的)。在您建议的 faces 数组中,第一个面是 2, 0, 1(顺时针)。以顺时针方式定义的面背向观察者。以逆时针方式定义的面朝向观察者。

    如何让你的网格可见

    如果您采用建议的面定义并将网格绕 Y 轴旋转 180 度,您将看到面。如果不旋转网格,默认情况下您将看到脸部的背面,并且网格的背面将被剔除(即不可见)。

    另一种在不旋转的情况下查看网格的方法是 set the cull face of the MeshCullFace.NONE,然后网格的背面将显示(尽管它只会显示为黑色而不是阴影区域)。

    关于您提供的代码中的 cmets 的注释

    您的代码示例中的注释有点误导,它应该反映实际的人脸定义,而不是不能真正按预期工作的人脸定义。

    文档请求更改建议

    IMO,TriangleMesh 文档应该得到增强,我在 JavaFX 问题跟踪器中记录了针对运行时项目的更改请求以请求此增强。

    更改文档以突出显示网格面中点的顺序的请求是:

    JDK-8122785 Document importance of TriangleMesh order of elements

    Java 8 3D API 文档的总括变更请求是:

    JDK-8101810 Finish javadoc for FX 8 3D API

    演示

    这是一个示例测试工具,您可以使用这些测试工具来玩弄这些概念,以便更好地理解它们。

    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.scene.*;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.paint.*;
    import javafx.scene.shape.*;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    
    // drag the mouse over the rectangle to rotate it.
    public class RectangleViewer extends Application {
     
        double anchorX, anchorY, anchorAngle;
     
        private PerspectiveCamera addCamera(Scene scene) {
            PerspectiveCamera perspectiveCamera = new PerspectiveCamera(false);
            scene.setCamera(perspectiveCamera);
            return perspectiveCamera;
        }
     
        public static void main(String[] args) {
            launch(args);
        }
     
        @Override
        public void start(Stage primaryStage) {
            final MeshView rect = new MeshView(
                    new Shape3DRectangle(200, 200)
            );
            rect.setMaterial(new PhongMaterial(Color.DARKGREEN));
            rect.setRotationAxis(Rotate.Y_AXIS);
            rect.setTranslateX(250);
            rect.setTranslateY(250);
    // try commenting this line out to see what it's effect is . . .
            rect.setCullFace(CullFace.NONE);
    
            final Group root = new Group(rect);
            final Scene scene = new Scene(root, 500, 500, true);
     
            scene.setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override public void handle(MouseEvent event) {
                    anchorX = event.getSceneX();
                    anchorY = event.getSceneY();
                    anchorAngle = rect.getRotate();
                }
            });
     
            scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
                @Override public void handle(MouseEvent event) {
                    rect.setRotate(anchorAngle + anchorX - event.getSceneX());
                }
            });
    
    
            addCamera(scene);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public class Shape3DRectangle extends TriangleMesh {
    
            public Shape3DRectangle(float width, float height) {
                float[] points = {
                        -width/2,  height/2, 0, // idx p0
                        -width/2, -height/2, 0, // idx p1
                        width/2,  height/2, 0, // idx p2
                        width/2, -height/2, 0  // idx p3
                };
                float[] texCoords = {
                        1, 1, // idx t0
                        1, 0, // idx t1
                        0, 1, // idx t2
                        0, 0  // idx t3
                };
                /**
                 * points:
                 * 1      3
                 *  -------   texture:
                 *  |\    |  1,1    1,0
                 *  | \   |    -------
                 *  |  \  |    |     |
                 *  |   \ |    |     |
                 *  |    \|    -------
                 *  -------  0,1    0,0
                 * 0      2
                 *
                 * texture[3] 0,0 maps to vertex 2
                 * texture[2] 0,1 maps to vertex 0
                 * texture[0] 1,1 maps to vertex 1
                 * texture[1] 1,0 maps to vertex 3
                 *
                 * Two triangles define rectangular faces:
                 * p0, t0, p1, t1, p2, t2 // First triangle of a textured rectangle
                 * p0, t0, p2, t2, p3, t3 // Second triangle of a textured rectangle
                 */
    
    // if you use the co-ordinates as defined in the above comment, it will be all messed up
    //            int[] faces = {
    //                    0, 0, 1, 1, 2, 2,
    //                    0, 0, 2, 2, 3, 3
    //            };
    
    // try defining faces in a counter-clockwise order to see what the difference is.
    //            int[] faces = {
    //                    2, 2, 1, 1, 0, 0,
    //                    2, 2, 3, 3, 1, 1
    //            };
    
    // try defining faces in a clockwise order to see what the difference is.
                int[] faces = {
                        2, 3, 0, 2, 1, 0,
                        2, 3, 1, 0, 3, 1
                };
    
                this.getPoints().setAll(points);
                this.getTexCoords().setAll(texCoords);
                this.getFaces().setAll(faces);
            }
        }
    } 
    

    演示输出

    矩形网格的正面和背面在绘制矩形时默认背向观察者(通过定义顺时针方向的面)并具有 CullFace.NONE 设置 (win7 jdkb115)。

    常见问题解答

    为什么是高度/2

    我以这种方式定义模型坐标,因为在这种情况下,我希望我正在旋转的 3D 形状的中心是该形状的centroid。这样我就可以围绕其质心旋转形状,而无需执行额外的平移。请参阅 pivot point rotation 以查看围绕任意枢轴点旋转所需的额外平移。

    坐标原点是右下角吗?

    涉及多个坐标。具有局部坐标系的模型有坐标(参见@​​987654328@ 文档):

    Node 类定义了一个传统的计算机图形“局部”坐标系,其中 x 轴向右增加,y 轴向下增加。形状的具体节点类提供了用于定义该局部坐标空间内形状的几何形状和位置的变量。

    相机操作的场景有坐标。在 3D 透视应用程序中,相机是PerspectiveCamera。关于它如何影响坐标的信息是:

    默认情况下,此摄像机位于场景中心,并沿 Z 轴正方向观察。此相机定义的坐标系的原点位于面板的左上角,Y 轴指向下方,Z 轴指向远离观察者(进入屏幕)的方向。如果将 PerspectiveCamera 节点添加到场景图中,则转换后的相机位置和方向将定义相机的位置和相机正在看的方向。

    mesh 中也有纹理坐标。这些是completely different 并将纹理贴图上的点映射到模型上的顶点:

    术语 texCoord 用于表示单个顶点的一对 2D 纹理坐标 (u, v),而术语 texCoords(复数)用于表示多个顶点的纹理坐标集。

    【讨论】:

    • 感谢逆时针提示 - 它拯救了我的一天。但是,如果 Oracle 如此自鸣得意和无能,以至于他们乐于按原样发布他们的文档 - 就这样吧。我不会为帮助这家极其富有的公司改进他们的产品而付出任何努力。
    • @ajeh Java 8 仍在开发中,四个多月后不会发布。该文档目前仅针对每周开发快照构建提供。有时这样的事情有错误或不完整。 Oracle 将 Java 源代码及其随附的 javadoc 作为免费软件发布。
    • 同时它是一个最终产品,只有错误修复仍在进行中。
    • @ThomasStokes 查看更新后的答案。有时最好提出问题,例如将坐标问题作为单独的问题而不是评论。
    • 我为坐标问题添加的更新可能会造成混淆或误导,并且在某些情况下可能有点不正确。当我有更多时间时,我可能会删除或修改并澄清它。同时,我建议您将坐标问题作为一个新问题提出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2014-10-05
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    相关资源
    最近更新 更多