模型lookAt Matrix - C ++,OpenGL

时间:2012-01-16 04:52:34

标签: c++ math vector 3d matrix

我成功地为相机实现了lookAt矩阵,因为有很多来源描述它。

我一直在尝试将其从相机外观转换为模型外观。我似乎无法让它工作,我认为我对如何构建矩阵有一点误解。我假设我不需要更改模型的翻译来查看某个点,因为它的位置应保持不变。

首先,这是相关代码。 lookAtRadians函数应该查看在相同的referance帧中指定的点和它的平移(即at - 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。其余矩阵是身份。我已经检查过这种情况)我将用它来证明问题。

屏幕截图:No rotation

如果我沿着X轴和Y轴移动lookAt点,lookAt似乎正常工作。

屏幕截图:X axis (Y rotation)

屏幕截图:Y axis (X rotation)

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

屏幕截图:Added Z rotation

此外,我发现如果我将lookAt点向下移动到Y轴,模型仍然遵循lookAt点,但它实际上围绕全局X轴旋转(或者至少等于那个)。

屏幕截图:Global X rotation

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

屏幕截图:Inverted X rotation

模型仍然围绕全局X轴旋转,就像lookAt点为+ Z时那样。

屏幕截图:Global X rotation (lookAt -Z)

正如我所提到的,这可能是对矩阵工作方式的误解,但它可能是另一回事。我环顾了几天,我似乎只能找到基于相机的lookAt功能。解释矩阵中包含的轴的任何来源都会导致本文中提供的代码。

1 个答案:

答案 0 :(得分:5)

啊,我发现了问题。这么简单我忽略了它。

我的矩阵:

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();

这完美无缺。非常愚蠢的错误,我甚至没想过要检查。这也解释了轴上的奇怪倒置。