opengl - 四元数旋转,试图围绕他的轴旋转一个对象

标签 opengl math rotation quaternions euler-angles

我在 Opengl 中显示字符,我让它们绕着四元数的轴旋转,我想要实现的是让它们绕着自己的轴旋转,但是当使用四元数时,如果我根据一个轴旋转一个对象,其他轴则不会没有考虑到这个旋转将围绕一个固定的世界轴旋转。 给定四元数 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();

到目前为止,它们都没有工作...我不认为我的旋转实现是问题,但如果有人这样做,我会发布代码。欧拉不是我想的那样吗?我应该使用什么轮换来实现我的目标?

编辑:我试过这个,帖子建议:

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();

最佳答案

我的第一个建议是不要使用欧拉角定义四元数旋转:

这里有一些链接比我能更好地解释它:

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

我建议将您的旋转定义为单个轴和角度,并按照此编写您的类接口(interface),这里有一些建议:

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

例如,如果您想对角色应用 45 个单位角度(度数或弧度,取决于您的旋转方法)的“滚动”旋转:

enter image description here

localAxis = Vector3(1,0,0);
angle = 45;

关于opengl - 四元数旋转,试图围绕他的轴旋转一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24681490/

相关文章:

math - 你如何计算入射角?

JavaScript 和 HTML5 - 朝鼠标方向旋转角色

apache-flex - 无法将 ImageSnapshot.captureBitmapData 与旋转矩阵一起使用

css - 如何将字体图标旋转 45 度?

opengl - 如何让 OpenGL 相机指向下方?

java - LWJGL 的 Assimp 教程

opengl - 如何找到贝塞尔曲线上两点之间的角度?

java - 旋转矩阵的逆序

php - 将数字的百分比添加到自身

java - 递归平方分割