Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Dual Quaternion Slerp

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2013
    Posts
    25

    Dual Quaternion Slerp

    Hey All,

    I'm implementing a skinning algorithm using dual quaternions to represent the translation/rotation of my joints a la wscg.zcu.cz/wscg2012/short/A29-full.pdf. However, I'm getting some errors during interpolation, and I suspect it's due to the fact that my quaternions aren't being normalized.

    Here's the deal: I understand how to use quaternions to represent rotation, and I understand why slerp works in this case. In order for us to use slerp we need a unit quaternion, and the rotation quaternion is unit (unit vector for axis, sin**2+cos**2 = 1).

    However, I don't believe that you can use slerp for the translation component (aka dual part) because it is not a unit quaternion on its own. We could normalize them, but if we did then we'd be losing the original translation information we wanted to store. We could store the translation magnitude, normalize the translation quaternion, and multiply it back in after slerp finishes, but then we'd have to linearly interpolate the magnitude, hence defeating the purpose of slerp.

    As of now, using glm, I've got the following slerp function:

    Code :
    using namespace glm; //not really but you get the idea
     
    fdualquat dualSlerp(fdualquat a, fdualquat b, float x){
       fdualquat ret;
       ret.real = slerp(a.real,b.real,x);
       ret.dual = lerp(a.dual,b.dual,x);
       return normalize(ret);
    }

    However, this feels dirty; there's no way I can combine slerp and lerp in the same function. However, I can't slerp the dual part because it's magnitude is greater than 1,

    To be honest, I don't see the point of dual quaternions at all if this is the case. Since we've got 8 floats in a dual quaternion, why not use one quaternion for rotation and one vec4 for translation? We could even use a vec3, but the one number isn't the issue here. Why are dual quaternions used at all?

  2. #2
    Member Regular Contributor
    Join Date
    Dec 2009
    Posts
    251
    The advantage of dual quaternions is that they can be composed easily, the algebra just works.

    If you use a quaternion + vector representation, you basically decompose your transform into a rotation r followed by a translation t. If you want to combine two transforms, you have to be careful: generally r1t1 * r2t2 != r1r2 t1t2, so you can't simply combine the rotation and translation components.

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2013
    Posts
    25
    Alright, I can see how that would make things easier to chain. Thanks.

    However, given all that, is my SLERP code correct?

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    894
    Sorry, can't help directly, but this paper by the same author as the one you linked above seems to have more details on interpolation. From a quick glance interpolation is a more involved operation than your implementation suggests

  5. #5
    Junior Member Newbie
    Join Date
    Dec 2013
    Posts
    25
    Yeesh. Well, alright, I'll press on.

    I'll stick with Dual Quaternions because I like the math. In theory, though, couldn't I define a class with a quaternion member (rotation) and a vec4 member (translation), overload the * operator to multiply the quaternion and add the translation, and use that to chain my transforms?

    Code :
    class QuatVec{
    public:
       fquat rot;
       vec3 trans;
       QuatVec(): rot(), trans(){}
       QuatVec(fquat r, vec3 t): rot(glm::normalize(r)), trans(t) {}
       QuatVec operator * (const QuatVec& other){
          return QuatVec(rot*other.rot, trans+other.trans);
       }
       QuatVec blend(const QuatVec& other, float x){
          return QuatVec(glm::slerp(rot,other.rot,x),glm::mix(trans,other.trans,x));
       }
       mat4 toMat4(){
          return glm::translate(trans)*glm::mat4_cast(rot);
       }
    };
    Last edited by mynameisjohn; 09-22-2014 at 05:09 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •