Java 第一人称相机在移动眼睛时的怪异行为

Java 第一人称相机在移动眼睛时的怪异行为,java,opengl,matrix,camera,lwjgl,Java,Opengl,Matrix,Camera,Lwjgl,我试图用Java/LWJGL制作一个游戏/演示,但第一人称相机出现问题: 我使用WASD移动眼睛向量,不管发生了什么奇怪的事情: 当我把眼睛移开或移向我时,右边的反应。视图的左侧部分被“我的视图”阻止 当我把眼睛移到我的右边或左边时,上面的眼睛会相应地移动。视图的底部部分被“我的视图”阻止 我已经成功地实现了鼠标移动(环顾四周),相关代码如下: (注:Matrix4f类按列主顺序工作) 我真的不知道为什么照相机的行为如此怪异,甚至不知道它是什么意思? 图片的某些部分怎么会突然变得不可见

我试图用Java/LWJGL制作一个游戏/演示,但第一人称相机出现问题:

我使用WASD移动
眼睛
向量,不管发生了什么奇怪的事情:

  • 当我把眼睛移开或移向我时,右边的反应。视图的左侧部分被“我的视图”阻止
  • 当我把眼睛移到我的右边或左边时,上面的眼睛会相应地移动。视图的底部部分被“我的视图”阻止
我已经成功地实现了鼠标移动(环顾四周),相关代码如下:

(注:Matrix4f类按列主顺序工作)



我真的不知道为什么照相机的行为如此怪异,甚至不知道它是什么意思?
图片的某些部分怎么会突然变得不可见


更新:这可能与
viewFPS()
方法有关,因为那里的平移看起来有点奇怪,有人能确认吗?

注意到在
viewFPS
中,旋转和平移组合在一个矩阵乘法中

我不熟悉你构建矩阵的方式,但我可以告诉你什么适合我

  • 创建3个矩阵,一个用于X旋转、Y旋转和Z旋转值
  • 按你想要的顺序乘以这些矩阵。(我使用Z,Y,然后X)
  • 将结果与平移矩阵相乘。(即眼睛的位置)
  • 生成的矩阵就是视图矩阵
这可能比您正在使用的方法效率低,但是让它工作然后从那里优化是很好的吗?拆分旋转轴还可以一次调试一个轴

我使用的旋转矩阵:


其中,(phi)和(psi)是围绕X、Y和Z轴的旋转。(

谢谢,当我使用原始旋转矩阵(无平移),然后平移它时,它现在工作了。我从那里得到那个特定矩阵的教程可能是以另一种方式进行矩阵乘法(与我相比)。这是一篇重复的帖子,使用了我帖子中的答案。@FelixCastor它可能使用了你的答案,但是你的答案当时我无法理解,有了这个和你的答案的帮助,我现在终于可以这样做了。
Matrix4f viewMatrix = new Matrix4f();

private void checkKeys() {
    if (isKeyCurrentlyDown(Keyboard.KEY_W)) {
        eye.updateTranslate(1.0f, 0.0f, 0.0f);
        updateView();
    }
    else if (isKeyCurrentlyDown(Keyboard.KEY_S)) {
        eye.updateTranslate(-1.0f, 0.0f, 0.0f);
        updateView();
    }
    else if (isKeyCurrentlyDown(Keyboard.KEY_A)) {
        eye.updateTranslate(0.0f, -1.0f, 0.0f);
        updateView();
    }
    else if (isKeyCurrentlyDown(Keyboard.KEY_D)) {
        eye.updateTranslate(0.0f, 1.0f, 0.0f);
        updateView();
    }
}

private void updateView() {
    System.out.println("eye = " + eye);
    viewMatrix.identity().viewFPS(eye, roll, yaw, pitch);
    System.out.println("viewMatrix = " + viewMatrix);
    Uniforms.setUniformMatrix4(UNIFORM_VIEW_MATRIX, false, viewMatrix);
}

@Override
protected void render(final double msDelta) {
    super.render(msDelta);

    glClearColor(0.0f, 0.25f, 0.0f, 1.0f);
    glClearDepthf(1f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    program.use();

    for (int i = 0; i < 24; i++) {
        float fVar = i + currentTime / 1000f * 0.3f;
        modelviewMatrix.identity()
                .translate(0.0f, 0.0f, -8.0f)
                .rotate(currentTime / 1000f * 45.0f, 0.0f, 1.0f, 0.0f)
                .rotate(currentTime / 1000f * 21.0f, 1.0f, 0.0f, 0.0f)
                .translate(
                    (float)Math.sin(2.1f * fVar) * 2.0f,
                    (float)Math.cos(1.7f * fVar) * 2.0f,
                    (float)Math.sin(1.3f * fVar) * (float)Math.cos(1.5f * fVar) * 2.0f
                );
        Uniforms.setUniformMatrix4(UNIFORM_MODEL_MATRIX, false, modelviewMatrix.writeToFloatBuffer(modelViewMatrixBuffer));
        program.drawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
    }
}
#version 440 core

layout(location = 0) in vec4 position;

out VS_OUT {
    vec4 color;
} vs_out;

layout(location = 0) uniform mat4 model_matrix;
layout(location = 1) uniform mat4 view_matrix;
layout(location = 2) uniform mat4 proj_matrix;

void main() {
    gl_Position = proj_matrix * view_matrix * model_matrix * position;
    vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
}
public enum UniformLocation {
    UNIFORM_MODEL_MATRIX(0),
    UNIFORM_VIEW_MATRIX(1),
    UNIFORM_PROJECTION_MATRIX(2)
    ;

    private final int location;

    private UniformLocation(final int location) {
        this.location = location;
    }

    public int getLocation() {
        return this.location;
    }
}
//Column-major order

public Matrix4f viewFPS(final Vector3f eye, final float rollAngle, final float yawAngle, final float pitchAngle) {
    //roll = rolling your head, Q&E
    //yaw = looking left/right, mouseY
    //pitch = looking up/down, mouseX
    float sinRoll = (float)Math.sin(Math.toRadians(rollAngle));
    float cosRoll = (float)Math.cos(Math.toRadians(rollAngle));
    float sinYaw = (float)Math.sin(Math.toRadians(yawAngle));
    float cosYaw = (float)Math.cos(Math.toRadians(yawAngle));
    float sinPitch = (float)Math.sin(Math.toRadians(pitchAngle));
    float cosPitch = (float)Math.cos(Math.toRadians(pitchAngle));

    Vector3f xAxis = new Vector3f(
        cosYaw * cosPitch,
        sinYaw * cosPitch,
        -sinPitch
    );
    Vector3f yAxis = new Vector3f(
        cosYaw * sinPitch * sinRoll - sinYaw * cosRoll,
        sinYaw * sinPitch * sinRoll + cosYaw * cosRoll,
        cosPitch * sinRoll
    );
    Vector3f zAxis = new Vector3f(
        cosYaw * sinPitch * cosRoll + sinYaw * sinRoll,
        sinYaw * sinPitch * cosRoll - cosYaw * sinRoll,
        cosPitch * cosRoll
    );
    return multiply(
        xAxis.getX(),   xAxis.getY(),   xAxis.getZ(),   -xAxis.dot(eye),    //X column
        yAxis.getX(),   yAxis.getY(),   yAxis.getZ(),   -yAxis.dot(eye),    //Y column  
        zAxis.getX(),   zAxis.getY(),   zAxis.getZ(),   -zAxis.dot(eye),    //Z column
        0.0f,           0.0f,           0.0f,           1.0f                //W column
    );
}