JavaFX 3D用两个摄像机的两个场景观看相同的对象

问题描述

有没有办法让两个具有两个不同摄像机的场景,但同时查看同一对象而又不重复每个对象的实例? 我正在开发一个3D游戏,该游戏的主要场景是跟随玩家的摄像头,并且我想在角落里有另一个场景,可以显示同一环境的鸟瞰图,例如迷你地图。 有什么想法如何发展吗?

解决方法

对于初学者来说,您不能在同一阶段拥有两个场景。您可以有两个场景和两个阶段,但是显然这意味着具有重复的对象,需要在场景和阶段之间进行同步。

但是,有一种方法可以在同一阶段和同一场景中在整个3D节点的顶部获得一个小的 mini-map (2D)节点,每个节点都有自己的相机。

这基于answerFXyz库中现有的CameraView类。

如您所见,CameraView基本上是一个ImageView节点,它在主场景上移至右下角(或其他位置),而3D部分则移至{{1} }放在场景的中心。

subScene和imageView都可以具有鼠标/键盘事件处理功能,并且都具有摄像头,因此,从某种意义上来说,您可以拥有两个不同的3D视图,并且它们分别控制相同的3D对象。

要获得一个反映实物子场景内容的“实时” SubScene,看起来像真实的实物场景,但不复制对象,ImageView主要使用:

  • CameraView:使用subScene拍摄快照将为ImageView获取更新的图像。

  • Node::snapshot(请参阅javadoc。这项不太知名的功能允许基于给定相机以给定视角拍摄快照。

  • SnapshotParameters::setCamera,以便在每个帧/脉冲上再次执行此过程。

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

org.fxyz3d:fxyz3d:0.5.2

运行该应用程序,您将获得:

Mini-map 1

,您可以在小地图视图上移动相机以获取3D对象的不同视图:

Mini-map 2

现在,您可以同时使用3D subScene和2D cameraView来获得所需的效果。通过设置 @Override public void start(Stage stage) { // 1. SubScene // 3D node SpringMesh spring = new SpringMesh(10,2,8 * 2 * Math.PI,200,100,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); 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,SceneAntialiasing.BALANCED); stage.setTitle("MiniMapTest"); stage.setScene(scene); stage.show(); // start timer cameraView.startViewing(); } ,迷你地图将不允许用户互动,您可以控制其摄像头(即,保持给定的SubScene缩放级别...)。