2
\$\begingroup\$
p0 ------- p1 ------- p2

I am successfully slerping between 2 points (p0-p1; p1-p2). But the transition between two slerped angles (p1_in-p1_out) do not match, and it looks jarring

Video of how it looks:

green squares are points, the position and angle between each are interpolated.

The issue is most visible at second 6.00

https://gfycat.com/unhealthygraveduckling

I tried hermite splines, although it reduces the effect, it's still visible.

I tried converting Catmull-Rom to use with quaternions by just adding the 4th index to the vector functions. This works perfectly except on some occasions, where some are interpolated from the wrong (long) "way", causing the view to flip between those points. I tried aligning, did not help.

Other questions on SO related to slerp don't ask this question, and I could not get any usable answers from some questions on 4 point slerps.

Is this a common issue, am I overseeing something?

Thanks

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I hadn't actually aligned in CatmullRom, it was one of my other tests. It got lost in all the messy code. The problem was solved by aligning the start and end points of the spline input. (params: pre, start, end, post)

The issue could also be solved by using circular blending, which I hadn't know, but it works as well. This video demonstrates my problem and the solution pretty well.

Quaternion aligning makes sure the quaternions are within 180 degrees of each other, if they're not, reverses one. This is the code I used:

void AlignQuaternions( const Quaternion &in1, const Quaternion &in2, Quaternion &out )
{
    float a = 0.0;
    float b = 0.0;

    // dot product of in1 - in2
    a += (in1.x-in2.x) * (in1.x-in2.x);
    a += (in1.y-in2.y) * (in1.y-in2.y);
    a += (in1.z-in2.z) * (in1.z-in2.z);
    a += (in1.w-in2.w) * (in1.w-in2.w);

    // dot product of in1 + in2
    b += (in1.x+in2.x) * (in1.x+in2.x);
    b += (in1.y+in2.y) * (in1.y+in2.y);
    b += (in1.z+in2.z) * (in1.z+in2.z);
    b += (in1.w+in2.w) * (in1.w+in2.w);

    if ( a > b )
    {
        out.x = -in2.x;
        out.y = -in2.y;
        out.z = -in2.z;
        out.w = -in2.w;
    }
    else
    {
        out.x = in2.x;
        out.y = in2.y;
        out.z = in2.z;
        out.w = in2.w;
    }
}
```
\$\endgroup\$
0

You must log in to answer this question.

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