- From: Brendan Kenny <bckenny@gmail.com>
- Date: Wed, 8 Jul 2015 19:21:36 -0700
- To: "Tab Atkins Jr." <jackalmage@gmail.com>
- Cc: Shane Stephens <shans@google.com>, "public-fx@w3.org" <public-fx@w3.org>
On Wed, Jul 8, 2015 at 12:21 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote: > On Mon, Jul 6, 2015 at 8:31 PM, Shane Stephens <shans@google.com> wrote: >> Hi list, >> >> Here's how we currently define quaternion SLERPing during interpolation: >> http://dev.w3.org/csswg/css-transforms/#interpolation-of-decomposed-3d-matrix-values >> >> When quatA = [0, 1, 0, 0] and quatB = [0, -1, 0, 0], this has the >> unfortunate side effect of setting product to -1, which means the definition >> of 'w' has 0 in the denominator. >> >> What do? > > Something analogous to the early exit when product is 1, I would > assume. I don't know how math works, so I'm not sure what the right > answer is. This is another example where the "shortest path" rotation[1] would fix things. Since [0, 1, 0, 0] and [0, -1, 0, 0] represent the same orientation/rotation, the shortest path is just an identity transform. Adding an early exit like when the product is 1 will add a discontinuity under the current interpolation algorithm, because two quaternions that are *almost* antipodal will do a full lap around before coming back to nearly the same orientation. It will have to be special-cased regardless, though, as the slerp path between quaternions is not unique iff their dot product has an absolute value of 1. The "correct" long path rotation would be to pick an arbitrary (quaternion) axis to rotate around, but if that level of edit needs to occur, it's the perfect chance to add the much simpler always-take-the-shortest-path change instead! > (By the way, the clamping code is exactly wrong. It should use min() > for the upper bound and max() for the lower bound; as written, it > ensures that product is *outside* the (-1,1) range.) There are a few odd things in the pseudo code: - Why is the clamping included at all? They have to be unit quaternions, so the clamping is just an implementation detail to make sure numerical issues don't take the dot product outside the domain of acos and sqrt - `theta = acos(dot)` should be `theta = acos(product)` - the expression multiplied with quaternionA's components can also be pulled out of the loop like `w`, which would make it a bit clearer: for (i = 0; i < 4; i++) quaternionDst[i] = w1 * quaternionA[i] + w2 * quaternionB[i] - the code doesn't take the shortest path between quaternions which really would be way better :) Is there a reason discussion of this fell off? Brendan [1] https://lists.w3.org/Archives/Public/www-style/2013May/0131.html
Received on Thursday, 9 July 2015 02:22:33 UTC