【问题标题】:OpenGL 3 (LWJGL) LookAt Matrix ConfusionOpenGL 3 (LWJGL) LookAt 矩阵混淆
【发布时间】:2013-01-29 18:04:25
【问题描述】:

我正在使用 LWJGL 学习 OpenGL 3。我试图实现一个等效于gluLookAt() 的方法,虽然它有效,但我对为什么有些困惑。

我承认只是从网络上的各种来源复制此代码,但经过大量研究,我认为了解其背后的数学原理,并且我了解 LWJGL 在做什么。

但是,“正确”gluLookAt 代码在我的应用程序中的行为不正确,因为相机似乎转向了错误的方向。我只设法通过转置正交向量forwardsideup 来使我的代码工作(希望我使用的是正确的术语!),我很确定这是错误的......

private static final Vector3f forward = new Vector3f();
private static final Vector3f side = new Vector3f();
private static final Vector3f up = new Vector3f();
private static final Vector3f eye = new Vector3f();

public static Matrix4f lookAt(float eyeX, float eyeY, float eyeZ, 
                              float centerX, float centerY, float centerZ, 
                              float upX, float upY, float upZ) {
    forward.set(centerX - eyeX, centerY - eyeY, centerZ - eyeZ);
    forward.normalise();

    up.set(upX, upY, upZ);

    Vector3f.cross(forward, up, side);
    side.normalise();

    Vector3f.cross(side, forward, up);
    up.normalise();

    Matrix4f matrix = new Matrix4f();
    matrix.m00 = side.x;
    matrix.m01 = side.y;
    matrix.m02 = side.z;

    matrix.m10 = up.x;
    matrix.m11 = up.y;
    matrix.m12 = up.z;

    matrix.m20 = -forward.x;
    matrix.m21 = -forward.y;
    matrix.m22 = -forward.z;

    matrix.transpose(); // <------ My dumb hack

    eye.set(-eyeX, -eyeY, -eyeZ);
    matrix.translate(eye);

    return matrix;
}

我认为我不应该进行转置,但没有它就行不通。我输入了transpose(),因为我懒得重新输入所有矩阵单元格的位置!

我的理解是lookAt矩阵的形式应该如下

[ side.x  up.x  fwd.x  0 ] [ 1  0  0  -eye.x ]
[ side.y  up.y  fwd.y  0 ] [ 0  1  0  -eye.y ]
[ side.z  up.z  fwd.z  0 ] [ 0  0  1  -eye.z ]
[      0     0      0  1 ] [ 0  0  0       1 ]

我认为 LWJGL Matrix4f 类将矩阵单元表示为 m&lt;col&gt;&lt;row&gt;translate(Vector3f) 方法执行以下操作

public static Matrix4f translate(Vector3f vec, Matrix4f src, Matrix4f dest) {
  ...
    dest.m30 += src.m00 * vec.x + src.m10 * vec.y + src.m20 * vec.z;
    dest.m31 += src.m01 * vec.x + src.m11 * vec.y + src.m21 * vec.z;
    dest.m32 += src.m02 * vec.x + src.m12 * vec.y + src.m22 * vec.z;
    dest.m33 += src.m03 * vec.x + src.m13 * vec.y + src.m23 * vec.z;
  ...
}

所以我对我搞砸了这部分内容感到非常困惑。是我对Matrix4f 的lookAt 矩阵、列/行专业性(这是一个词吗?!)的理解,还是其他什么?我的其余代码是否刚刚损坏?它真的正确吗,我只是担心太多了吗?我只是个白痴吗?

谢谢。

【问题讨论】:

    标签: java opengl matrix lwjgl glulookat


    【解决方案1】:

    你不应该转置任何东西。你应该否定lookAt()矩阵的“眼睛”向量和观察方向。“眼睛”对应于相机位置,应该总是倒置。所有这些都在lookAt()内完成

    这是来自famous GLM math lib 的Java 端口的lookAt() 方法。

     public static Mat4 lookAt(Vec3 eye, Vec3 center, Vec3 up) {
    
        Vec3 f = normalize(Vec3.sub(center, eye));
        Vec3 u = normalize(up);
        Vec3 s = normalize(cross(f, u));
        u = cross(s, f);
    
        Mat4 result = new Mat4(1.0f);
        result.set(0, 0, s.x);
        result.set(1, 0, s.y);
        result.set(2, 0, s.z);
        result.set(0, 1, u.x);
        result.set(1, 1, u.y);
        result.set(2, 1, u.z);
        result.set(0, 2, -f.x);
        result.set(1, 2, -f.y);
        result.set(2, 2, -f.z);
    
        return translate(result, new Vec3(-eye.x,-eye.y,-eye.z));
    }
    

    我将它与我的基于 LWJGL 的 OpenGL 4 渲染器一起使用,它就像一个魅力:)

    【讨论】:

    • 感谢您的回答。很高兴知道我离得不远。方法是 Mat4.set(, , )?
    • 没错,我建议在 github 上搜索整个库。我不记得项目的名称,但它是 LWJGL 教程。
    • @Zutty 例如将 result.set(1, 0, s.y) 替换为 result.m10 = s.y;
    • @MichaelIV 所指的项目是jgltut ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2015-12-17
    • 2020-10-01
    • 2012-01-20
    • 2019-11-23
    • 1970-01-01
    相关资源
    最近更新 更多