【问题标题】:How to move my camera straight to mouse cursor, with any rotation?如何通过任何旋转将我的相机直接移动到鼠标光标?
【发布时间】:2016-09-28 00:38:07
【问题描述】:

我正在使用 LWJGL 创建一个 java 3d 游戏。我正在制作游戏第一人称,玩家可以用鼠标“转动”相机(它实际上会根据相机旋转移动所有其他对象)。

我正在尝试从相机的俯仰、偏航和滚动中获取 3d 矢量。当我按下 W 时,它应该通过向量 X 乘以速度来增加相机 X,它也应该对相机 Y 和 Z 做同样的事情。这应该使相机直接移动到我的鼠标光标所在的位置(鼠标光标始终设置在屏幕中间)。

目前,只要相机的滚动(Z 旋转)为 0,此功能就可以正常工作。当相机滚动不为 0 时,它会将相机/玩家移动到错误的方向。

我想做的是让相机朝着我的光标移动,即使滚动不等于 0。

我的顶点着色器代码如下(这似乎是相关的,因为这里计算了渲染位置):

#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;
}

位置 vec3 只是对象的世界位置。转换矩阵和视图矩阵在以下代码中计算:

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;
}

我很想知道为什么在代码中使用滚动旋转时我不能只使用它,但我对矩阵了解不多。

我正在尝试使用以下代码使向量乘以相机的运动:

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);
}

这是我更新旋转和位置的相机代码,每帧都会调用:

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;
}

有人知道为什么我不能毫无问题地更换相机胶卷,或者我怎样才能做到这一点?

【问题讨论】:

  • 你能分享一下你做旋转和移动的代码吗?

标签: java


【解决方案1】:

在对这种情况进行了大量逻辑思考之后,我自己找到了一种方法。我在计算后编辑了 X 轴和 Y 轴的矢量,然后使用 Z 轴对其进行了编辑。这可能是一种奇怪的方式,但至少有效。

工作方法是这个方法:

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);
}

回答我自己的问题可能看起来有点傻,但我没想到当我发布这个问题时我会设法自己解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    相关资源
    最近更新 更多