How to make sense of JavaFX triangle mesh?

前端 未结 1 1503
轮回少年
轮回少年 2021-02-04 21:50

Just trying to make sense of JavaFX documentation re triangle mesh. This code works and draws a rectangle.

public class Shape3DRectangle extends TriangleMesh {

         


        
1条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-04 22:23

    Explanation of how the face direction works

    The direction in which the face is defined is important. In the working sample, the point of the first face is 2, 1, 0 (i.e. the triangle is defined in a counter-clockwise order). In the faces array you suggest, the first face is 2, 0, 1 (clockwise). A face which is defined in a clockwise manner faces away from the viewer. A face which is defined in a counter-clockwise manner faces toward the viewer.

    How to make your mesh visible

    If you take your suggested face definition and rotate the mesh 180 degrees round the Y axis, you will see the face. Without rotation of the mesh, you will by default be looking at the back of the face, and the back of the mesh will be culled (i.e. not visible).

    Another way to see your mesh without rotation is to set the cull face of the Mesh to CullFace.NONE, then the back of the mesh will show (though as it will just show as black rather than a shaded region).

    A note on the comments in your supplied code

    The comment in your code sample is slightly misleading, it should reflect the the actual face definition rather than a face definition which doesn't really work as expected.

    Documentation request change suggestion

    IMO, the TriangleMesh documentation should be enhanced, I logged a change request in the JavaFX issue tracker against the runtime project to request this enhancement.

    Change request for documentation to highlight ordering of points in mesh faces is:

    RT-34292 Document importance of TriangleMesh order of elements

    Umbrella change request for documentation of the Java 8 3D API is:

    RT-26385 Finish javadoc for FX 8 3D API

    Demo

    Here is a sample test harness you can use for playing around with this concepts in order to understand them better.

    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() {
                @Override public void handle(MouseEvent event) {
                    anchorX = event.getSceneX();
                    anchorY = event.getSceneY();
                    anchorAngle = rect.getRotate();
                }
            });
    
            scene.setOnMouseDragged(new EventHandler() {
                @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);
            }
        }
    } 
    

    Demo Output

    Front and back faces of the rectangle mesh when the rectangle is drawn to be by default facing away the viewer (by defining a face in a clockwise direction) and with a CullFace.NONE setting (win7 jdkb115).

    backfront

    0 讨论(0)
提交回复
热议问题