2

我在尝试用 Java 制作以与 OpenGL 绑定 LWJGL 一起使用的 3D 虚拟相机时遇到问题。问题是我希望相机能够跟随与 FPS 相同的运动。我的意思是围绕 Y 轴(左右)进行旋转,我希望它围绕固定轴旋转。因此,当他们围绕 X 轴向下看 45 度然后向左看时,我希望围绕固定的 (0, 1, 0) 轴而不是新转换的 Y 轴进行旋转。

目前,当前系统通过围绕任意轴创建旋转来工作,该轴作为旋转方法的参数。在 rotateY 方法中,我将向上向量替换为硬编码的固定向上指向 Y 轴 (0, 1, 0),尽管这似乎不起作用。它只是表现得好像它围绕任意 Y 轴旋转。

这是 Camera 类的源代码:

public class Camera {
    public Vector4f pos, side, up, forward;

    public Camera() {
        pos = new Vector4f(0f, 2f, 0f);
        side = new Vector4f(1.0f, 0.0f, 0.0f);
        up = new Vector4f(0.0f, 1.0f, 0.0f);
        forward = new Vector4f(0.0f, 0.0f, 1.0f);
    }

    public void rotateX(float delta) {
        delta = (float) Math.toRadians(delta);
        Matrix4f mat = createRotation(delta, side.x, side.y, side.z);
        Vector4f n_up = Vector4f.multiply(mat, up);
        Vector4f n_forward = Vector4f.cross(side, n_up);
        n_up.normalise();
        n_forward.normalise();
        up = n_up;
        forward = n_forward;
    }

    public void rotateY(float delta) {
        delta = (float) Math.toRadians(delta);
        Matrix4f mat = createRotation(delta, up.x, up.y, up.z);
        Vector4f n_side = Vector4f.multiply(mat, side);
        Vector4f n_forward = Vector4f.cross(n_side, up);
        n_side.normalise();
        n_forward.normalise();
        side = n_side;
        forward = n_forward;
    }

    public Matrix4f createRotation(float angle, float x, float y, float z) {
        float cos = (float) Math.cos(angle);
        float sin = (float) Math.sin(angle);
        float one_c = 1.0f - cos;
        float xx = x * x;
        float yy = y * y;
        float zz = z * z;
        float xy = x * y;
        float xz = x * z;
        float yz = y * z;
        float xs = x * sin;
        float ys = y * sin;
        float zs = z * sin;
        float mag = (float) Math.sqrt(xx + yy + zz);

        if(mag == 0.0f) {
            float[] ident = new float[] {
                1.0f, 0.0f, 0.0f, 0.0f, 
                0.0f, 1.0f, 0.0f, 0.0f, 
                0.0f, 0.0f, 1.0f, 0.0f, 
                0.0f, 0.0f, 0.0f, 1.0f
            };
            return new Matrix4f(ident);
        }

        x /= mag;
        y /= mag;
        z /= mag;

        Matrix4f m = new Matrix4f();
        m.set(new float[] {
                (one_c * xx) + cos, 
                (one_c * xy) - zs, 
                (one_c * xz) + ys, 
                0.0f, 
                (one_c * xy) + zs, 
                (one_c * yy) + cos, 
                (one_c * yz) - xs, 
                0.0f, 
                (one_c * xz) - ys, 
                (one_c * yz) + xs, 
                (one_c * zz) + cos, 
                0.0f, 
                0.0f, 0.0f, 0.0f, 1.0f
            });
        return m;
    }

    public void transform() {
        GL11.glMultMatrix((FloatBuffer) BufferUtils.createFloatBuffer(16).put(new float[] {
                side.x, up.x, forward.x, 0.0f, 
                side.y, up.y, forward.y, 0.0f, 
                side.z, up.z, forward.z, 0.0f, 
                0.0f, 0.0f, 0.0f, 1.0f
        }).flip());

        GL11.glTranslatef(-pos.x, -pos.y, -pos.z);
    }
}

我尝试禁用第 15 行,这样 Y 轴就不会被转换,但这会使视图非常倾斜并且不显示任何 X 轴旋转。谁能看到我在这里出错的地方?

编辑:一直在玩它并更新了上面的代码。我找到了倾斜形状的来源。通过标准化每个新向量来解决这个问题。

我似乎无法弄清楚我如何围绕 (0, 1, 0) 旋转而不是转换后的 Y 坐标,但视图变得倾斜。我确实希望相机能够上下查看(X 轴旋转),但我也希望 Y 轴有效地保持在同一方向。在 FPS 中,所有轴都从其先前旋转的方向自由旋转,但是当它们向下看并向左转时,它们有点绕原始 Y 轴旋转,而不是旋转的 Y 轴。这实现起来相当简单吗?

4

0 回答 0