四元数旋转应该如何表现?

时间:2013-04-19 03:49:10

标签: rotation quaternions

过去几天我一直在慢慢搞清楚四元数,并遇到了意想不到的问题。在最终得到代码后,我发现传递给我的旋转函数的数字并没有产生与度数或弧度相关的旋转。

这是我的旋转功能

void solveRotation(Quaternion* q, float pitch, bool localx, float yaw, bool localy, float roll, bool localz)
{
    Quaternion temp;
    if(yaw !=0.f)
    { 
        if(localy==true)
        {
            //quaternionMultBA(q, yaw, 0.f, 1.f, 0.f);
            temp.w = q->w*yaw - q->y;
            temp.x = q->x*yaw + q->z;
            temp.y = q->y*yaw + q->w;
            temp.z = q->z*yaw - q->x;
        }
        else
        {
            //quaternionMultAB(q, yaw, 0.f, 1.f, 0.f);
            temp.w = q->w*yaw - q->y;
            temp.x = q->x*yaw - q->z;
            temp.y = q->w + q->y*yaw;
            temp.z = q->z*yaw + q->x;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }
    if(pitch != 0.f)
    {
        if(localx==true)
        {

            //quaternionMultBA(q, pitch, 1.f, 0.f, 0.f);
            temp.w = q->w*pitch - q->x;
            temp.x = q->x*pitch + q->w;
            temp.y = q->y*pitch - q->z;
            temp.z = q->z*pitch + q->y;
        }
        else
        {
            //quaternionMultAB(q, pitch, 1.f, 0.f, 0.f);
            temp.w = q->w*pitch - q->x;
            temp.x = q->w + q->x*pitch;
            temp.y = q->y*pitch + q->z;
            temp.z = q->z*pitch - q->y;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }
    if(roll != 0.f)
    {
        if(localz==true)
        {

            //quaternionMultBA(q, roll, 0.f, 0.f, 1.f);
            temp.w = q->w*roll - q->z;
            temp.x = q->x*roll - q->y;
            temp.y = q->y*roll + q->x;
            temp.z = q->z*roll + q->w;
        }
        else
        {
            //quaternionMultAB(q, roll, 0.f, 0.f, 1.f);
            temp.w = q->w*roll - q->z;
            temp.x = q->x*roll + q->y;
            temp.y = q->y*roll - q->x;
            temp.z = q->z*roll + q->w;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }

    normalize(q);
}

上面的代码传递一个值,具体取决于在循环迭代期间按下了哪些键。首先,我将值设置为0.1,并期望慢速旋转。 相反,我看到每次迭代都有一个很大的转弯,在60fps时看起来很奇怪。当我将传递的值更改为1.0时,我正在处理的立方体似乎完成了90度旋转(颜色移动但几何体没有移动)

当我将通过的数量增加到5以上时,我开始看到我期待的平稳旋转,并注意到随着我增加值,它减慢了。我想了很多,但它确实没有帮助我,因为我不能用它来旋转特定的数量。我读过的任何四元数教程都没有提到这类问题,因为它们都提到了弧度。我不确定我是犯了错误,还是我错过了一个额外的步骤,或者我搞砸了整个该死的东西。

提前感谢您的帮助, 回复也可能很慢

1 个答案:

答案 0 :(得分:0)

所以我做了一些搜索并修改了我的函数,以包含我缺少的sin和cos函数。因为我在GPwiki上看到的代码示例,我以为我能够在没有触发的情况下完成旋转。无论如何,这个功能现在已修复,如果有人想使用它 - 即使有可能更好的那里 - 这里是:

void solveRotation(Quaternion* q, float pitch, bool localx, float yaw, bool localy, float roll, bool localz)
{
    Quaternion temp;
    float s;
    float c;
    if(yaw !=0.f)
    { 
        yaw*=0.5f;
        s = sin(yaw);
        c = cos(yaw);
        if(localy==true)
        {
            temp.w = q->w*c - q->y*s;
            temp.x = q->x*c + q->z*s;
            temp.y = q->y*c + q->w*s;
            temp.z = q->z*c - q->x*s;
        }
        else
        {
            temp.w = q->w*c - q->y*s;
            temp.x = q->x*c - q->z*s;
            temp.y = q->y*c + q->w*s;
            temp.z = q->z*c + q->x*s;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }
    if(pitch != 0.f)
    {
        pitch*=0.5f;
        s = sin(pitch);
        c = cos(pitch);
        if(localx==true)
        {
            temp.w = q->w*c - q->x*s;
            temp.x = q->x*c + q->w*s;
            temp.y = q->y*c - q->z*s;
            temp.z = q->z*c + q->y*s;
        }
        else
        {
            temp.w = q->w*c - q->x*s;
            temp.x = q->x*c + q->w*s;
            temp.y = q->y*c + q->z*s;
            temp.z = q->z*c - q->y*s;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }
    if(roll != 0.f)
    {
        roll*=0.5f;
        s = sin(roll);
        c = cos(roll);
        if(localz==true)
        {
            temp.w = q->w*c - q->z*s;
            temp.x = q->x*c - q->y*s;
            temp.y = q->y*c + q->x*s;
            temp.z = q->z*c + q->w*s;
        }
        else
        {
            temp.w = q->w*c - q->z*s;
            temp.x = q->x*c + q->y*s;
            temp.y = q->y*c - q->x*s;
            temp.z = q->z*c + q->w*s;
        }
        q->w=temp.w;
        q->x=temp.x;
        q->y=temp.y;
        q->z=temp.z;
    }

    normalize(q);
}

顺便感谢Jim Lewis