2

我希望能够创建一个第一人称的相机,并且可以处于两种模式之一。它要么固定在特定位置(标准的“wasd”移动围绕该点移动),要么具有自由查看,其中移动不受限制在一个点周围盘旋,鼠标可用于查看任何地方。(虽然只能向上/向下看,因为我不想要一个六自由度的相机来下降)这意味着我目前不想滚动。

有人可以指导我完成实现这种事情所需的基础知识吗?我目前正在使用 LWJGL,因此我可以访问它们提供的 Vector* 和 Matrix* 类,以及我自己的 Quaternion 类,它可以做一些 LWJGL 没有做的事情。还假设我有一个方法lookAt,它的坐标与OpenGL的gluLookAt(eyex,eyey,...,upy,upz)完全相同,这就是我想要构建矩阵/矩阵的地方。还假设生成的矩阵/矩阵将在版本 330 着色器中使用,其中

layout(location = 0) in vec4 position;
uniform mat4 camera;
uniform mat4 projection;
uniform mat4 model;
// ...
gl_Position = projection * camera * model * (position);

是一些代码。我是保持当前的操作顺序,还是需要以任何方式更改它以获得正确的 gl_Position?

四元数代码:

public class Quaternion {
    public float x, y, z, w;

    public Quaternion() {
        this.x = 0.0f;
        this.y = 0.0f;
        this.z = 0.0f;
        this.w = 1.0f;
    }

    public Quaternion(Vector3f v, float w) {
        this.x = v.x;
        this.y = v.y;
        this.z = v.z;
        this.w = w;
    }

    public Quaternion(float x, float y, float z, float w) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.w = w;
    }

    public Quaternion(Quaternion other) {
        this.x = other.x;
        this.y = other.y;
        this.z = other.z;
        this.w = other.w;
    }

    public float length() {
        return (float)Math.sqrt(x * x + y * y + z * z + w * w);
    }

    public Quaternion normalize() {
        return Quaternion.normalize(new Quaternion(this));
    }

    public Quaternion conjugate() {
        return Quaternion.conjugate(new Quaternion(this));
    }

    public Quaternion mult(Quaternion other) {
        return Quaternion.mult(this, other, new Quaternion());
    }

    public static Quaternion fromAxisAngle(Quaternion q, Vector3f axis, float angle) {
        float sinAngle2 = (float)Math.sin(angle / 2.0);
        q.x = axis.x * sinAngle2;
        q.y = axis.y * sinAngle2;
        q.y = axis.y * sinAngle2;
        q.w = (float)Math.cos(angle / 2.0);
        return q;
    }

    public static Matrix4f toMatrixUnit(Quaternion q) {
        Matrix4f ret = new Matrix4f();

        ret.m00 = 1 - 2 * q.y * q.y - 2 * q.z * q.z;
        ret.m01 = 2 * q.x * q.y - 2 * q.w * q.z;
        ret.m02 = 2 * q.x * q.z + 2 * q.w + q.y;
        ret.m03 = 0;

        ret.m10 = 2 * q.x * q.y + 2 * q.w * q.z;
        ret.m11 = 1 - 2 * q.x * q.x - 2 * q.z * q.z;
        ret.m12 = 2 * q.y * q.z + 2 * q.w * q.x;
        ret.m13 = 0;

        ret.m20 = 2 * q.x * q.z - 2 * q.w * q.z;
        ret.m21 = 2 * q.y * q.z - 2 * q.w * q.x;
        ret.m22 = 1 - 2 * q.x * q.x - 2 * q.y * q.y;
        ret.m23 = 0;

        ret.m30 = 0;
        ret.m31 = 0;
        ret.m32 = 0;
        ret.m33 = 1;

        return ret;
    }

    public static Matrix4f toMatrix(Quaternion q) {
        throw new UnsupportedOperationException("Use toMatrixUnit");
//        Matrix4f ret = new Matrix4f();
//        return ret;
    }

    public static Quaternion mult(Quaternion A, Quaternion B, Quaternion C) {
        C.x = A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
        C.y = A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
        C.z = A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
        C.w = A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
        return C;
    }

    public static Quaternion normalize(Quaternion q) {
        float len = q.length();
        q.x = q.x / len;
        q.y = q.y / len;
        q.z = q.y / len;
        q.w = q.w / len;
        return q;
    }

    public static Quaternion conjugate(Quaternion q) {
        q.x = -q.x;
        q.y = -q.y;
        q.z = -q.z;
        return q;
    }
4

1 回答 1

1

如果您在 Google 上搜索,有大量资源可用于实现基于四元数的相机。

如果您使用 C++,我建议使用GLM(OpenGL 数学)来支持他们的 vec/mat/quat(如果您只是在学习,它胜过在您的算术中出现错误。)

于 2013-03-14T21:04:26.197 回答