Getting Started with JavaFX 3D Graphics

Previous

Beta Draft: 2013-09-17

8 Building a 3D Sample Application

This chapter provides the steps to build a simple application, MoleculeSampleApp, that uses some of the JavaFX 3D graphics features that were discussed earlier in this document.

The steps in this tutorial chapter use the NetBeans 4 IDE to help you develop the MoleculseSampleApp application.

The following files are included for this tutorial:

This tutorial contains the following sections.

Create the Project

Use the NetBeans IDE to create the JavaFX project, MoleculeSampleApp.

  1. From the File menu, choose New Project.

  2. In the New Project wizard, choose the JavaFX application category and JavaFX Application project. Click Next.

  3. Type MoleculeSampleApp for the Project Name. Enter the path for the Project Location text field or click Browse to navigate to the folder you want to use for this project.

  4. Click Finish.

    When you create a JavaFX project, NetBeans IDE provides a Hello World source code template as a starting point. You will replace that template source code in the next sections.

Create the Scene

Create the scene that will hold your molecule UI layout.

  1. First, download the Xform.java file and save it to the moleculesampleapp source folder of the moleculesampleapp project.

    This file contains the source code for the Xform sub-class that is derived from the Group class. Using the Xform node prevents the automatic recalculation of the position of a group node's pivot when the children of the group node is changed in a 3D UI layout. The Xform node allows you to add your own types of transforms and rotation. The file contains a translation component, three rotation components, and a scale component. Having the three rotation components is helpful when changing rotation values frequently, such as in changing the angle of the camera in the scene.

  2. If not already opened in the IDE editor, open the MoleculeSampleApp.java file that was created with the project creation. Replace the import statements at the top of the file with the import statements shown in Example 8-1.

    Example 8-1 Replacement Import Statements

    import javafx.application.Application;
    import static javafx.application.Application.launch;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    import moleculesampleapp.Xform;
    
  3. Replace the rest of the body of the code in MoleculeSampleApp.java with the lines of code shown in Example 8-2. The code creates a new scene graph with an Xform as its node.

    Example 8-2 Replacement Body of Code

    /**
     * MoleculeSampleApp
     */
    public class MoleculeSampleApp extends Application {
     
        final Group root = new Group();
        final Xform world = new Xform();
     
        private void buildScene() {
            System.out.println("buildScene");
            root.getChildren().add(world);
        }
     
        @Override
        public void start(Stage primaryStage) {
            System.out.println("start");
            buildScene();
     
            Scene scene = new Scene(root, 1024, 768, true);
            scene.setFill(Color.GREY);
     
            primaryStage.setTitle("Molecule Sample Application");
            primaryStage.setScene(scene);
            primaryStage.show();
     
        }
     
        /**
         * The main() method is ignored in correctly deployed JavaFX application.
         * main() serves only as fallback in case the application can not be
         * launched through deployment artifacts, e.g., in IDEs with limited FX
         * support. NetBeans ignores main().
         *
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            System.setProperty("prism.dirtyopts", "false");
            launch(args);
        }
    }
    
  4. Press Ctrl+S to save the file.

Set Up the Camera

Set up the camera in a hierarchy of Group class with Xform instances. Perform the translation and rotation on the camera to change its default location.

  1. At the top of the MoleculeSampleApp.java file, add the following import statement for the Camera class.

    Example 8-3 Import the Perspective

    import javafx.scene.PerspectiveCamera;
    
  2. Add the following lines of code, shown in bold below, so that it appears after the declaration statement for the world object, as shown in Example 8-4.

    These lines of code create an instance of a perspectiveCamera and three instances of the public class Xform, which extends the Group class. The Xform class is defined in the Xform.java file you added to your NetBeans project in the previous section of this document.

    Example 8-4 Add Variables for the Camera

        final Group root = new Group();
        final Xform world = new Xform();
        final PerspectiveCamera camera = new PerspectiveCamera(true);
        final Xform cameraXform = new Xform();
        final Xform cameraXform2 = new Xform();
        final Xform cameraXform3 = new Xform();
        final double cameraDistance = 450;
    
  3. Copy the lines of code for the buildCamera() method, shown in Example 8-5. Add them right after the lines for the buildScene() method.

    The buildCamera() method sets the camera to have the view upside down instead of the default JavaFX 2D Y-down. So the scene is viewed as a Y-up (Y-axis pointing up) scene.

    Example 8-5 Add the buildCamera() Method

       private void buildCamera() {
            root.getChildren().add(cameraXform);
            cameraXform.getChildren().add(cameraXform2);
            cameraXform2.getChildren().add(cameraXform3);
            cameraXform3.getChildren().add(camera);
            cameraXform3.setRotateZ(180.0);
     
            camera.setNearClip(0.1);
            camera.setFarClip(10000.0);
            camera.setTranslateZ(-cameraDistance);
            cameraXform.ry.setAngle(320.0);
            cameraXform.rx.setAngle(40);
        }
    
  4. In the start() method, add the call to the buildCamera() so that it appears as shown in bold in Example 8-6

    Example 8-6 Add Method Call to buildCamera()

            buildScene();
            buildCamera();
            
    
  5. Set the camera in the scene by copying the line of code shown in bold in Example 8-7 and adding it to the end of the start() method.

    Example 8-7 Set the Camera in the Scene

            primaryStage.show();
            scene.setCamera(camera);
    
  6. Save the file with Ctrl+S.

Build the Axes

Add the 3D axes that you will use to build this molecule. The Box class is used to create the axes and the PhongMaterial is used to set the specular and diffused colors. By default in JavaFX, the Y-axis is down.

Per the usual convention, the X-axis is shown in the color red, Y-axis is shown in green, and Z-axis in blue.

  1. Copy the following declaration shown in bold in Example 8-8 and add it to just after the line where root is declared.

    Example 8-8 Create the axisGroup

    final Group root = new Group();
    final Group axisGroup = new Group();
    
  2. Add the buildAxes() method shown in Example 8-9 to after the buildCamera() method.

    Example 8-9 Add buildAxes() Method

        private void buildAxes() {
            System.out.println("buildAxes()");
            final PhongMaterial redMaterial = new PhongMaterial();
            redMaterial.setDiffuseColor(Color.DARKRED);
            redMaterial.setSpecularColor(Color.RED);
     
            final PhongMaterial greenMaterial = new PhongMaterial();
            greenMaterial.setDiffuseColor(Color.DARKGREEN);
            greenMaterial.setSpecularColor(Color.GREEN);
     
            final PhongMaterial blueMaterial = new PhongMaterial();
            blueMaterial.setDiffuseColor(Color.DARKBLUE);
            blueMaterial.setSpecularColor(Color.BLUE);
     
            final Box xAxis = new Box(240.0, 1, 1);
            final Box yAxis = new Box(1, 240.0, 1);
            final Box zAxis = new Box(1, 1, 240.0);
            
            xAxis.setMaterial(redMaterial);
            yAxis.setMaterial(greenMaterial);
            zAxis.setMaterial(blueMaterial);
     
            axisGroup.getChildren().addAll(xAxis, yAxis, zAxis);
            world.getChildren().addAll(axisGroup);
        }
    
  3. Fix the imports by adding the following import statements shown in Example 8-10.

    Example 8-10 Add Two Import Statements

    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    
  4. Add the call to buildAxes() method, as shown in bold in Example 8-11.

    Example 8-11 Add Call to buildAxes() Method

            buildCamera();
            buildAxes();
    
  5. Compile and run the project by right-clicking the MoleculeSampleApp node in the project window and choose Run. A window appears with the 3D axes, as shown in Figure 8-1.

Build the Molecule

In this section, you build the molecule UI. This is where you use the 3D features such as PhongMaterial, Sphere, and Cylinder. The Xform class is used.

  1. To declare the moleculeGroup Xform, copy the line of code shown in bold in Example 8-12. Paste it after the cameraDistance variable.

    Example 8-12 Declare the moleculeGroup Xform

     final double cameraDistance = 450;
     final Xform moleculeGroup = new Xform();
    
  2. Add the following import statements for the classes used in the buildMolecule() method:

    Example 8-13 Add Import Statements for build Molecule()

        import javafx.scene.shape.Cylinder;
        import javafx.scene.shape.Sphere;
        import javafx.scene.transform.Rotate;
    
  3. Click the buildMolecule() link on the right-hand column of this tutorial to open the buildMolecule.html file. Copy the body of code for buildMolecule() and paste it after the buildAxes() method in the MoleculeSampleApp.java file.

  4. In the start() method, add the call to the buildMolecule() method so that it appears as shown in bold in Example 8-14.

    Example 8-14 Add the Call to the buildMolecule() Method

    buildCamera();
    buildAxes();
    buildMolecule();
    
  5. Now run the project and you should see something similar to Figure 8-2.

    Figure 8-2 The Water Molecule 3DModel

    Description of Figure 8-2 follows
    Description of "Figure 8-2 The Water Molecule 3DModel"

Add Camera Viewing Controls

The handleMouse() and handleKeyboard() methods allow you to see the different camera views. The source has been provided for you to demonstrate the use of the mouse and the keyboard to the camera's view in the scene.

  1. Add the import statement for the javafx.animation.Timeline class to the top of the file.

  2. Add the declaration for variables that are used in the handleMouse() and handleKeyboard() source code you are about to add. Copy the code shown in Example 8-15 and paste after the line for the moleculeGroup declaration.

    Example 8-15 Add Variables Used

        private Timeline timeline;
        boolean timelinePlaying = false;
        double ONE_FRAME = 1.0/24.0;
        double DELTA_MULTIPLIER = 200.0;
        double CONTROL_MULTIPLIER = 0.1;
        double SHIFT_MULTIPLIER = 0.1;
        double ALT_MULTIPLIER = 0.5;
            
        double mousePosX;
        double mousePosY;
        double mouseOldX;
        double mouseOldY;
        double mouseDeltaX;
        double mouseDeltaY;
    
  3. Click the handleCameraViews link on the right-hand side bar and open the file.

  4. Copy the import statements used in the handleMouse() and handleKeyboard() methods, as shown in Example 8-16. Paste them at the top of the MoleculeSampleApp.java file.

    Example 8-16 Add the Import Statements

    import javafx.event.EventHandler;
    import static javafx.scene.input.KeyCode.*;
    import javafx.scene.input.KeyEvent;
    import javafx.scene.input.MouseEvent;
    import javafx.util.Duration;
    import javafx.scene.Node;
    
  5. Copy the lines of code for the handleMouse() and the handleKeyboard() methods in the handleCameraViews.html file. Add them after the buildMolecule() method in the MoleculeSampleApp.java file.

  6. In the start() method, add the calls to the handleKeyboard() and handleMouse() methods that you just added. Copy the lines of code shown in bold in Example 8-17 and paste them after the scene.setFill(Color.GREY) line.

    Example 8-17 Add Method Calls

            Scene scene = new Scene(root, 1024, 768, true);
            scene.setFill(Color.GREY);
            handleKeyboard(scene, world);
            handleMouse(scene, world);
    
  7. Save the file.

  8. Compile and run the project. Use the following mouse or keyboard strokes to get the different views.

    • Hold the left mouse button and drag the mouse right or left and up or down to rotate the camera view of the molecule around the axes.

    • Hold the right mouse button and drag the mouse to the left to move camera view away from the water molecule model. Drag the mouse to the right to move the camera view closer to the molecule model.

    • Ctrl+s is used for showing and hiding the molecule.

    • Ctrl+x is used for showing and hiding the axes.

Previous