问题描述
有没有办法让两个具有两个不同摄像机的场景,但同时查看同一对象而又不重复每个对象的实例? 我正在开发一个3D游戏,该游戏的主要场景是跟随玩家的摄像头,并且我想在角落里有另一个场景,可以显示同一环境的鸟瞰图,例如迷你地图。 有什么想法如何发展吗?
解决方法
对于初学者来说,您不能在同一阶段拥有两个场景。您可以有两个场景和两个阶段,但是显然这意味着具有重复的对象,需要在场景和阶段之间进行同步。
但是,有一种方法可以在同一阶段和同一场景中在整个3D节点的顶部获得一个小的 mini-map (2D)节点,每个节点都有自己的相机。
这基于answer和FXyz库中现有的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
运行该应用程序,您将获得:
,您可以在小地图视图上移动相机以获取3D对象的不同视图:
现在,您可以同时使用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缩放级别...)。