关于数学:模型lookAt Matrix-C ++,OpenGL

Model lookAt Matrix - C++, OpenGL

我成功地为相机实现了lookAt矩阵,因为有许多描述它的资料。

我一直试图将其从相机lookAt转换为模型lookAt。我似乎无法使其正常工作,并且我假设我对矩阵的构造方式有一些误解。我假设我不需要更改模型的转换就可以查看一个点,因为它的位置应该保持不变。

首先,这里是相关代码。 lookAtRadians函数应在平移的同一参考框架中查看指定的点(即-位置=方向)。但是,有些问题将在屏幕截图中显示。它不检查direction.y()是否为1.0f或-1.0f,但这是微不足道的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void TransformMatrix3D::lookAtRadians(float atX, float atY, float atZ, float toZRadians)
{
    Vector3D direction(atX - x(), atY - y(), atZ - z());
    direction.normalize();

    Vector3D up(0.0f, 1.0f, 0.0f);

    Vector3D right(direction.crossProduct(up));
    right.normalize();
    up = direction.crossProduct(right);

    mMatrix[0] = right.x();
    mMatrix[4] = right.y();
    mMatrix[8] = right.z();
    mMatrix[1] = up.x();
    mMatrix[5] = up.y();
    mMatrix[9] = up.z();
    mMatrix[2] = direction.x();
    mMatrix[6] = direction.y();
    mMatrix[10] = direction.z();
}

这是叉积和归一化函数,以防它们不正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Vector3D Vector3D::crossProduct(const Vector3D& rightVector) const
{
    const float NEW_X(y() * rightVector.z() - z() * rightVector.y());
    const float NEW_Y(z() * rightVector.x() - x() * rightVector.z());
    const float NEW_Z(x() * rightVector.y() - y() * rightVector.x());

    return Vector3D(NEW_X, NEW_Y, NEW_Z);
}


void Vector3D::normalize()
{
    float length(x() * x() + y() * y() + z() * z());

    if(fabs(length) == 1.0f)
        return;

    length = 1.0f / sqrt(length);
    moveTo(x() * length, y() * length, z() * length);
}

这是一些截图来描述我的问题。白色球形表示lookAt点。

我创建了一个沿Z轴平移-10.0f的多维数据集(这会将mMatrix[12]mMatrix[13]mMatrix[14]分别设置为0.0f,0.0f,-10.0f。矩阵的其余部分是恒等式。我已经检查了就是这种情况),我将用它来演示问题。

屏幕截图:无旋转

如果我仅沿X和Y轴移动lookAt点,则lookAt似乎可以正常工作。

屏幕截图:X轴(Y旋转)

屏幕截图:Y轴(X旋转)

但是,当我将两者结合时(即,移动lookAt点,以便X和Y都不为0.0f),将应用一些Z旋转,因为UP x DIRECTION总是会导致RIGHT.y(),所以不应发生这种旋转。为0.0f。 Z旋转将使用toZRadians应用(尚未实现)。

截图:添加了Z旋转

我还发现,如果我随后将lookAt点沿Y轴向下移动,则模型仍将遵循lookAt点,但实际上它绕着全局X轴旋转(或至少与之等效)。

屏幕截图:全局X旋转

现在,当lookAt点移至-Z时,模型具有正确的Y旋转,但X旋转已反转。我在这一点上检查了向量,发现UP.y()为负,这是不可能的(可以为0.0f,但不能为负),因为DIRECTION和RIGHT应该始终以相同的方式缠绕(即从指向右)。 UP.y()可能为负的唯一方法是,如果RIGHT实际上为LEFT。

屏幕截图:反转X旋转

模型仍然像lookAt点为+ Z时一样绕全局X轴旋转。

屏幕截图:全局X旋转(lookAt -Z)

正如我提到的那样,这可能是对矩阵工作方式的误解,但可能还有其他事情。我环顾了好几天,似乎只能找到基于相机的lookAt函数。解释矩阵中包含的轴的任何资料都导致了本文中提供的代码。


嗯,我发现了问题。 如此简单,我忽略了它。

我的矩阵:

1
2
3
4
5
6
7
8
9
mMatrix[0] = right.x();
mMatrix[4] = right.y();
mMatrix[8] = right.z();
mMatrix[1] = up.x();
mMatrix[5] = up.y();
mMatrix[9] = up.z();
mMatrix[2] = direction.x();
mMatrix[6] = direction.y();
mMatrix[10] = direction.z();

在内存中定义的列主。 它应该是:

1
2
3
4
5
6
7
8
9
mMatrix[0] = right.x();
mMatrix[1] = right.y();
mMatrix[2] = right.z();
mMatrix[4] = up.x();
mMatrix[5] = up.y();
mMatrix[6] = up.z();
mMatrix[8] = direction.x();
mMatrix[9] = direction.y();
mMatrix[10] = direction.z();

而且效果很好。 极其愚蠢的错误,我什至没有想到要检查。 这也解释了轴上的反演。