我成功实现了相机的lookAt矩阵,因为有很多来源描述它。模型lookAt矩阵 - C++,OpenGL
我一直在试图从相机lookAt翻译到模型lookAt。我似乎无法让它起作用,并且我假设我对矩阵的构建方式有轻微的误解。我假设我不需要改变模型的翻译来看待某一点,因为它的位置应该保持不变。
首先,这里是相关的代码。 lookAtRadians函数应该查看同一个参照框架中指定的点,因为它是平移的(即在 - 位置=方向)。但是,有一些问题,我将在屏幕截图中展示。它不检查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点。
我创建翻译-10.0f向下Z轴的立方体(这将设置mMatrix[12]
,mMatrix[13]
和mMatrix[14]
为0.0f,0.0F,-10.0f分别矩阵的其余部分的身份。我已检查这是这样的),我将用它来展示问题。
截图:No rotation
如果我移动的lookAt点仅沿X轴和Y轴的的lookAt似乎正常工作。
然而,当我将二者结合起来(即移动的lookAt点,从而X和Y不0.0F),一些Z旋转被施加,这不应该发生,因为UP x DIRECTION应该总是导致RIGHT.y()为0.0f。 Z轴旋转将使用toZRadians
(尚未实施)应用。
而且我发现,如果我再移动的lookAt点向下Y轴,模型依然沿用了的lookAt点,但它实际上围绕全局X轴旋转(或equivilant到至少)。
现在,当的lookAt点移动至-Z,该模型具有正确的Y轴旋转,但它的X轴旋转反转。我在这一点检查了我的向量,发现UP.y()是负数,这是不可能的(它可以是0.0f,但不是负数),因为DIRECTION和RIGHT总是以相同方式缠绕向右)。 UP.y()可能是负数的唯一方法是如果RIGHT实际上是左边的。
模型仍然围绕全局X轴旋转,因为它在的lookAt点为+ Z一样。
截图:Global X rotation (lookAt -Z)
正如我所说,这很可能是对矩阵的工作方式的误解,但它可能是别的东西。我环顾了好几天,我似乎只能找到基于相机的lookAt功能。任何解释矩阵中包含的轴的源代码都会导致本文中介绍的代码。