JavaFX 3D 有两个场景,两个摄像头查看相同的对象

JavaFX 3D Having two scenes with two cameras viewing the same objects

有没有办法让两个场景有两个不同的相机,但同时查看相同的对象而不复制每个对象的实例? 我正在开发一款 3D 游戏,其主场景带有跟随玩家的摄像头,我希望在角落有另一个场景,显示相同环境的鸟瞰图,如迷你地图。 对如何开发这个有什么想法吗?

首先,你不能在同一个舞台上有两个场景。你可以有两个场景和两个舞台,但显然这意味着有重复的对象,需要在场景和舞台之间同步。

但是,有可能在同一阶段和同一场景中,在整个 3D 节点之上获得一个小的 mini-map (2D) 节点, 他们每个人都有自己的相机。

这是基于这个 answer, and the existing CameraView class in the FXyz 库。

如您所见,CameraView 基本上是一个 ImageView 节点,它在主场景上到达右下角(或其他任何地方),而 3D 部分进入 SubScene在场景中央。

subScene 和 imageView 都可以有 mouse/keyboard 事件处理,并且都有相机,所以在某种程度上你有两个不同的 3D 视图,它们自己控制同一个 3D 对象。

要获得反映子场景内容的“实时”ImageView,看起来像真实的子场景,但没有复制对象,CameraView主要使用:

  • Node::snapshot:拍摄子场景的快照将获得 ImageView 的更新图像。

  • SnapshotParameters::setCamera(参见 javadoc。这并非如此 well-known 功能允许基于给定相机以给定视角拍摄快照。

  • AnimationTimer 在每个 frame/pulse.

    上重新执行此过程

以下是 CameraView 的一个简单用例,可以添加到您的项目中,包括 org.fxyz3d:fxyz3d:0.5.2 依赖项。

    @Override
    public void start(Stage stage) {

        // 1. SubScene

        // 3D node
        SpringMesh spring = new SpringMesh(10, 2, 2, 8 * 2 * Math.PI, 200, 100, 0, 0);
        spring.setCullFace(CullFace.NONE);
        spring.setTextureModeVertices3D(1530, p -> p.f);

        // root
        Group worldRoot = new Group(spring);

        // Camera
        PerspectiveCamera camera = new PerspectiveCamera(true);
        CameraTransformer cameraTransform = new CameraTransformer();
        cameraTransform.setTranslate(0, 0, 0);
        cameraTransform.getChildren().add(camera);
        camera.setNearClip(0.1);
        camera.setFarClip(10000.0);
        camera.setTranslateZ(-100);
        camera.setFieldOfView(20);
        cameraTransform.ry.setAngle(-30.0);
        cameraTransform.rx.setAngle(-15.0);
        worldRoot.getChildren().add(cameraTransform);

        // SubScene
        SubScene subScene = new SubScene(worldRoot, 800,600, true, SceneAntialiasing.BALANCED);
        subScene.setFill(Color.DARKSLATEGRAY);
        subScene.setCamera(camera);

        // mouse, key events on subScene:
    
        // subScene.setOnKeyPressed(event -> {...});
        // subScene.setOnMousePressed(event -> {...});
        // subScene.setOnMouseDragged(event -> {...});

        // 2. CameraView
        CameraView cameraView = new CameraView(subScene);
        cameraView.setFirstPersonNavigationEabled(true);
        cameraView.setFitWidth(350);
        cameraView.setFitHeight(225);
        cameraView.getRx().setAngle(-45);
        cameraView.getT().setZ(-100);
        cameraView.getT().setY(-500);
        cameraView.getCamera().setTranslateZ(-100);

        // Right-bottom corner
        StackPane.setAlignment(cameraView, Pos.BOTTOM_RIGHT);
        StackPane.setMargin(cameraView, new Insets(5));

        // 3. Scene
        StackPane root = new StackPane(subScene, cameraView);
        root.setStyle("-fx-background-color: DEEPSKYBLUE;");
        subScene.widthProperty().bind(root.widthProperty());
        subScene.heightProperty().bind(root.heightProperty());

        Scene scene = new Scene(root, 810,610, true, SceneAntialiasing.BALANCED);
        stage.setTitle("MiniMapTest");
        stage.setScene(scene);
        stage.show();

        // start timer
        cameraView.startViewing();
    }

运行申请,您将获得:

并且您可以在 mini-map 视图上移动相机以获得 3D 对象的不同视图:

现在您可以同时使用 3D subScene 和 2D cameraView 来获得您想要的效果。通过设置 cameraView.setFirstPersonNavigationEabled(false),mini-map 将不允许用户交互,您可以控制它的相机(即,保持子场景的给定缩放级别...)。