四元数到方向向量

时间:2015-11-20 15:46:28

标签: c++ vector quaternions

我试图将我的四元数转换为方向向量,这样我就可以朝着它面向的方向移动相机。我读到你可以先将四元数转换为旋转矩阵然后得到方向,所以我试过了。

inline Matrix4<float> ToRotationMatrix() {
    Vector3<float> forward = Vector3<float>( 2.0f * ( GetX() * GetZ() - GetW() * GetY() ), 2.0f * ( GetY() * GetZ() + GetW() * GetX() ), 1.0f - 2.0f * ( GetX() * GetX() + GetY() * GetY() ) );
    Vector3<float> up = Vector3<float>( 2.0f * ( GetX() * GetY() + GetW() * GetZ() ), 1.0f - 2.0f * ( GetX() * GetX() + GetZ() * GetZ() ), 2.0f * ( GetY() * GetZ() - GetW() * GetX() ) );
    Vector3<float> right = Vector3<float>( 1.0f - 2.0f * ( GetY() * GetY() + GetZ() * GetZ() ), 2.0f * ( GetX() * GetY() - GetW() * GetZ() ), 2.0f * ( GetX() * GetZ() + GetW() * GetY() ) );

    return Matrix4<float>().InitRotationFromVectors( forward, up, right );
}

inline Matrix4<T> InitRotationFromVectors( const Vector3<T> &n, const Vector3<T> &v, const Vector3<T> &u ) {
    Matrix4<T> ret = Matrix4<T>().InitIdentity();

    ret[ 0 ][ 0 ] = u.GetX();
    ret[ 1 ][ 0 ] = u.GetY();
    ret[ 2 ][ 0 ] = u.GetZ();

    ret[ 0 ][ 1 ] = v.GetX();
    ret[ 1 ][ 1 ] = v.GetY();
    ret[ 2 ][ 1 ] = v.GetZ();

    ret[ 0 ][ 2 ] = n.GetX();
    ret[ 1 ][ 2 ] = n.GetY();
    ret[ 2 ][ 2 ] = n.GetZ();

    return ret;
}

inline Vector3<float> GetForward( const Matrix4<float> &rotation ) const {
    return Vector3<float>( rotation[ 2 ][ 0 ], rotation[ 2 ][ 1 ], rotation[ 2 ][ 2 ] );
}

当我的相机朝前时,它会以正确的方向移动,但是当我转动它时,相机开始向错误的方向移动。相机像这样旋转。

void Camera::Rotate( const Vector3<float> &axis, float angle ) {
    Rotate( Quaternion( axis, angle ) );
}

void Camera::Rotate( const Quaternion &quaternion ) {
    m_rotation = Quaternion( ( quaternion * m_rotation ).Normalized() );
}

并将这些四元数相乘......

inline Quaternion operator*( const Quaternion &quat ) const {
    Quaternion ret;

    ret[ 3 ] = ( ( *this )[ 3 ] * quat[ 3 ] ) - ( ( *this )[ 0 ] * quat[ 0 ] ) - ( ( *this )[ 1 ] * quat[ 1 ] ) - ( ( *this )[ 2 ] * quat[ 2 ] );
    ret[ 0 ] = ( ( *this )[ 3 ] * quat[ 0 ] ) + ( ( *this )[ 0 ] * quat[ 3 ] ) + ( ( *this )[ 1 ] * quat[ 2 ] ) - ( ( *this )[ 2 ] * quat[ 1 ] );
    ret[ 1 ] = ( ( *this )[ 3 ] * quat[ 1 ] ) + ( ( *this )[ 1 ] * quat[ 3 ] ) + ( ( *this )[ 2 ] * quat[ 0 ] ) - ( ( *this )[ 0 ] * quat[ 2 ] );
    ret[ 2 ] = ( ( *this )[ 3 ] * quat[ 2 ] ) + ( ( *this )[ 2 ] * quat[ 3 ] ) + ( ( *this )[ 0 ] * quat[ 1 ] ) - ( ( *this )[ 1 ] * quat[ 0 ] );

    return ret;
}

注意:Quaternion [0]是x,Quaternion [1]是y,Quaternion [2]是z,Quaternion [3]是w。

我几周来一直在努力解决这个问题,而且我对可能出错的想法不以为然。如果任何人对于其工作原理或其他方法有任何想法或建议,我们将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:2)

因此,让我们改写你想要做的事情:你在全局框架G_p1中表示相机的位置,并希望在自己的框架中向前移动量C_t = [0;0;1](这里,G_前缀表示全局帧,C_表示相机)。

我们要计算G_p2 = G_p1 + G_t。我们需要用G_t来代表C_t

我们可以将其写为G_t = G_R_C C_t,其中G_R_C是描述从相机到全局帧的旋转的旋转矩阵。将此作为四元数q的函数编写,您只需计算G_t = G_R_C(q) C_t并将其添加到该位置。由于C_t = [0;0;1],您可以看到G_tG_R_C(q)的最后一列。您正在使用最后一行,而不是最后一列。