qed
qed

Reputation: 23104

Position of PerspectiveCamera in JavaFX 8

Here is the code:

import javafx.animation.Animation;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.shape.CullFace;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class CameraTest extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        Box box = new Box(100, 100, 100);
        box.setCullFace(CullFace.NONE);
        box.setTranslateX(0);
        box.setTranslateY(0);
        box.setTranslateZ(0);

        PerspectiveCamera camera = new PerspectiveCamera(false);
        camera.setTranslateX(0);
        camera.setTranslateY(0);
        camera.setTranslateZ(0);

        // Add a Rotation animation to the camera
        RotateTransition rt = new RotateTransition(Duration.seconds(2), box);
        rt.setCycleCount(Animation.INDEFINITE);
        rt.setFromAngle(0);
        rt.setToAngle(360);
        rt.setAutoReverse(true);
        rt.setAxis(Rotate.Y_AXIS);
        rt.play();

//        PointLight redLight = new PointLight();
//        redLight.setColor(Color.RED);
//        redLight.setTranslateX(250);
//        redLight.setTranslateY(-100);
//        redLight.setTranslateZ(250);

        PointLight greenLight = new PointLight();
        greenLight.setColor(Color.GREEN);
        greenLight.setTranslateX(250);
        greenLight.setTranslateY(300);
        greenLight.setTranslateZ(300);

        Group root = new Group(box, greenLight);
        root.setRotationAxis(Rotate.X_AXIS);
        root.setRotate(30);

        Scene scene = new Scene(root, 500, 300, true);
        scene.setCamera(camera);
        stage.setScene(scene);
        stage.setTitle("Using camaras");
        stage.show();
    }
}
  1. Why do I feel there is a up-down movement along the y-axis?
  2. The camera is set at the same position as the cube, how come the cube ends up appearing at the top-right corner?

Upvotes: 3

Views: 3012

Answers (1)

José Pereda
José Pereda

Reputation: 45456

For the first question: yes, there's an up-down movement as you describe it. The explanation is simple:

You have added your rotating box to a Group, and according to Javadoc:

A Group node contains an ObservableList of children that are rendered in order whenever this node is rendered. A Group will take on the collective bounds of its children and is not directly resizable. Any transform, effect, or state applied to a Group will be applied to all children of that group. Such transforms and effects will NOT be included in this Group's layout bounds, however if transforms and effects are set directly on children of this Group, those will be included in this Group's layout bounds.

Last statement says that the rotation applied to the box is affecting the group layout bounds.

Since the scene root is the group, its layout changes are reflected on the scene.

If you track the Y center of the group:

root.boundsInLocalProperty().addListener((obs, oldBounds, newBounds)->{
        double yCenterLocal = newBounds.getWidth()/2;
        double yCenterScene = root.localToScene(new Point2D(0,yCenterLocal)).getY();
        System.out.println(yCenterScene);
    });

You will see the change in position:

212.89169311523438
209.2910614013672
209.34730529785156
209.4747772216797
209.52439880371094
209.576171875

This is a chart after two complete rotations (720º):

ycenter

To avoid this problem you could use another container, like a StackPane:

StackPane root = new StackPane(box, greenLight);

Y center will be, in your case, at 237.03555297851562 all the time.

And you will have also solved your second problem, since the box will appear centered in the scene.

stackpane

Note I've moved the light to negative Z coordinates (out of the screen).

greenLight.setTranslateZ(-300);

Also, you should use scene antialiasing:

Scene scene = new Scene(root, 500, 300, true, SceneAntialiasing.BALANCED);

Upvotes: 3

Related Questions