【问题标题】:Rotate a model with a quaternion使用四元数旋转模型
【发布时间】:2013-12-15 20:06:53
【问题描述】:

我已经找到了解决这个问题的方法,但似乎没有一个有效。

我正在使用 JBullet 库并检索对象方向,它以四元数的形式给出。我将如何从这个四元数中检索欧拉值以便我可以调用..?

glRotate(rotationX, 1, 0, 0);
glRotate(rotationY, 0, 1, 0);
glRotate(rotationZ, 0, 0, 1);

或者也许有更有效的方法?

编辑:

我试过 quat -> vec

public static Vector3f quatToVec(Quat4f q) {
        float x = q.x;
        float y = q.y;
        float z = q.z;
        float w = q.w;
        float roll  = (float) (Math.atan2(2*y*w - 2*x*z, 1 - 2*y*y - 2*z*z) / Math.PI * 360);
        float pitch = (float) (Math.atan2(2*x*w - 2*y*z, 1 - 2*x*x - 2*z*z) / Math.PI * 360);
        float yaw   =  (float) (Math.asin(2*x*y + 2*z*w) / Math.PI * 720);
        return new Vector3f(yaw, pitch, roll);
    }

我试过quat -> 旋转矩阵

public static FloatBuffer quatToMatrix(Quat4f q) {
        float qx = q.x;
        float qy = q.y;
        float qz = q.z;
        float qw = q.w;
        FloatBuffer fb = BufferUtils.createFloatBuffer(16);
        fb.put(new float[]{1.0f - 2.0f*qy*qy - 2.0f*qz*qz, 2.0f*qx*qy - 2.0f*qz*qw, 2.0f*qx*qz + 2.0f*qy*qw, 0.0f,
                2.0f*qx*qy + 2.0f*qz*qw, 1.0f - 2.0f*qx*qx - 2.0f*qz*qz, 2.0f*qy*qz - 2.0f*qx*qw, 0.0f,
                2.0f*qx*qz - 2.0f*qy*qw, 2.0f*qy*qz + 2.0f*qx*qw, 1.0f - 2.0f*qx*qx - 2.0f*qy*qy, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f});
        fb.flip();
        return fb;
    }

但似乎都不起作用

【问题讨论】:

  • 你尝试了什么?什么不起作用? ...因为我们不是来做你的工作/研究的!
  • @Vallentin 好的 :)

标签: java opengl graphics 3d lwjgl


【解决方案1】:

您发布的第二个解决方案更可取,因为欧拉角在 +/- 90 度间距处存在奇点(在其他领域称为万向节锁定)。

您现在最大的障碍是无论出于何种原因,您的矩阵都是行优先的。因为这是一个通用的FloatBuffer,而不是一个实际的矩阵类,所以当你做fb.put (...) 时,你可能不得不自己转置矩阵。

这应该可以解决问题:

fb.put(new float[] {1.0f - 2.0f*qy*qy - 2.0f*qz*qz, 2.0f*qx*qy + 2.0f*qz*qw,        2.0f*qx*qz - 2.0f*qy*qw,        0.0f,
                    2.0f*qx*qy - 2.0f*qz*qw,        1.0f - 2.0f*qx*qx - 2.0f*qz*qz, 2.0f*qy*qz + 2.0f*qx*qw,        0.0f,
                    2.0f*qx*qz + 2.0f*qy*qw,        2.0f*qy*qz - 2.0f*qx*qw,        1.0f - 2.0f*qx*qx - 2.0f*qy*qy, 0.0f,
                    0.0f,                           0.0f,                           0.0f,                           1.0f});

【讨论】:

  • 非常感谢,从 2003 年开始,您已经结束了数小时的痛苦搜索论坛,并给出了这个答案 :)
【解决方案2】:

您可以使用 1 个轮换调用

glRotation(Math.acos(q.w)*360/Math.PI, q.x, q.y, q.z);

但是矩阵提取更可取,因为它避免了 glRotation 调用中的 acos 和 cos

【讨论】:

    【解决方案3】:

    我之前遇到过这个问题,这是我的(直接复制粘贴)代码:

        static public void addBoneRotation(float[] quart){
        //0  1  2  3   4   5   6
        //x, y, z, qw, qx, qy, qz;
    
        //rotate by (qw, qx, qy, qz)
        tmp.m00=1 - 2*quart[5]*quart[5] - 2*quart[6]*quart[6];
        tmp.m01=2*quart[4]*quart[5] - 2*quart[6]*quart[3];
        tmp.m02=2*quart[4]*quart[6] + 2*quart[5]*quart[3];
        tmp.m03=0;
        tmp.m10=2*quart[4]*quart[5] + 2*quart[6]*quart[3];
        tmp.m11=1 - 2*quart[4]*quart[4] - 2*quart[6]*quart[6];
        tmp.m12=2*quart[5]*quart[6] - 2*quart[4]*quart[3];
        tmp.m13=0;
        tmp.m20=2*quart[4]*quart[6] - 2*quart[5]*quart[3];
        tmp.m21=2*quart[5]*quart[6] + 2*quart[4]*quart[3];
        tmp.m22=1 - 2*quart[4]*quart[4] - 2*quart[5]*quart[5];
        tmp.m23=0;
        tmp.m30=tmp.m31=tmp.m32=0;
        tmp.m33=1;
    
        //translate by (x,y,z)
        tmp2.m30=quart[0];
        tmp2.m31=quart[1];
        tmp2.m32=quart[2];
    
        Matrix4f.mul(tmp2,tmp,tmp);
        //add to the current bone transformation
        Matrix4f.mul(tmp, bone, bone);
    }
    

    这假设 quart[] 持有骨骼平移旋转。

    您需要稍作更改以匹配您的应用程序。

    允许连续的这些调用将骨骼链接在一起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-14
      • 2020-04-11
      相关资源
      最近更新 更多