我成功地为相机实现了 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);
}
这里有一些屏幕截图来描述我的问题。白色球体表示观察点。
我创建了一个沿 Z 轴平移 -10.0f 的立方体(这将设置 mMatrix[12]
、mMatrix[13]
和 mMatrix[14]
分别为 0.0f、0.0f、-10.0f。矩阵的其余部分是相同的。我已经检查过是这种情况),我将使用它来演示问题。
截图:No rotation
如果我仅沿 X 轴和 Y 轴移动 lookAt 点,lookAt 似乎可以正常工作。
但是,当我将两者组合时(即移动观察点,使 X 和 Y 都不是 0.0f),应用了一些 Z 旋转,这不应该发生,因为 UP x DIRECTION 应该总是导致 RIGHT。 y() 为 0.0f。 Z 旋转将使用 toZRadians
(尚未实现)应用。
我还发现,如果我随后将 lookAt 点沿 Y 轴向下移动,模型仍会跟随 lookAt 点,但它实际上会围绕全局 X 轴旋转(或至少与之等效)。
现在,当观察点移动到 -Z 时,模型具有正确的 Y 旋转,但它的 X 旋转是反转的。此时我检查了我的 vector ,我发现 UP.y() 是负数,这不应该是可能的(它可以是 0.0f,但不是负数)因为 DIRECTION 和 RIGHT 应该总是以相同的方式缠绕(即顺时针从向右方向)。 UP.y() 可能为负的唯一方法是 RIGHT 实际上是 LEFT。
当观察点为 +Z 时,模型仍然围绕全局 X 轴旋转。
截图:Global X rotation (lookAt -Z)
正如我提到的,这可能是对矩阵工作方式的误解,但也可能是其他原因。我环顾四周好几天了,似乎只能找到基于相机的 lookAt 函数。任何解释矩阵中包含的轴的来源都导致了本文中提供的代码。
最佳答案
啊,我发现问题了。太简单了,我忽略了它。
我的矩阵:
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();
是内存中定义的主要列。应该是:
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();
这非常有效。极其愚蠢的错误,我什至没想过要检查一下。这也解释了坐标轴中奇怪的反转。
关于c++ - 模型观察矩阵 - C++、OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8875909/