How to set axis (triad) at fixed position on screen in JavaFX?

后端 未结 5 1554
隐瞒了意图╮
隐瞒了意图╮ 2020-12-07 03:15

How to set axis (triad) at fixed position on screen in JavaFX? I am currently developing one application in which I want to show axis (triad) at fixed position on my screen

相关标签:
5条回答
  • 2020-12-07 03:41

    In order to see what you were seeing, I made these changes to TrafoTest and set the scene to black.

    I then modified this example to make the scene look more like yours, adding a sphere on one corner and shifting the axes to the corner opposite. I substituted a variation of your custom rotation Group and your mouse handler from here. The new group also rotates around z when isShiftDown(). Also note the slightly simpler camera dolly in the setOnScroll() handler. In particular, note that the axes can be translated independently as a group. Try this variation in Content.create().

    c.axes.setTranslateX(c.axes.getTranslateX() - 20);
    c.axes.setTranslateY(c.axes.getTranslateY() + 20);
    c.axes.setTranslateZ(c.axes.getTranslateZ() + 20);
    

    import javafx.application.Application;
    import javafx.geometry.Point3D;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    import javafx.scene.shape.DrawMode;
    import javafx.scene.shape.Sphere;
    import javafx.scene.transform.Rotate;
    import javafx.scene.transform.Transform;
    import javafx.stage.Stage;
    
    /**
     * @see https://stackoverflow.com/a/37755149/230513
     * @see https://stackoverflow.com/a/37743539/230513
     * @see https://stackoverflow.com/a/37370840/230513
     */
    public class TriadBox extends Application {
    
        private static final double SIZE = 300;
        private final Content content = Content.create(SIZE);
        private double mousePosX, mousePosY, mouseOldX, mouseOldY, mouseDeltaX, mouseDeltaY;
    
        private static final class Content {
    
            private static final double WIDTH = 3;
            private final Xform group = new Xform();
            private final Group cube = new Group();
            private final Group axes = new Group();
            private final Box xAxis;
            private final Box yAxis;
            private final Box zAxis;
            private final Box box;
            private final Sphere sphere;
    
            private static Content create(double size) {
                Content c = new Content(size);
                c.cube.getChildren().addAll(c.box, c.sphere);
                c.axes.getChildren().addAll(c.xAxis, c.yAxis, c.zAxis);
                c.group.getChildren().addAll(c.cube, c.axes);
                return c;
            }
    
            private Content(double size) {
                double edge = 3 * size / 4;
                xAxis = createBox(edge, WIDTH, WIDTH, edge);
                yAxis = createBox(WIDTH, edge / 2, WIDTH, edge);
                zAxis = createBox(WIDTH, WIDTH, edge / 4, edge);
                box = new Box(edge, edge / 2, edge / 4);
                box.setDrawMode(DrawMode.LINE);
                sphere = new Sphere(8);
                PhongMaterial redMaterial = new PhongMaterial();
                redMaterial.setDiffuseColor(Color.CORAL.darker());
                redMaterial.setSpecularColor(Color.CORAL);
                sphere.setMaterial(redMaterial);
                sphere.setTranslateX(edge / 2);
                sphere.setTranslateY(-edge / 4);
                sphere.setTranslateZ(-edge / 8);
            }
    
            private Box createBox(double w, double h, double d, double edge) {
                Box b = new Box(w, h, d);
                b.setMaterial(new PhongMaterial(Color.AQUA));
                b.setTranslateX(-edge / 2 + w / 2);
                b.setTranslateY(edge / 4 - h / 2);
                b.setTranslateZ(edge / 8 - d / 2);
                return b;
            }
        }
    
        private static class Xform extends Group {
    
            private final Point3D px = new Point3D(1.0, 0.0, 0.0);
            private final Point3D py = new Point3D(0.0, 1.0, 0.0);
            private Rotate r;
            private Transform t = new Rotate();
    
            public void rx(double angle) {
                r = new Rotate(angle, px);
                this.t = t.createConcatenation(r);
                this.getTransforms().clear();
                this.getTransforms().addAll(t);
            }
    
            public void ry(double angle) {
                r = new Rotate(angle, py);
                this.t = t.createConcatenation(r);
                this.getTransforms().clear();
                this.getTransforms().addAll(t);
            }
    
            public void rz(double angle) {
                r = new Rotate(angle);
                this.t = t.createConcatenation(r);
                this.getTransforms().clear();
                this.getTransforms().addAll(t);
            }
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.setTitle("JavaFX 3D");
            Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
            primaryStage.setScene(scene);
            scene.setFill(Color.BLACK);
            PerspectiveCamera camera = new PerspectiveCamera(true);
            camera.setFarClip(SIZE * 6);
            camera.setTranslateZ(-2 * SIZE);
            scene.setCamera(camera);
            scene.setOnMousePressed((MouseEvent e) -> {
                mousePosX = e.getSceneX();
                mousePosY = e.getSceneY();
                mouseOldX = e.getSceneX();
                mouseOldY = e.getSceneY();
            });
            scene.setOnMouseDragged((MouseEvent e) -> {
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = e.getSceneX();
                mousePosY = e.getSceneY();
                mouseDeltaX = (mousePosX - mouseOldX);
                mouseDeltaY = (mousePosY - mouseOldY);
                if (e.isShiftDown()) {
                    content.group.rz(-mouseDeltaX * 180.0 / scene.getWidth());
                } else if (e.isPrimaryButtonDown()) {
                    content.group.rx(+mouseDeltaY * 180.0 / scene.getHeight());
                    content.group.ry(-mouseDeltaX * 180.0 / scene.getWidth());
                } else if (e.isSecondaryButtonDown()) {
                    camera.setTranslateX(camera.getTranslateX() - mouseDeltaX * 0.1);
                    camera.setTranslateY(camera.getTranslateY() - mouseDeltaY * 0.1);
                    camera.setTranslateZ(camera.getTranslateZ() + mouseDeltaY);
                }
            });
            scene.setOnScroll((final ScrollEvent e) -> {
                camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
            });
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 03:44

    I wanted the axis to be fixed at left, bottom corner of the screen and axis should rotate about it's own origin.

    This variation leaves the axes at the origin, moves the box to

    P = (size / 2, -size / 2, -size / 2)
    

    relative to the axes, and pans the camera toward the bottom, center of the screen. Uncomment the call to camera.setTranslateX() to pan left. Moving the mouse causes the group to rotate about the axes' origin. Press shift to rotate about z, and use the mouse wheel to dolly the camera.

    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    
    /**
     * @see http://stackoverflow.com/a/37734966/230513
     * @see http://stackoverflow.com/a/37714700/230513
     * @see http://stackoverflow.com/a/37685167/230513
     * @see http://stackoverflow.com/a/37370840/230513
     */
    public class TriadBox extends Application {
    
        private static final double SIZE = 300;
        private final Content content = Content.create(SIZE);
    
        private static final class Content {
    
            private static final double WIDTH = 3;
            private final Group group = new Group();
            private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
            private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
            private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
            private final Box xAxis;
            private final Box yAxis;
            private final Box zAxis;
            private final Box box;
    
            private static Content create(double size) {
                Content c = new Content(size);
                c.group.getChildren().addAll(c.box, c.xAxis, c.yAxis, c.zAxis);
                c.group.getTransforms().addAll(c.rz, c.ry, c.rx);
                return c;
            }
    
            private Content(double size) {
                xAxis = createBox(size * 2, WIDTH, WIDTH);
                yAxis = createBox(WIDTH, size * 2, WIDTH);
                zAxis = createBox(WIDTH, WIDTH, size * 2);
                double edge = 3 * size / 4;
                box = new Box(edge, edge, edge);
                box.setMaterial(new PhongMaterial(Color.CORAL));
                box.setTranslateX(size / 2);
                box.setTranslateY(-size / 2);
                box.setTranslateZ(-size / 2);
            }
    
            private Box createBox(double w, double h, double d) {
                Box b = new Box(w, h, d);
                b.setMaterial(new PhongMaterial(Color.AQUA));
                return b;
            }
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.setTitle("JavaFX 3D");
            Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
            primaryStage.setScene(scene);
            scene.setFill(Color.BLACK);
            scene.setOnMouseMoved((final MouseEvent e) -> {
                if (e.isShiftDown()) {
                    content.rz.setAngle(e.getSceneX() * 360 / scene.getWidth());
                } else {
                    content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
                    content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
                }
            });
            PerspectiveCamera camera = new PerspectiveCamera(true);
            camera.setFarClip(SIZE * 6);
            //camera.setTranslateX(SIZE / 2);
            camera.setTranslateY(-SIZE / 2);
            camera.setTranslateZ(-4.5 * SIZE);
            scene.setCamera(camera);
            scene.setOnScroll((final ScrollEvent e) -> {
                camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
            });
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 03:45

    It may be easier to have separate groups for the rotatable content versus the fixed triad. In the example below, cube contains a single child, box, and three transforms, rx, ry and rz. In contrast, axes contains three axes with no transforms. The axes are translated to the lower left corner as a group, leaving the mouse handler free to manipulate the Rotate instances belonging to cube.

    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    
    /**
     * @see http://stackoverflow.com/a/37685167/230513
     * @see http://stackoverflow.com/a/37370840/230513
     */
    public class TriadBox extends Application {
    
        private static final double SIZE = 300;
        private final Content content = Content.create(SIZE);
    
        private static final class Content {
    
            private static final double WIDTH = 3;
            private final Group group = new Group();
            private final Group cube = new Group();
            private final Group axes = new Group();
            private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
            private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
            private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
            private final Box xAxis;
            private final Box yAxis;
            private final Box zAxis;
            private final Box box;
    
            private static Content create(double size) {
                Content c = new Content(size);
                c.cube.getChildren().add(c.box);
                c.cube.getTransforms().addAll(c.rz, c.ry, c.rx);
                c.axes.getChildren().addAll(c.xAxis, c.yAxis, c.zAxis);
                c.axes.setTranslateX(-size / 2);
                c.axes.setTranslateY(size / 2);
                c.group.getChildren().addAll(c.cube, c.axes);
                return c;
            }
    
            private Content(double size) {
                xAxis = createBox(size*2, WIDTH, WIDTH);
                yAxis = createBox(WIDTH, size*2, WIDTH);
                zAxis = createBox(WIDTH, WIDTH, size*2);
                double edge = 3 * SIZE / 4;
                box = new Box(edge, edge, edge);
                box.setMaterial(new PhongMaterial(Color.CORAL));
            }
    
            private Box createBox(double w, double h, double d) {
                Box b = new Box(w, h, d);
                b.setMaterial(new PhongMaterial(Color.AQUA));
                return b;
            }
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.setTitle("JavaFX 3D");
            Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
            primaryStage.setScene(scene);
            scene.setFill(Color.BLACK);
            scene.setOnMouseMoved((final MouseEvent e) -> {
                content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
                content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
            });
            PerspectiveCamera camera = new PerspectiveCamera(true);
            camera.setFarClip(SIZE * 6);
            camera.setTranslateZ(-3 * SIZE);
            scene.setCamera(camera);
            scene.setOnScroll((final ScrollEvent e) -> {
                camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
            });
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 03:45

    How to set axis (triad) at fixed position…I also wanted axis rotation in sync with box.

    In this example, the Content.create() factory method translates the triad of axes is to the point

    P = (-size / 2, size / 2, 0)
    

    Because its separate group has no transforms, the triad's origin "sticks" to that point in the space viewed by the camera.

    In contrast, the example below translates the triad of axes is to the point

    P = (-size / 2, size / 2, size / 2)
    

    Because the axes are in the same group as box, they undergo the same rotations.

    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    
    /**
     * @see https://stackoverflow.com/a/37714700/230513
     * @see https://stackoverflow.com/a/37685167/230513
     * @see https://stackoverflow.com/a/37370840/230513
     */
    public class TriadBox extends Application {
    
        private static final double SIZE = 300;
        private final Content content = Content.create(SIZE);
    
        private static final class Content {
    
            private static final double WIDTH = 3;
            private final Group group = new Group();
            private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
            private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
            private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
            private final Box xAxis;
            private final Box yAxis;
            private final Box zAxis;
            private final Box box;
    
            private static Content create(double size) {
                Content c = new Content(size);
                c.group.getChildren().addAll(c.box, c.xAxis, c.yAxis, c.zAxis);
                c.group.getTransforms().addAll(c.rz, c.ry, c.rx);
                return c;
            }
    
            private Content(double size) {
                xAxis = createBox(size * 2, WIDTH, WIDTH);
                xAxis.setTranslateY(size / 2);
                xAxis.setTranslateZ(size / 2);
                yAxis = createBox(WIDTH, size * 2, WIDTH);
                yAxis.setTranslateX(-size / 2);
                yAxis.setTranslateZ(size / 2);
                zAxis = createBox(WIDTH, WIDTH, size * 2);
                zAxis.setTranslateX(-size / 2);
                zAxis.setTranslateY(size / 2);
                double edge = 3 * size / 4;
                box = new Box(edge, edge, edge);
                box.setMaterial(new PhongMaterial(Color.CORAL));
            }
    
            private Box createBox(double w, double h, double d) {
                Box b = new Box(w, h, d);
                b.setMaterial(new PhongMaterial(Color.AQUA));
                return b;
            }
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.setTitle("JavaFX 3D");
            Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
            primaryStage.setScene(scene);
            scene.setFill(Color.BLACK);
            scene.setOnMouseMoved((final MouseEvent e) -> {
                if (e.isShiftDown()) {
                    content.rz.setAngle(e.getSceneX() * 360 / scene.getWidth());
                } else {
                    content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
                    content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
                }
            });
            PerspectiveCamera camera = new PerspectiveCamera(true);
            camera.setFarClip(SIZE * 6);
            camera.setTranslateZ(-3.5 * SIZE);
            scene.setCamera(camera);
            scene.setOnScroll((final ScrollEvent e) -> {
                camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
            });
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2020-12-07 04:03

    I wanted to rotate both main object and axis about their own center.

    For that, I would return to the original example that has separate groups for the content and triad. The variation below adds the same threes Rotate transforms to both cube and axes. As a result, the setOnMouseMoved() implementation causes the the two to rotate in synchrony. Mouse over the stage to see the effect.

    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    
    /**
     * @see https://stackoverflow.com/a/37743539/230513
     * @see https://stackoverflow.com/a/37370840/230513
     */
    public class TriadBox extends Application {
    
        private static final double SIZE = 300;
        private final Content content = Content.create(SIZE);
    
        private static final class Content {
    
            private static final double WIDTH = 3;
            private final Group group = new Group();
            private final Group cube = new Group();
            private final Group axes = new Group();
            private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
            private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
            private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
            private final Box xAxis;
            private final Box yAxis;
            private final Box zAxis;
            private final Box box;
    
            private static Content create(double size) {
                Content c = new Content(size);
                c.cube.getChildren().add(c.box);
                c.cube.getTransforms().addAll(c.rz, c.ry, c.rx);
                c.cube.setTranslateX(size / 2);
                c.axes.getChildren().addAll(c.xAxis, c.yAxis, c.zAxis);
                c.axes.getTransforms().addAll(c.rz, c.ry, c.rx);
                c.axes.setTranslateX(-size / 2);
                c.group.getChildren().addAll(c.cube, c.axes);
                return c;
            }
    
            private Content(double size) {
                xAxis = createBox(size, WIDTH, WIDTH);
                yAxis = createBox(WIDTH, size, WIDTH);
                zAxis = createBox(WIDTH, WIDTH, size);
                double edge = 3 * size / 5;
                box = new Box(edge, edge, edge);
                box.setMaterial(new PhongMaterial(Color.CORAL));
            }
    
            private Box createBox(double w, double h, double d) {
                Box b = new Box(w, h, d);
                b.setMaterial(new PhongMaterial(Color.AQUA));
                return b;
            }
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.setTitle("JavaFX 3D");
            Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
            primaryStage.setScene(scene);
            scene.setFill(Color.BLACK);
            scene.setOnMouseMoved((final MouseEvent e) -> {
                if (e.isShiftDown()) {
                    content.rz.setAngle(e.getSceneX() * 360 / scene.getWidth());
                } else {
                    content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
                    content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
                }
            });
            PerspectiveCamera camera = new PerspectiveCamera(true);
            camera.setFarClip(SIZE * 6);
            camera.setTranslateZ(-4 * SIZE);
            scene.setCamera(camera);
            scene.setOnScroll((final ScrollEvent e) -> {
                camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
            });
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
提交回复
热议问题