Zed-Log
Zed-Log

Reputation: 13

JavaFX animation/View 3d with panes

I've been working in JavaFX for the first time to try to make an app which I can use to demonstrate a simple animation with button controls. To do this I've used a BoarderPane for the primary stage, with both the left,right, and bottom using Gridpanes.

However, for the center I need to be able to draw a sphere with a line within it which I can rotate for different views while simultaneously being able to animated, or at the very least snap-move, the line within.

I've tried using a Pane for the center which doesn't work. I've tried making it it's own scene and sub scene which doesn't work. And I can't use a canvas as that is only for 2D animation.

Is there a way I can animate the line or rotate the camera while maintaining the BoarderPane layout I've created?

I've tried looking at the following before to understand what I could do but most just seem incompatible with the BoarderPane:

JavaFX Rotating Camera Around a Pivot

JavaFX Canvas rotate image with fixed center (and without bouncing)

Upvotes: 1

Views: 1177

Answers (1)

José Pereda
José Pereda

Reputation: 45456

Whenever you want to mix 2D and 3D (and camera) you have to use a SubScene container for the 3D content:

SubScene provides separation of different parts of a scene, each of which can be rendered with a different camera, depth buffer, or scene anti-aliasing. A SubScene is embedded into the main scene or another sub-scene.

If you have a BorderPane container, you can perfectly add the subScene to its center.

For a similar use case, you can check the Qubit3D class from here, which is mainly a group that holds a sub scene with an Sphere and a cylinder (both from the FXyz 3D library).

You can add this group easily to your 2D scene:

private final Rotate rotate = new Rotate(0, 0, 0, 0, javafx.geometry.Point3D.ZERO.add(1, 1, 1));

@Override
public void start(Stage primaryStage) throws Exception {

    final Timeline timeline = new Timeline(
        new KeyFrame(Duration.seconds(10), 
            new KeyValue(rotate.angleProperty(), 360)));

    final Qubit3D qubit = new Qubit3D();

    final BorderPane root = new BorderPane(qubit);

    final Button buttonAnimate = new Button("Animate");
    buttonAnimate.setOnAction(e -> {
        rotate.setAngle(0);
        timeline.playFromStart();
    });

    root.setLeft(new StackPane(buttonAnimate));
    final Button buttonStop = new Button("Stop");
    buttonStop.setOnAction(e -> timeline.stop());
    root.setRight(new StackPane(buttonStop));

    Scene scene = new Scene(root, 600, 400, true, SceneAntialiasing.BALANCED);
    scene.setFill(Color.BISQUE);

    primaryStage.setScene(scene);
    primaryStage.setTitle("Qubit3D Sample");
    primaryStage.show();

    qubit.rotateRod(rotate);

}

The only modification I've added to Qubit3D is:

public void rotateRod(Rotate rotate) {
    rodSphere.getTransforms().setAll(rotate);
}

If you run it:

Qubit3D

Note that you can interact with the sphere (via mouse dragged events), while you can also start/stop a full rotation of sphere and rod.

Upvotes: 3

Related Questions