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的多维数据集(这会将
屏幕截图:无旋转
如果我仅沿X和Y轴移动lookAt点,则lookAt似乎可以正常工作。
屏幕截图:X轴(Y旋转)
屏幕截图:Y轴(X旋转)
但是,当我将两者结合时(即,移动lookAt点,以便X和Y都不为0.0f),将应用一些Z旋转,因为UP x DIRECTION总是会导致RIGHT.y(),所以不应发生这种旋转。为0.0f。 Z旋转将使用
截图:添加了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(); |
而且效果很好。 极其愚蠢的错误,我什至没有想到要检查。 这也解释了轴上的反演。