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 将不允许用户交互,您可以控制它的相机(即,保持子场景的给定缩放级别...)。
有没有办法让两个场景有两个不同的相机,但同时查看相同的对象而不复制每个对象的实例? 我正在开发一款 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 将不允许用户交互,您可以控制它的相机(即,保持子场景的给定缩放级别...)。