今天开始学习javaFX 3D图形中的Camera,Camera作为一个节点,可以被添加到场景中,它能允许你在一个3D场景中移动它,不同于二维布局的是,camera总能保持在一个位置上。
在javaFX场景坐标空间中,camera的默认投影平面是在Z=0上。camera的坐标系统如下:
在显示屏上,
X轴指向右边
Y轴指向下面
Z轴的指向是从显示屏到你。
其实这也是java中的坐标系统。
Perspective Camera类
javaFX提供了一个PerspectiveCamera类,用来渲染3D场景,该类提供了一个视锥,该视锥可以通过fieldOfView属性
来改变。
下图显示了两种构造方法来构造PerspectiveCamera
第二个构造函数,是javaFX8中新加进去的,它允许你控制相机的位置,通过fixedEyeAtCameraZero属性,它将相机呈现在一个3D场景中。因此构建一个3D场景只需将它设置为true即可,此时它的视角位置会固定在坐标空间的(0,0,0)像素处,既电脑显示屏的左上角且不管你如何改变窗体的大小。当fixedEyeAtCameraZero设置为false的时候(默认值),相机有它的起源坐标系统在左上角的面板上。此模式用于2 d UI控件呈现,但对于大多数3 d图形应用程序并不有用。当窗口改变大小时,相机会移动,例如,保持原点在面板的左上角,这正是你想要的2 d UI布局,但在一个3 d的布局中不行。因此,重要的是要记住当你在做的3 d图形改变或移动相机时,设置fixedEyeAtCameraZero属性为true。
创建一个Camera并添加到场景中,可以使用如下代码:
使用如下代码添加Camera到scene graph中:
旋转Camera并移动CameraGroup
Field of View(视野)
设置Camera的视野
注意,视野越大,则角度变形和大小差异则增加越多
Fisheye
:鱼眼镜头有一个180度的视野。
Normal
:正常的镜头有一个40到62度的视野。
Telephoto
:长焦镜头有一个1度到30度的视野(或许更少)。
Clipping Planes(裁剪平面)
你可以设置相机裁剪平面附近的坐标系统:
设置相机在当前的坐标系统中的裁剪平面:
Y-down 与 Y-up
大多数的2D平面坐标系统的Y轴是沿着你的屏幕向下的,许多3D图形坐标系统的Y轴却是沿着屏幕向上的,还有一些事Z轴向上的,在javaFX中,Camera的坐标系统是Y轴指向下的,X轴指向右边,Z轴指向你。如果你想要改变他们,你可以创建一个Xform节点,给它起个名字root3D,你可以设置rx.setAngle为180度,这样就可以把它颠倒了。然后把你的3D元素添加到root3D中。例子如下:
你也可以创建一个叫做cameraXform的Xform,把它放到你的root下,上下颠倒之后,把你的camera放到cameraXform中。代码如下:
一种比较好的方式添加一个旋转180度的相机,和上面的方式相比有些许细微的差距。下面的例子是让相机旋转180度然后添加一些子元素到cameraXform中(这里使用Rotate)。
细微的差别是,cameraxform保留非常原始的值它的默认位置,一切归零,包括平移和旋转。
Sample Code Using PerspectiveCamera(样品代码)
<span style="font-size:14px;">package simple3dbox;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.DrawMode;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class Simple3DBoxApp extends Application {
public Parent createContent() throws Exception {
// Box
Box testBox = new Box(5, 5, 5);
testBox.setMaterial(new PhongMaterial(Color.RED));
testBox.setDrawMode(DrawMode.LINE);
// Create and position camera
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.getTransforms().addAll (
new Rotate(-20, Rotate.Y_AXIS),
new Rotate(-20, Rotate.X_AXIS),
new Translate(0, 0, -15));
// Build the Scene Graph
Group root = new Group();
root.getChildren().add(camera);
root.getChildren().add(testBox);
// Use a SubScene
SubScene subScene = new SubScene(root, 300,300);
subScene.setFill(Color.ALICEBLUE);
subScene.setCamera(camera);
Group group = new Group();
group.getChildren().add(subScene);
return group;
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setResizable(false);
Scene scene = new Scene(createContent());
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Java main for when running without JavaFX launcher
*/
public static void main(String[] args) {
launch(args);
}
}</span>