0
\$\begingroup\$

I have some existing code which does catmull-rom interpolation on two vectors (facing and up). I'm converting this to use quaternions instead (to replace the two vectors). Is there a general way to convert the vector based interpolation to a quaternion one?

The approach I'm using now is to exact the axis and angle from the quanternion. I then interpolate each of those independently and convert back to a quaternion. Is there a more direct method?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Have you tried simply interpolating the quaternion components, then normalising the result? It is definitely “more direct” and the results are very similar. \$\endgroup\$ Jun 4, 2014 at 9:30
  • \$\begingroup\$ Well, that seems to work for me. I don't know if it's producing the same results but it'll be fine for my use. \$\endgroup\$ Jun 4, 2014 at 11:55

2 Answers 2

4
\$\begingroup\$

Since it seems acceptable, I’ll go for the following suggestion: just interpolate the quaternion components, then normalise the resulting quaternion.

  • pro: it’s fast and the code is short
  • pro: and there is no need to handle the case when the angle reaches 360 degrees and warps back to zero.

  • con: you can still get singularities if the quaternions aren’t carefully computed

  • con: the derivative of the rotation angle is not constant along the curve (but it’s still almost constant)

If that last issue becomes problematic, you could use slerp() instead of linear interpolation. Slerp only works with two quaternions whereas in a Catmull-Rom spline you usually blend four, but there is a method (see Barry and Goldman's pyramidal formulation) that lets you compute the spline using only pairwise interpolations if you attach time values to each point.

\$\endgroup\$
1
  • \$\begingroup\$ The first con I don't have since my inputs are all valid unit quaternions (and no division is involved in the interpolation). The second con is not an issue for me since I'm just doing this for visual continuity and don't actually care about physical accuracy. The pairwise approach looks like it might be somewhat costly in comparison. \$\endgroup\$ Jun 4, 2014 at 17:59
2
\$\begingroup\$

In one of the earlier Game Programming Gems books there exists an article which outlines how to do spline interpolation of orientations represented with quaternions.

The gist is that a mapping from SO(3) to R4 is made, the interpolation is performed component-wise in R4 as with any other vector, and a reverse mapping from R4 to SO(3) is performed.

I believe that the mapping should be largely free of singularities, but you would have to consult the text to find out the particulars.

inline float4 SO3ToR4(Quat const& q)
{
    float const mul = 1.0f / sqrt(2.0f * (1.0f - q.w));
    return float4(q.x, q.y, q.z, (1.0f - q.w)).Mul(mul);
}

inline Quat R4ToSO3(float4 const& v)
{
    float4 const sq = v.Mul(v);
    float const denom = v.SumOfElements();
    float const s = sq.xyz().SumOfElements() - sq.w;
    return Quat(
        2.0f*v.x*v.w/denom,
        2.0f*v.y*v.w/denom,
        2.0f*v.z*v.w/denom,
        s/denom);
}
\$\endgroup\$
2
  • \$\begingroup\$ As q.w approaches 1 the precision here will be a problem, with a division by zero at q.w == 1. \$\endgroup\$ Jun 4, 2014 at 12:45
  • \$\begingroup\$ @edA-qamort-ora-y Ah right, the caveat mentioned in the article was something along the lines of "there's a singularity facing straight up/down, constrain your orientations accordingly." \$\endgroup\$ Jun 4, 2014 at 13:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .