I want to be able to rotate a perspective camera using the WASD keys. Pressing the W and S keys should rotate the camera along the X axis, and pressing the A and D keys should rotate it along the Y. In an attempt to do this I created a class called RotateCamera that extends the PerspectiveCamera class and includes methods I made to rotate the camera. This way mostly works, but I find if I first move the camera forward using the up arrow key, and then spam the W key so that the camera rotates 360 degrees, when the sphere comes back in view it is very far away, and moving the camera using the arrow keys seems to move it in random directions. I was wondering why this is/how to fix it? A copy of my classes is below.
package ui;
import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
/**
* A PerspectiveCamera that includes methods which allow it to be rotated
*/
public class RotateCamera extends PerspectiveCamera {
Transform currTransform;
/**
* Constructor
* Creates a new camera with default Rotate transform
*/
public RotateCamera() {
currTransform = new Rotate();
}
/**
* Rotates the camera along the x-axis according to the given angle
* @param angle the amount of degrees the camera is rotated
*/
public void rotateInX(int angle) {
Rotate newRotation = new Rotate(angle, Rotate.X_AXIS);
rotateCam(newRotation);
}
/**
* Rotates the camera along the y-axis according to the given angle
* @param angle the amount of degrees the camera is rotated
*/
public void rotateInY(int angle) {
Rotate newRotation = new Rotate(angle, Rotate.Y_AXIS);
rotateCam(newRotation);
}
/**
* Applies both the currTransform and given rotation to the camera
*/
private void rotateCam(Rotate rotation) {
currTransform = currTransform.createConcatenation(rotation);
getTransforms().clear();
getTransforms().addAll(currTransform);
}
}
>
package ui;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Sphere;
import javafx.stage.Stage;
import javafx.scene.Group;
import model.Molecule;
import java.util.Observable;
import java.util.Observer;
/**
* Represents the window in which the molecule drawing editor appears.
* Run the main method to start the program!
*/
public class MarsBonds extends Application {
private static final int CAM_NEAR_CLIP = 0;
private static final int CAM_FAR_CLIP = 1000;
private static final int CAM_ORG_DISTANCE = -10;
private static final int WIDTH = 1000;
private static final int HEIGHT = 800;
private static final Color SCENE_COLOR = Color.BLACK;
private static final int CAM_SPEED = 30;
private static Stage primaryStage;
private static RotateCamera camera;
private static Scene scene;
@Override
public void start(Stage primaryStage) throws Exception {
setScene();
setCamera();
setPrimaryState(primaryStage);
}
/**
* Creates scene with molecule in center of screen and black background
*/
public static void setScene() {
Sphere molecule = new Sphere(30);
molecule.translateXProperty().set(WIDTH/2);
molecule.translateYProperty().set(HEIGHT/2);
Group root = new Group();
root.getChildren().add(molecule);
scene = new Scene(root, WIDTH, HEIGHT);
scene.setFill(SCENE_COLOR);
}
/**
* Initializes camera and adds to scene
*/
private static void setCamera() {
camera = new RotateCamera();
camera.setNearClip(CAM_NEAR_CLIP);
camera.setFarClip(CAM_FAR_CLIP);
camera.translateZProperty().set(CAM_ORG_DISTANCE);
scene.setCamera(camera);
}
/**
* Sets up the primary stage by setting its scene, title, and adding key control
* @param stage the primary stage
*/
private static void setPrimaryState(Stage stage) {
primaryStage = stage;
addEventHandlers();
primaryStage.setTitle("Mar's Bonds");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Adds KeyEvent handler to primary stage
* The KeyEvent handler uses input from the WASD keys to rotate
* the camera and the arrow keys to move the camera
*/
private static void addEventHandlers() {
primaryStage.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
switch(e.getCode()) {
case W:
camera.rotateInX(-1);
break;
case S:
camera.rotateInX(1);
break;
case A:
camera.rotateInY(1);
break;
case D:
camera.rotateInY(-1);
break;
case UP:
camera.setTranslateZ(camera.getTranslateZ() + CAM_SPEED);
break;
case DOWN:
camera.setTranslateZ(camera.getTranslateZ() - CAM_SPEED);
break;
case LEFT:
camera.setTranslateX(camera.getTranslateX() - CAM_SPEED/3);
break;
case RIGHT:
camera.setTranslateX(camera.getTranslateX() + CAM_SPEED/3);
break;
}
});
}
public static void main( String[] args ) {
launch(args);
}
}