我成功地为相机实现了一个lookAt矩阵,因为有很多描述它的来源。
我一直在尝试将这个从相机的lookAt转换为模型的lookAt。我似乎无法让它工作,我认为我对矩阵的构建方式有一些误解。我假设我不需要改变模型的位置来使其看向一个点,因为它的位置应该保持不变。
首先,这是相关代码。lookAtRadians函数应该在与其平移相同的参考框架中查看指定点(即在-position=direction处)。然而,存在一些问题,我将通过截图展示。它没有检查direction.y()是否为1.0f或-1.0f,但这是微不足道的。
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();
}
以下是叉积和归一化函数,如果不正确请参考。
叉积函数:
归一化函数:
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。将使用toZRadians
(尚未实现)应用Z旋转。
截图:添加了Z旋转
另外,我发现如果我将lookAt点向下移动到Y轴上,模型仍然跟随lookAt点移动,但它实际上围绕全局X轴旋转(或至少相当于那样)。
截图:全局X轴旋转
现在,当lookAt点移动到-Z时,模型具有正确的Y旋转,但其X旋转是反转的。我检查了此时的向量,并发现UP.y()为负,这不应该是可能的(它可以是0.0f,但不是负数),因为DIRECTION和RIGHT应始终以相同的方式盘旋(即从DIRECTION顺时针到RIGHT)。 UP.y()可能为负的唯一方法是如果RIGHT实际上是LEFT。截图:反转的X旋转
当lookAt点为+Z时,模型仍然围绕全局X轴旋转。
正如我所提到的,这很可能是对矩阵工作方式的误解,但也可能是其他原因。我已经寻找了几天,似乎只能找到基于相机的lookAt函数。任何解释矩阵中包含的轴的来源的来源都导致了本帖子中呈现的代码。