OpenGL 3(LWJGL)LookAt矩阵混淆

6

我正在使用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<col><row>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;
  ...
}

我非常困惑,不知道哪个部分出了问题。是我的lookAt矩阵的理解有误,还是Matrix4f的列/行优先(这是一个单词吗?!)有问题,还是其他原因?我的代码剩下的部分是否正确呢?它其实是正确的,只是我过于担心了吗?我是个笨蛋吗?

谢谢。

1个回答

12

你不应该转置任何东西。你需要否定lookAt()矩阵的“EYE”向量和观察方向。这里的“EYE”对应于摄像机位置,它应该始终被反转。这一切都在lookAt()中完成。

这是Java版的著名GLM数学库中的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(<column>, <row>, <value>)吗? - Zutty
确切地说,我建议在 GitHub 上搜索整个库。我不记得项目的名称,但它是 LWJGL 教程。 - Michael IV
1
@Zutty,将例如result.set(1, 0, s.y)替换为result.m10 = s.y;。 - Michael Hall
2
@MichaelIV所提到的项目是jgltut ;) - user1266094

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接