四元数到方向向量
Quaternion To Direction Vector
我正在尝试将我的四元数转换为方向向量,以便我可以将我的相机朝它所面对的方向移动。我读到您可以先将四元数转换为旋转矩阵,然后再获取方向,所以我试过了。
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;
}
注:四元数[0]为x,四元数[1]为y,四元数[2]为z,四元数[3]为w。
几周来我一直在为此苦苦挣扎,我不知道哪里出了问题。如果有人对为什么这样做或其他方法有任何想法或建议,将不胜感激。谢谢!
那么让我们重新表述一下您想要做的事情:您有一个相机在全局框架中的位置表示,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_t
是G_R_C(q)
的最后一列。您使用的是最后一行,而不是最后一列。
我正在尝试将我的四元数转换为方向向量,以便我可以将我的相机朝它所面对的方向移动。我读到您可以先将四元数转换为旋转矩阵,然后再获取方向,所以我试过了。
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;
}
注:四元数[0]为x,四元数[1]为y,四元数[2]为z,四元数[3]为w。
几周来我一直在为此苦苦挣扎,我不知道哪里出了问题。如果有人对为什么这样做或其他方法有任何想法或建议,将不胜感激。谢谢!
那么让我们重新表述一下您想要做的事情:您有一个相机在全局框架中的位置表示,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_t
是G_R_C(q)
的最后一列。您使用的是最后一行,而不是最后一列。