Search code examples
javafxcamera

Move camera relative to view in javafx?


I have a camera in my scene, which I am currently moving on the x y and z axis using WASD. However, I would want it to move according to the direction it is facing. For better illustration of what I mean, I am using snippets from the program blender to demonstrate the idea.

Image 1

In Image 1, it is quite easy. Moving forward will simply move on the x (red) axis, moving to the sides will be on the y (green) axis. The problems arise when the camera is rotated, thereby changing it's position relative to the axes, as Image 2 shows from the top view:

Image 2

If I now try to move forward (direction of the red arrow), I need the movement to accommodate for the rotation, and adjust the x and y coordinates so that the camera moves forward from it's perspective.

Is there a way of doing this? I have tried many calculations involving sine and cosine, and quite a few google searches, but it led to no result. Google mostly showed unsolved questions or solutions using OpenGL, and my math equations simply spewed out incorrect results.

I hope I explained the problem clearly, if not I will be happy to provide additional information. Thank you for your time!


Solution

  • I know im like 3 months late but I think I know what you mean.

    In JavaFX you have a group called world (Everything 3d except the camera). If you want to rotate the camera to the left (example around the y axis) you don't touch the camera but the world and rotate that around the y axis.

    I'll be honest I don't 100% understand why it works but it does for me (I'm working on a game so I had to go through it).

    I hope this answers your question :D

    EDIT 1: Sample code

    package FXTesting;
    
    import javafx.application.Application;
    import javafx.scene.Camera;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.KeyEvent;
    import javafx.scene.shape.Box;
    import javafx.scene.transform.Rotate;
    import javafx.scene.transform.Translate;
    import javafx.stage.Stage;
    
    public class Main extends Application {
    
        public static int SIZEFACTOR = 100;
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            Group world = createEnvironment();
    
            Scene scene = new Scene(world);
            primaryStage.setScene(scene);
            primaryStage.setWidth(16 * SIZEFACTOR);
            primaryStage.setHeight(9 * SIZEFACTOR);
    
            Camera camera = new PerspectiveCamera();
            camera.setFarClip(2000);
            camera.setNearClip(1);
    
            scene.setCamera(camera);
    
            Rotate worldRotX = new Rotate(0, Rotate.X_AXIS);
            Rotate worldRotY = new Rotate(0, Rotate.Y_AXIS);
    
            Translate  worldTransX = new Translate();
    
            world.getTransforms().addAll(worldRotY, worldRotX);
    
            primaryStage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
                switch(event.getCode()){
                    case LEFT:
                        worldRotY.setAngle(worldRotY.getAngle() + 10);
                        break;
                    case RIGHT:
                        worldRotY.setAngle(worldRotY.getAngle() - 10);
                        break;
                    case UP:
                        worldRotX.setAngle(worldRotX.getAngle() + 10);
                        break;
                    case DOWN:
                        worldRotX.setAngle(worldRotX.getAngle() - 10);
                    case W: //w/s is for z
                        world.setTranslateZ(world.getTranslateZ() + 10);
                        break;
                    case S:
                        world.setTranslateZ(world.getTranslateZ() - 10);
                        break;
                    case A:// a/d is x axis
                        world.setTranslateX(world.getTranslateX() + 10);
                        break;
                    case D:
                        world.setTranslateX(world.getTranslateX() - 10);
                        break;
                    case SHIFT:// shift/contr is for y axis
                        world.setTranslateY(world.getTranslateY() + 10);
                        break;
                    case CONTROL:
                        world.setTranslateY(world.getTranslateY() - 10);
                        break;
    
                }
            });
    
            primaryStage.show();
        }
    
        private Group createEnvironment(){
            Group group = new Group();
    
            Box ground = new Box();
            ground.setHeight(10);
            ground.setWidth(1000);
            ground.setDepth(1000);
    
            ground.setTranslateX(-500);
            ground.setTranslateZ(-500);
    
    
            Box box = new Box(100,100,100);
            box.setTranslateY(10);
    
            group.getChildren().addAll(ground, box);
    
            return group;
        }
    
        public static void main(String... args){
            launch(args);
        }
    }