2

OpenGL バインディング LWJGL で動作するように Java で作成しようとしている 3D 仮想カメラに問題があります。問題は、カメラが FPS と同じ動きに追従できるようにしたいということです。これは、Y 軸 (左右) を中心に回転させることで、固定軸を中心に回転させたいということです。そのため、X 軸を中心に 45 度下を向いてから左を見ると、新しく変形された Y 軸ではなく、固定 (0, 1, 0) 軸を中心にこの回転を実行したいと考えています。

現時点では、現在のシステムは任意の軸を中心とした回転を作成することで機能します。この軸は、回転メソッドのパラメーターとして指定されます。回転 Y メソッドでは、ハードコードされた固定の上向きの 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);
    }
}

Y 軸が変換されないように 15 行目を無効にしようとしましたが、ビューが非常に歪んでいて、X 軸の回転が表示されません。ここでどこが間違っているのか誰にもわかりますか?

編集:それをいじって、上記のコードを更新しました。歪んだ形状のソースを見つけました。新しいベクトルをそれぞれ正規化するだけで解決しました。

ただし、ビューが歪んで変換された Y 座標ではなく、(0, 1, 0) を中心に回転する方法がわかりません。カメラを上下に動かせるようにしたい (X 軸の回転) だけでなく、Y 軸も効果的に同じ方向に維持したいと考えています。FPS では、すべての軸が以前に回転した方向から自由に回転しますが、下を向いて左に曲がると、回転した軸ではな​​く元の Y 軸を中心に回転します。これを達成するのはかなり簡単ですか?

4

0 に答える 0