2012-01-16 130 views
4

我成功实现了相机的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似乎正常工作。

截图:X axis (Y rotation)

截图:Y axis (X rotation)

然而,当我将二者结合起来(即移动的lookAt点,从而X和Y不0.0F),一些Z旋转被施加,这不应该发生,因为UP x DIRECTION应该总是导致RIGHT.y()为0.0f。 Z轴旋转将使用toZRadians(尚未实施)应用。

截图:Added Z rotation

而且我发现,如果我再移动的lookAt点向下Y轴,模型依然沿用了的lookAt点,但它实际上围绕全局X轴旋转(或equivilant到至少)。

截图:Global X rotation

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

截图:Inverted X rotation

模型仍然围绕全局X轴旋转,因为它在的lookAt点为+ Z一样。

截图:Global X rotation (lookAt -Z)

正如我所说,这很可能是对矩阵的工作方式的误解,但它可能是别的东西。我环顾了好几天,我似乎只能找到基于相机的lookAt功能。任何解释矩阵中包含的轴的源代码都会导致本文中介绍的代码。

回答

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

而且工作完美。非常愚蠢的错误,我甚至没有想过要检查。这也解释了轴上奇怪的反转。