JavaFX 3D - 如何为带有 3D 对象的组和带有 UI 控件的子场景设置不同的摄像机? [英] JavaFX 3D - How to set different cameras for Group with 3D object and SubScene with UI Controls?

查看:37
本文介绍了JavaFX 3D - 如何为带有 3D 对象的组和带有 UI 控件的子场景设置不同的摄像机?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于 JavaFX 8 中的新功能,可以将 3D 对象与 2D UI 控件相结合.

Due to new features in JavaFX 8, it became possible to combine 3D objects with 2D UI controls.

我将此文档用作手册:JavaFX 教程, 探索 JavaFX 3D.

I used this documents as manuals: JavaFX Tutorial, Exploring JavaFX 3D.

所以,我做了这个代码:

So, I made this code:

public class CastAnalytics extends Application {

    final Group root = new Group();
    final Group axisGroup = new Group();
    final XForm world = new XForm();
    final PerspectiveCamera camera = new PerspectiveCamera(true);
    final PerspectiveCamera subSceneCamera = new PerspectiveCamera(false);
    final XForm cameraXForm = new XForm();
    final XForm cameraXForm2 = new XForm();
    final XForm cameraXForm3 = new XForm();
    final double cameraDistance = 450;
    final XForm moleculeGroup = new XForm();
    private Timeline timeline;
    boolean timelinePlaying = false;
    double CONTROL_MULTIPLIER = 0.1;
    double SHIFT_MULTIPLIER = 0.1;
    double ALT_MULTIPLIER = 0.5;
    double mousePosX;
    double mousePosY;
    double mouseOldX;
    double mouseOldY;
    double mouseDeltaX;
    double mouseDeltaY;

    @Override
    public void start(Stage primaryStage) throws Exception{
        buildScene();
        buildCamera();
        buildAxes();

        Scene scene = new Scene(root, 1024, 768, true);
        scene.setFill(Color.GREY);
        handleKeyboard(scene, world);
        handleMouse(scene, world);

        primaryStage.setTitle("Sample Application");
        primaryStage.setScene(scene);
        primaryStage.show();


        scene.setCamera(subSceneCamera);
        scene.setCamera(camera);
    }

    private void buildScene() {
        root.getChildren().add(world);

        Label label = new Label("123");
        HBox hBox = new HBox();
        hBox.getChildren().add(label);
        SubScene subScene =  new SubScene(hBox, 200, 200);
        subScene.setLayoutX(100);
        subScene.setLayoutY(100);

        root.getChildren().addAll(subScene);
    }

    private void buildCamera() {
        root.getChildren().addAll(cameraXForm);
        cameraXForm.getChildren().add(cameraXForm2);
        cameraXForm2.getChildren().add(cameraXForm3);
        cameraXForm3.getChildren().add(camera);
        cameraXForm3.setRotateZ(180.0);

        camera.setNearClip(0.1);
        camera.setFarClip(10000.0);
        camera.setTranslateZ(-cameraDistance);
        cameraXForm.ry.setAngle(320.0);
        cameraXForm.rx.setAngle(40);
    }

    private void buildAxes() {
        Box box = new Box(200,200,200);


        axisGroup.getChildren().addAll(box);
        world.getChildren().addAll(axisGroup);
    }

    private void handleMouse(Scene scene, final Node root) {
        scene.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override public void handle(MouseEvent me) {
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseOldX = me.getSceneX();
                mouseOldY = me.getSceneY();
            }
        });
        scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent me) {
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseDeltaX = (mousePosX - mouseOldX);
                mouseDeltaY = (mousePosY - mouseOldY);

                double modifier = 1.0;
                double modifierFactor = 0.1;

                if (me.isControlDown()) {
                    modifier = 0.1;
                }
                if (me.isShiftDown()) {
                    modifier = 10.0;
                }
                if (me.isPrimaryButtonDown()) {
                    cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - mouseDeltaX * modifierFactor * modifier * 2.0);  // +
                    cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + mouseDeltaY * modifierFactor * modifier * 2.0);  // -
                } else if (me.isSecondaryButtonDown()) {
                    double z = camera.getTranslateZ();
                    double newZ = z + mouseDeltaX * modifierFactor * modifier;
                    camera.setTranslateZ(newZ);
                } else if (me.isMiddleButtonDown()) {
                    cameraXForm2.t.setX(cameraXForm2.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3);  // -
                    cameraXForm2.t.setY(cameraXForm2.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3);  // -
                }
            }
        });
    }

    private void handleKeyboard(Scene scene, final Node root) {
        final boolean moveCamera = true;
        scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                Duration currentTime;
                switch (event.getCode()) {
                    case Z:
                        if (event.isShiftDown()) {
                            cameraXForm.ry.setAngle(0.0);
                            cameraXForm.rx.setAngle(0.0);
                            camera.setTranslateZ(-300.0);
                        }
                        cameraXForm2.t.setX(0.0);
                        cameraXForm2.t.setY(0.0);
                        break;
                    case X:
                        if (event.isControlDown()) {
                            if (axisGroup.isVisible()) {
                                axisGroup.setVisible(false);
                            } else {
                                axisGroup.setVisible(true);
                            }
                        }
                        break;
                    case S:
                        if (event.isControlDown()) {
                            if (moleculeGroup.isVisible()) {
                                moleculeGroup.setVisible(false);
                            } else {
                                moleculeGroup.setVisible(true);
                            }
                        }
                        break;
                    case SPACE:
                        if (timelinePlaying) {
                            timeline.pause();
                            timelinePlaying = false;
                        } else {
                            timeline.play();
                            timelinePlaying = true;
                        }
                        break;
                    case UP:
                        if (event.isControlDown() && event.isShiftDown()) {
                            cameraXForm2.t.setY(cameraXForm2.t.getY() - 10.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown() && event.isShiftDown()) {
                            cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() - 10.0 * ALT_MULTIPLIER);
                        } else if (event.isControlDown()) {
                            cameraXForm2.t.setY(cameraXForm2.t.getY() - 1.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown()) {
                            cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() - 2.0 * ALT_MULTIPLIER);
                        } else if (event.isShiftDown()) {
                            double z = camera.getTranslateZ();
                            double newZ = z + 5.0 * SHIFT_MULTIPLIER;
                            camera.setTranslateZ(newZ);
                        }
                        break;
                    case DOWN:
                        if (event.isControlDown() && event.isShiftDown()) {
                            cameraXForm2.t.setY(cameraXForm2.t.getY() + 10.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown() && event.isShiftDown()) {
                            cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + 10.0 * ALT_MULTIPLIER);
                        } else if (event.isControlDown()) {
                            cameraXForm2.t.setY(cameraXForm2.t.getY() + 1.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown()) {
                            cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + 2.0 * ALT_MULTIPLIER);
                        } else if (event.isShiftDown()) {
                            double z = camera.getTranslateZ();
                            double newZ = z - 5.0 * SHIFT_MULTIPLIER;
                            camera.setTranslateZ(newZ);
                        }
                        break;
                    case RIGHT:
                        if (event.isControlDown() && event.isShiftDown()) {
                            cameraXForm2.t.setX(cameraXForm2.t.getX() + 10.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown() && event.isShiftDown()) {
                            cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - 10.0 * ALT_MULTIPLIER);
                        } else if (event.isControlDown()) {
                            cameraXForm2.t.setX(cameraXForm2.t.getX() + 1.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown()) {
                            cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - 2.0 * ALT_MULTIPLIER);
                        }
                        break;
                    case LEFT:
                        if (event.isControlDown() && event.isShiftDown()) {
                            cameraXForm2.t.setX(cameraXForm2.t.getX() - 10.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown() && event.isShiftDown()) {
                            cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() + 10.0 * ALT_MULTIPLIER);  // -
                        } else if (event.isControlDown()) {
                            cameraXForm2.t.setX(cameraXForm2.t.getX() - 1.0 * CONTROL_MULTIPLIER);
                        } else if (event.isAltDown()) {
                            cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() + 2.0 * ALT_MULTIPLIER);  // -
                        }
                        break;
                }
            }
        });
    }



    public static void main(String[] args) {
        launch(args);
    }
}

但是结果不是我所期望的.我想为 3D 对象上方的 UI 控件设置 Pane,但我得到的是:

But te result isn't that what I expected. I wanted to have Pane for UI controls above the 3D object, but what I get is this:

我做错了什么?

推荐答案

从我所做的(有限的)测试中我了解到,有两个选择:

From what I understand from the (limited) tests I have done, there are two options:

  1. 为子场景设置相机并将该子场景添加到根.您将只使用一台相机.您的世界必须是一个单独的组,并且必须通过转换世界组来实现飞行/旋转相机视图.

  1. Set a camera for a sub-scene and add that sub-scene to the root. You will be using only one camera. Your world will have to be a separate group and flying/pivoting camera view will have to be accomplished by transforming the world group.

使用 JavaFX jira 提交错误报告.

File a bug report with JavaFX jira.

我没有成功使用单独的相机作为子场景相机.应用于相机或子场景本身的任何变换都不会从类似于屏幕截图中的默认位置旋转子场景.在这一点上,Oracle 没有发布任何子场景文档,我们只能等到它们清理干净并填补空白.在此之前,我们可以考虑破坏 JavaFX 3D 中的子场景支持.

I was not successful using a separate camera as a sub-scene camera. No transforms applied to the camera or a sub-scene itself ever rotated a sub-scene from the default position similar to the one in your screenshot. At this point with Oracle not releasing any sub-scene documentation, we can only wait till they come clean and fill the gaps. Until then we can consider subscene support in JavaFX 3D broken.

这篇关于JavaFX 3D - 如何为带有 3D 对象的组和带有 UI 控件的子场景设置不同的摄像机?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆