我在Opengl中显示caracters,我让它们围绕轴旋转四元数,我想要实现的是让它们围绕自己的轴旋转但是当使用四元数时,如果我按照一个斧头旋转一个物体,其他人不要考虑到这种旋转将围绕固定世界轴旋转。 给定四元数Qaccumulative(前旋转)和3个角度AngleX,AngleY和AngleZ。 首先我认为欧拉的轮换是尝试的东西,我尝试了几种技术:
Quaternion rot1;
Quaternion rot2;
Quaternion rot3;
Vector3 axis ;
float angle;
QAccumulative.getAxisAngle(&axis, &angle);
// first try : around fix axes
cout << "axis : " << axis << endl;
rot1.FromAxis(Vector3(1.0,0.0,0.0),angleX);
rot2.FromAxis(Vector3(0.0,1.0,0.0),angleY);
rot3.FromAxis(Vector3(0.0,0.0,1.0),angleZ);
QAccumulative = QAccumulative * rot1;
QAccumulative = QAccumulative * rot2;
QAccumulative = QAccumulative * rot3;
/*
// second try, around current modified axes
rot1.FromAxis(Vector3(axis.x,0.0,0.0),angleX);
rot2.FromAxis(Vector3(0.0,axis.y,0.0),angleY);
rot3.FromAxis(Vector3(0.0,0.0,axis.z),angleZ);
QAccumulative = QAccumulative * rot1;
QAccumulative = QAccumulative * rot2;
QAccumulative = QAccumulative * rot3;
*/
/*
// third try with Euler rotation
Quaternion rotation;
rotation.FromEuler(10*angleX,10*angleY,10*angleZ);
QAccumulative = QAccumulative * rotation;
*/
QAccumulative.normalise();
到目前为止,他们都没有工作......我不认为我的旋转实现是问题,但如果有人,我会发布代码。 Euler不是我认为的吗?我应该用什么样的轮换来实现我的目标?
编辑:我试过这个,帖子建议:rotate(float angleX,float angleY,float angleZ) {
Vector3 axis = Vector3(angleX,angleY,angleZ);
Vector3 worldAxis = QAccumulative * axis;
Quaternion worldRotation( worldAxis.x,worldAxis.y,worldAxis.z, 10 );
QAccumulative = worldRotation * QAccumulative;
QAccumulative.normalise();
角色仍围绕固定轴旋转。
编辑: 我应用了一个帖子给出的伪代码,它起作用了:
rotate(float angleX,float angleY,float angleZ) {
Vector3 axis = Vector3(angleX,angleY,angleZ);
Vector3 worldAxis = QAccumulative * axis;
Quaternion worldRotationx( 1.0,0,0, angleZ );
Quaternion worldRotationy( 0,1.0,0, angleX);
Quaternion worldRotationz( 0,0,1.0, -angleY );
QAccumulative = worldRotationx * worldRotationy * worldRotationz * QAccumulative;
QAccumulative.normalise();
答案 0 :(得分:2)
我的第一个建议是不使用欧拉角定义你的四元数旋转:
以下是一些可以解释它的链接:
http://bitsquid.blogspot.ca/2013/03/what-is-gimbal-lock-and-why-do-we-still.html
https://mathoverflow.net/questions/95902/the-gimbal-lock-shows-up-in-my-quaternions
http://answers.unity3d.com/questions/573035/avoiding-gimbal-lock.html
我建议您将旋转定义为单个轴和角度,然后编写您的类接口,以下是一些建议:
Vector3 operator* ( const Vector3& vec ) const; // rotate a vector
Quaternion operator* ( const Quaternion& quat ) const; // concatenate
void set( const Vector3& axis, float angle ); // set quaternion
void getAxisAngle( Vector3* axis, float* angle ); // extract axis and angle
对于使用四元数应用局部轴旋转,您可以简单地将局部轴转换为世界空间并以此方式应用变换。
我假设您将字符变换存储为旋转四元数,平移向量和缩放矢量/标量。在这种情况下,您只需将字符旋转四元数应用于局部轴以将其带入世界空间,然后使用该世界空间轴来构建并应用旋转。
您的角色当前旋转存储为四元数:
Quaternion characterQuaternion;
然后您有要应用的本地轮换:
Vector3 localAxis;
float angle;
您需要将局部轴转换为世界空间,然后从中构建四元数并将其应用于角色四元数:
Vector3 worldAxis = characterQuaternion * localAxis; // transform local axis to world coordinate system
Quaternion worldRotation( worldAxis, angle ); // build quaternion
characterQuaternion = worldRotation * characterQuaternion; // apply the rotation
例如,如果你想应用一个&#39; roll&#39;旋转角度为45个单位(度数或弧度取决于你的旋转方法)到你的角色:
localAxis = Vector3(1,0,0);
angle = 45;