四元数转方向向量

4

我试图将我的四元数转换为方向向量,以便我可以沿着它面对的方向移动我的相机。我读到可以先将四元数转换为旋转矩阵,然后获取方向。因此我尝试了这种方法。

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。
我已经苦苦挣扎了几个星期,但无法理解出错的原因。如果有人有任何想法或建议,可以让它正常工作或使用其他方法实现,将不胜感激。谢谢!

为什么不直接将单位向量乘以四元数? - Tim B
1个回答

1
所以让我们重新阐述一下你想做的事情:你有相机在全局坐标系中的位置表示,G_p1,想要将其在自身坐标系中向前移动一个量C_t = [0;0;1](这里,G_前缀表示全局坐标系,C_表示相机)。
我们想要计算G_p2 = G_p1 + G_t。我们需要用C_t来表示G_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)的最后一列。你正在使用最后一行,而不是最后一列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接