Getting Started with JavaFX 3D Graphics
Beta Draft: 2013-09-17
This chapter describes the Camera API that is included with the JavaFX 3D Graphics feature.
The camera is now a node and can be added to the JavaFX scene graph. It allows you to move the camera around in a 3D UI layout. This is different from the 2D layout where you did not need to move the camera around.
In JavaFX, the camera coordinate system is as follows:
• X-axis pointing to the right
• Y-axis pointing down
• Z-axis pointing away from the viewer or into the screen.
To create a camera and add it to the scene, use the following lines of code:
Camera camera = new PerspectiveCamera(true); scene.setCamera(camera);
Use the following code to add a camera to the scene graph.
Group cameraGroup = new Group(); cameraGroup.getChildren().add(camera); root.getChildren().add(cameraGroup);
To rotate the camera and move the cameraGroup, use
JavaFX provides a perspective camera for rendering a 3D scene. This camera defines a viewing volume for a perspective projection. The viewing volume can be changed by changing the value of the
Example 3-1 shows the two constructors for creating a Perspective Camera:
Example 3-1 Constructors for PerspectiveCamera
PerspectiveCamera() PerspectiveCamera(boolean fixedEyeAtCameraZero)
The latter constructor is a new constructor in JavaFX 8 and allows you to control the camera position with the specified
fixedEyeAtCameraZero flag so that it renders what the camera would see in a 3D environment.
The following constructor should be used for 3D graphics programming:
When the option
fixedEyeAtCameraZero is set to true, a PerspectiveCamera is constructed with its eye position fixed at (0, 0, 0), in its coordinate space, regardless of the change in the dimension of the projection area or window resize.
fixedEyeAtCameraZero is set to the default value of
false, the coordinate system defined by the camera has its origin in the upper left corner of the panel. This mode is used for 2D UI controls rendered with a perspective camera, but is not useful for most 3D graphics applications. The camera is moved when the window is resized, for example, to maintain the origin in the upper left corner of the panel. That is exactly what you want for a 2D UI layout, but not in a 3D layout. So, it is important to remember to set the fixedEyePosition to true when you are doing 3D graphics.
Field of View
The camera's field of view can be set as follows:
The larger the field of view, the more perspective distortion and size differences increase.
Fisheyelenses have a field of view of up to 180 degrees and beyond.
Normallenses have a field of view between 40 and 62 degrees.
Telephotolenses have a field of view of 1 (or less) degrees to 30 degrees.
You can set the near clipping plane of the Camera in the local coordinate system as follows:
To set the far clipping plane of the Camera in the local coordinate system, use the following:
Setting the near or far clipping planes determines the viewing volume. If the near clipping plane is too great, it will basically start clipping the front of the scene. If it is too small, then it will start clipping the back of the scene.
Don't set the near clipping value to a smaller value than is needed or the far clipping value to a larger value than is needed because strange visual artifacts may start appearing.
The clipping planes need to be set so that enough of the scene can be seen. But the viewing range should not be set so large that a numerical error is encountered. If the near clipping plane is too large a value, the scene starts getting clipped. But if the near clipping plane too small, a different kind of visual artifact will appear due to a value being too close to zero. If the far clipping plane is too large a value, a numerical error is also encountered, especially if the near clipping plane is too small a value.
Y-down versus Y-up
Most 2D graphics coordinate systems (including UI) have Y increasing as you go down the screen. This is true of PhotoShop, JavaFX, and Illustrator. Basically most 2D packages work this way. Many 3D graphics coordinate systems typically have Y increasing as you move up the screen. Some 3D graphics coordinate systems have Z increasing as you move up, but most have Y increasing as you move up the screen.
Y down versus Y up are both correct in their own context. In JavaFX, the camera's coordinate system is Y-down, which means X axis points to the right, Y axis is pointing down, Z axis is pointing away from the viewer or into the screen.
If you want to think of a 3D scene as Y-up, you could create an
Xform node, called
root3D, under root, as shown in Example 3-2. You set its
rx.setAngle property to 180 degrees, basically turning it upside down. Then, add your 3D elements to your
root3D node and put your camera under r
Example 3-2 Create Xform node, root3D
root3D = new Xform(); root3D.rx.setAngle(180.0); root.getChildren().add(root3D); root3D.getChildren().add(...); // add all your 3D nodes here
You can also create an Xform node called
cameraXform and put it under the root, as shown in Example 3-3. You turn it upside down, and put your camera under the
Example 3-3 Create a cameraXform Node
Camera camera = new PerspectiveCamera(true); Xform cameraXform = new Xform(); root.getChildren().add(cameraXform); cameraXform.getChildren().add(camera); cameraXform.rz.setAngle(180.0);
An even better way, with subtle difference on the camera node, is to add a 180 degree rotation to the camera. The rotation used is not the one provided for you because you want to avoid the auto pivoting. In Example 3-4, the camera is turned 180 degrees and it is then added to the camera as a child of cameraXform. The subtle difference is that the cameraXform retains very pristine values and in its default position, everything is zeroed out, including the translations and rotations.