Wednesday, November 24, 2010

Dual Quaternions... All the Way... Across the Vectorspace

I can't believe I'm saying this, but complex-numbers actually kinda make sense. Dual numbers and split-complex numbers confuse me.

However, I'm trying to get a handle on them because there seems to be a small new wave of skinning techniques coming from "dual quaternions": quaternions composed of 4 "dual numbers" instead of 4 Real numbers.

DISCLAIMER: I am by no means a pedantic mathematician, so I'm probably going to say something really wrong by the measure of what a mathematician would deem appropriate. I'm approaching this purely from an application and implementation standpoint.

So, back to the basic definition of a complex number: i is the "imaginary unit" such that i*i = -1. A coordinate in the complex plane is given by a Real coefficient and an imaginary one (i.e. 1 and i are basis vectors). This gives a + bi as a complex number.

Dual numbers and split-complex numbers are almost the same.... except e, the "dual unit", is defined as e*e = 0 and j, the "split-complex unit", is defined as j*j = 1. Wait, what? but that should give e = sqrt(0) and j = sqrt(1). Aren't those both 0 and 1, respectively?

Well it turns out that if you take e to be the matrix [[0, 1][0, 0]], you can get some useful properties out of it (covered here). It maintains the property that e*e is the 0-matrix, and allows you to have an "alternate complex plane" of two coefficients a and b such that a + be is a dual number.

Using dual numbers as components of quaternions instead of Real numbers allows you to introduce a translation component directly into the quaternion. How this alteration affects quaternion multiplication is demonstrated here. As far as I can tell, this type of transformation is called a "rigid transformation". I'm not sure why it's called that, but if you need to research things more, there's a keyword for you.

Since complex numbers can be distributed, having a quaternion defined as [v, s] such that v = [x + ae, y + be, z + ce] and s = [w + de], you can describe this "dual quaternion" by breaking it into two, regular quaternions where one is scaled by the dual unit: Q0 + eQ1 such that Q0 = [x, y, z, w] and Q1 = [a, b, c, d].

Hey, that's neat... just like the imaginary unit, we can pretty much ignore the dual unit and not attempt to represent it until we need to get meaningful info out of the quaternion!

So, how is this pertinent is for skinning? Instead of having an encompassing data-structure like a VQS transformation (V = vector = position, Q = quaternion = rotation, and S = scale), translation can be incorporated directly into the concatenation of Quaternions, much like linear transformations in matrices.

There are various papers that demonstrate the usefulness of this, elsewhere [Kavan et al. 2006]. In many instances, it cuts down on the number of operations you have to do since the translation is right there. It also naturally covers some pinching edge cases, just like quaternion double-cover does for blending.

It seems to have many benefits, so far, apart from some more mathematical complexity. Since when has mathematical complexity stopped game programmers from shaving off a few instructions? There's a catch (isn't there always?). They can't be linearly interpolated in a clean manner. Kavan et al. maintain that the only effective way to interpolate between dual quaternions is an extension of Slerp called "Screw Linear Interpolation" or "Sclerp". There does exist away to linearly interpolate, but it requires lots of silly finagling that is more costly than Sclerp-ing, itself. Directly interpolating the components is ineffective and can result in singularities. That's not cool.

That's a problem. Sclerp being the only effective means of interpolation means that:
  1. Animation blending is order-dependent, e.g Sclerp(Sclerp(Q0,Q1),Q2) != Sclerp(Q0,Sclerp(Q1, Q2)).
  2. The only method of blending is VERY expensive. Just like Slerp, Sclerp has a linear combination of sin() and cos(). If you've already approximated your animation to the frame-level with a fitted curve, you don't need hyper-correct, constant-velocity interpolation between each keyframe. It's unnecessary complexity.
So, while they're kinda nifty... I'm not so sure that they'll lead to anything for game developers until a better interpolation method is found. I definitely want to do more research to see if there is a better way to interpolate, and I just don't see it. Until then, VQS it is!

EDIT (11/25/10): There's a light at the end of the tunnel! I learned from Andy Firth and Christian Diefenbach of Bungie that you can effectively avoid the singularities of linearly blending dual quaternions. I'll post my findings one the fuller proofs of how that's possible. This makes me happy, dual quaternions seem like a very useful solution to skinning with animation blending, and it'd be a shame to not be able to use them for real-time applications

No comments:

Post a Comment