c++ - 模型观察矩阵 - C++、OpenGL

标签 c++ math vector 3d matrix

我成功地为相机实现了 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 axis (Y rotation)

截图:Y axis (X rotation)

但是,当我将两者组合时(即移动观察点,使 X 和 Y 都不是 0.0f),应用了一些 Z 旋转,这不应该发生,因为 UP x DIRECTION 应该总是导致 RIGHT。 y() 为 0.0f。 Z 旋转将使用 toZRadians(尚未实现)应用。

截图:Added Z rotation

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

截图:Global X rotation

现在,当观察点移动到 -Z 时,模型具有正确的 Y 旋转,但它的 X 旋转是反转的。此时我检查了我的 vector ,我发现 UP.y() 是负数,这不应该是可能的(它可以是 0.0f,但不是负数)因为 DIRECTION 和 RIGHT 应该总是以相同的方式缠绕(即顺时针从向右方向)。 UP.y() 可能为负的唯一方法是 RIGHT 实际上是 LEFT。

截图:Inverted X rotation

当观察点为 +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/

相关文章:

java - 访问存储在 vector 中的对象的变量

c++ - 通过重载 < 对自定义对象的 vector 进行排序

C++专访: vtable for a class with a pure virtual function

c# - 如何在 C# 中计算指定数量项的总和?

c++ - 需要帮助格式化数字 C++

c++ - 初始化通过引用传递的 vector

c++ - 可能的段错误 : Am I using the "this->" operator correctly?

c++ - 从另一个文件访问 C++ 中的外部变量

带网页的 C++ 输出

java - 确定平均值