用于相机的C++OpenGL四元数将其倒置

C++ OpenGL Quaternion for Camera flips it upside down

本文关键字:四元数 相机 C++OpenGL 用于      更新时间:2023-10-16

当我向右移动到目标时,它确实会观察目标,并向上观察它,直到它偏离-zaxis 180度,然后决定转向另一个方向。

Matrix4x4 camera::GetViewMat()
{
    Matrix4x4 oRotate, oView;
    oView.SetIdentity();
    Vector3 lookAtDir = m_targetPosition - m_camPosition;
    Vector3 lookAtHorizontal = Vector3(lookAtDir.GetX(), 0.0f, lookAtDir.GetZ());
    lookAtHorizontal.Normalize();
    float angle = acosf(Vector3(0.0f, 0.0f, -1.0f).Dot(lookAtHorizontal));
    Quaternions horizontalOrient(angle, Vector3(0.0f, 1.0f, 0.0f));
    ori = horizontalOrient;
    ori.Conjugate();
    oRotate = ori.ToMatrix();
    Vector3 inverseTranslate = Vector3(-m_camPosition.GetX(), -m_camPosition.GetY(), -m_camPosition.GetZ());
    oRotate.Transform(inverseTranslate);
    oRotate.Set(0, 3, inverseTranslate.GetX());
    oRotate.Set(1, 3, inverseTranslate.GetY());
    oRotate.Set(2, 3, inverseTranslate.GetZ());
    oView = oRotate;
    return oView;
}

正如承诺的那样,一些代码显示了我如何让相机始终观察空间中的特定点。

首先,我们需要一种从角度和轴构造四元数的方法,我碰巧在pastebin上有这个方法,角度输入以弧度为单位:

http://pastebin.com/vLcx4Qqh

确保你没有输入轴(0,0,0),这将没有任何意义。

现在实际的更新方法是,我们需要获得四元数,将相机从默认方向旋转到指向目标点。请注意,我只是在脑海中写下了这篇文章,它可能需要一点调试,也可能需要一些优化,但这至少应该会给你一个正确的方向。

void camera::update()
{
    // First get the direction from the camera's position to the target point
    vec3 lookAtDir = m_targetPoint - m_position;
    // I'm going to divide the vector into two 'components', the Y axis rotation
    // and the Up/Down rotation, like a regular camera would work.
    // First to calculate the rotation around the Y axis, so we zero out the y
    // component:
    vec3 lookAtHorizontal = vec3(lookAtDir.x, 0.0f, lookAtDir.z).normalize();
    // Get the quaternion from 'default' direction to the horizontal direction
    // In this case, 'default' direction is along the -z axis, like most OpenGL
    // programs. Make sure the projection matrix works according to this.
    float angle = acos(vec3(0.0f, 0.0f, -1.0f).dot(lookAtHorizontal));
    quaternion horizontalOrient(angle, vec3(0.0f, 1.0f, 0.0f));
    // Since we already stripped the Y component, we can simply get the up/down
    // rotation from it as well.
    angle = acos(lookAtDir.normalize().dot(lookAtHorizontal));
    if(angle) horizontalOrient *= quaternion(angle, lookAtDir.cross(lookAtHorizontal));
    // ...
    m_orientation = horizontalOrient;
}

现在实际拍摄m_orientationm_position并获得世界->相机矩阵

// First inverse each element (-position and inverse the quaternion),
// the position is rotated since the position within a matrix is 'added' last
// to the output vector, so it needs to account for rotation of the space.
mat3 rotationMatrix = m_orientation.inverse().toMatrix();
vec3 inverseTranslate = rotationMatrix * -m_position; // Note the minus
mat4 matrix = mat3; // just means the matrix is expanded, the last entry (bottom right of the matrix) is a 1.0f like an identity matrix would be.
// This bit is row-major in my case, you just need to set the translation of the matrix.
matrix[3] = inverseTranslate.x;
matrix[7] = inverseTranslate.y;
matrix[11] = inverseTranslate.z;

EDIT我认为这应该是显而易见的,但只是为了完整性,.dot()取向量的点积,.cross()取叉积,执行方法的对象是向量A,方法的参数是向量B。