2

I am creating a java 3d game using LWJGL. I am making the game first person, the player can 'turn' the camera with the mouse (it actually moves all other objects based on the camera rotation).

I am trying to get a 3d vector from the pitch, yaw and roll of the camera. When I press W, it should increase the camera X by the vector X multiplied with the speed, it should do the same with the camera Y and Z as well. This should make the camera move straight to the place my mouse cursor is looking at (the mouse cursor is always set to the middle of the screen).

At the moment, this works fine as long as the roll of the camera (the Z rotation) is 0. When the camera roll is not 0, it moves the camera/player to the wrong direction.

What I had like to do is make the camera move towards my cursor, even if the roll is not equal to 0.

My vertex shader code is the following (this seems relevant because the render position is calculated here):

#version 400 core

in vec3 position;
in vec2 textureCoords;
in vec3 normal;

out vec2 passTextureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector;

uniform mat4 projectionMatrix;
uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

void main(void){
    vec4 worldPosition = transformationMatrix * vec4(position,1.0);
    gl_Position = projectionMatrix * viewMatrix * worldPosition;
    passTextureCoords = textureCoords;
    surfaceNormal = (transformationMatrix * vec4(normal,0.0)).xyz;
    toLightVector = lightPosition - worldPosition.xyz;
}

The position vec3 is just the world position of the object. The transformationMatrix and view matrix are calculated in the following code:

public static final Matrix4f createTransformationMatrix(Vector3f position,     float rx, float ry, float rz, float size){
    Matrix4f matrix = new Matrix4f();
    matrix.setIdentity();
    Matrix4f.translate(position, matrix, matrix);
    Matrix4f.rotate((float) toRadians(rz), new Vector3f(0, 0, 1), matrix, matrix);
    Matrix4f.rotate((float) toRadians(ry), new Vector3f(0, 1, 0), matrix, matrix);
    Matrix4f.rotate((float) toRadians(rx), new Vector3f(1, 0, 0), matrix, matrix);
    Matrix4f.scale(new Vector3f(size, size, size), matrix, matrix);
    return matrix;
}

public static final Matrix4f createViewMatrix(Camera camera){
    Matrix4f view = new Matrix4f();
    view.setIdentity();
    Matrix4f.rotate(camera.getRadPitch(), new Vector3f(1, 0, 0), view, view);
    Matrix4f.rotate(camera.getRadYaw(), new Vector3f(0, 1, 0), view, view);
    Matrix4f.rotate(camera.getRadRoll(), new Vector3f(0, 0, 1), view, view);
    Vector3f c = camera.getPosition();
    Vector3f invert = new Vector3f(-c.x, -c.y, -c.z);
    Matrix4f.translate(invert, view, view);
    return view;
}

I am seriously wondering why I can't just use the roll rotation while it is used in the code, but I don't know very much about matrices.

I am trying to get the vector to multiply the movement of the camera with the following code:

public static final Vector3f getRotationVector(float pitch, float yaw, float roll){
    Matrix4f mat = createTransformationMatrix(Game.getCamera().getPosition(), pitch, yaw, roll, 1);
    return new Vector3f(mat.m20, mat.m21, -mat.m22);
}

Here is the camera code where I update my rotation and position, this is called every frame:

public void update(){
    super.update();
    int midX = Display.getWidth() / 2;
    int midY = Display.getHeight() / 2;
    int mx = Mouse.getDX();
    int my = Mouse.getDY();
    if(rotationX > 360)
        rotationX -= 360;
    if(rotationX < 0)
        rotationX += 360;
    if(rotationY > 360)
        rotationY -= 360;
    if(rotationY < 0)
        rotationY += 360;
    if(rotationZ > 360)
        rotationZ -= 360;
    if(rotationZ < 0)
        rotationZ += 360;
    if(mouseMoved){
        mouseMoved = false;
        mx = 0;
        my = 0;
    }
    float speed = 0.02f;
    float rotateSpeed = 0.25f;
    if(Keyboard.isKeyDown(Keyboard.KEY_A)){
        Vector3f left = Maths.getRotationVector(-rotationX, rotationY - 90, rotationZ);
        move(left.x * speed, left.y * speed, left.z * speed);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_D)){
        Vector3f right = Maths.getRotationVector(rotationX, rotationY + 90, rotationZ);
        move(right.x * speed, right.y * speed, right.z * speed);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_W)){
        Vector3f forward = Maths.getRotationVector(rotationX, rotationY, rotationZ);
        move(forward.x * speed * 3, forward.y * speed * 3, forward.z * speed * 3);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_S)){
        Vector3f forward = Maths.getRotationVector(rotationX, rotationY, rotationZ);
        move(-forward.x * speed * 3, -forward.y * speed * 3, -forward.z * speed * 3);
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_SPACE))
        position.y += speed;
    if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT))
        position.y -= speed;
    if(mx != 0 && Mouse.isInsideWindow() && wasMouse){
        rotationY += rotateSpeed * mx;
        Mouse.setCursorPosition(midX, midY);
        mouseMoved = true;
    }
    if(my != 0 && Mouse.isInsideWindow() && wasMouse){
        rotationX += rotateSpeed * -my;
        Mouse.setCursorPosition(midX, midY);
        mouseMoved = true;
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL))
        rotationZ -= rotateSpeed;
    if(Keyboard.isKeyDown(Keyboard.KEY_RCONTROL))
        rotationZ += rotateSpeed;
    if(Keyboard.isKeyDown(Keyboard.KEY_M))
        System.out.println("rotationX = " + rotationX + " rotationY = " + rotationY + " rotationZ = " + rotationZ);
    if(Keyboard.isKeyDown(Keyboard.KEY_T))
        System.out.println(Maths.getRotationVector(getPitch(), getYaw(), getRoll()));
    if(Keyboard.isKeyDown(Keyboard.KEY_U)){
        motionX = 0;
        motionY = 0;
        motionZ = 0;
    }
    if(Keyboard.isKeyDown(Keyboard.KEY_X)){
        if(cooldown == 0){
            Vector3f forward = Maths.getRotationVector(rotationX, rotationY, rotationZ);
            world.spawnEntity(new Entity(new TexturedModel(Game.getLoader().loadModelToVAO("geometric/pyramid"), new ModelTexture(Game.getLoader().loadTexture("test 2"))), new Vector3f(position.x + forward.x * 2, position.y + forward.y * 2, position.z + forward.z * 2), rotationX, rotationY, rotationZ, 1f).addForce(rotationX, rotationY, rotationZ, 1000));
            cooldown = 120;
        }
    }
    if(!mouseMoved)
        wasMouse = Mouse.isInsideWindow();
    if(cooldown > 0)
        --cooldown;
}

Does anybody know why I can't change the camera roll without problems or how I can make this work?

Knokko
  • 88
  • 1
  • 8

1 Answers1

0

After a lot of logical thinking about the situation, I found a way to do this myself. I edited the vector for the X axis and the Y axis after they were calculated and edited it using the Z axis afterwards. This is probably a strange way, but it works at least.

The working method is this method:

public static final Vector3f getRotationVector(float pitch, float yaw, float roll){
    float r = (float) toRadians(roll);
    Matrix4f mat = createTransformationMatrix(new Vector3f(), pitch, yaw, 0, 1);
    Vector3f vector = new Vector3f(mat.m20, mat.m21, -mat.m22);
    return new Vector3f((float)(vector.x * cos(r) + vector.y * sin(r)), (float)(vector.y * cos(r) - vector.x * sin(r)), vector.z);
}

It might look a little silly to answer my own question, but I didn't expect I would manage to solve it myself when I posted this.

Knokko
  • 88
  • 1
  • 8