quaternion::slerp

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
JVr
Posts: 28
Joined: Wed Oct 19, 2011 2:32 pm

quaternion::slerp

Post by JVr »

This method is actually bugged coz it may product quaternion that are not normalized.

Original code (current trunk) - it's much worse code bugged same way in stable branch 1.7.2

Code: Select all

 
inline quaternion& quaternion::slerp(quaternion q1, quaternion q2, f32 time)
{
        f32 angle = q1.dotProduct(q2);
 
        // make sure we use the short rotation
        if (angle < 0.0f)
        {
                q1 *= -1.0f;
                angle *= -1.0f;
        }
 
        if (angle <= 0.95f) // spherical interpolation
        {
                const f32 theta = acosf(angle);
                const f32 invsintheta = reciprocal(sinf(theta));
                const f32 scale = sinf(theta * (1.0f-time)) * invsintheta;
                const f32 invscale = sinf(theta * time) * invsintheta;
                return (*this = (q1*scale) + (q2*invscale));
        }
        else // linear interploation
                return lerp(q1,q2,time);
}
 
modified code

Code: Select all

 
inline quaternion& quaternion::slerp(quaternion q1, quaternion q2, f32 time)
{
        f32 angle = q1.dotProduct(q2);
 
        // make sure we use the short rotation
        if (angle < 0.0f)
        {
                q1 *= -1.0f;
                angle *= -1.0f;
        }
 
        if (angle <= 1.0 - core::ROUNDING_ERROR_f32) // spherical interpolation
        {
                const f32 theta = acosf(angle);
                const f32 invsintheta = reciprocal(sinf(theta));
                const f32 scale = sinf(theta * (1.0f-time)) * invsintheta;
                const f32 invscale = sinf(theta * time) * invsintheta;
                return (*this = (q1*scale) + (q2*invscale));
        }
        else // linear interploation
                return lerp(q1,q2,time);
}
 
So the change is in constant that it's not 0.95 but 0.999999

This way it does not product quaternions with size > 1.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: quaternion::slerp

Post by hybrid »

Do you have quaternions which will return wrong results for the current method?
JVr
Posts: 28
Joined: Wed Oct 19, 2011 2:32 pm

Re: quaternion::slerp

Post by JVr »

OK I found that:

Source (-0.803446 0.012917 0.135859 0.579525) and (-0.587987 0.085837 0.129373 0.793830) blend 0.372368 result length 0.977165
Source (result) (-0.723216 0.040070 0.133444 0.659326)
Result scale 0.999113 0.974986 0.975745

Source (-0.687014 -0.001438 -0.097833 0.720027) and (0.870995 0.025545 0.099108 -0.480512) bland 0.589717 result length 0.977789
Source (result) (0.795511 0.015654 0.098585 -0.578781)
Result scale 0.999557 0.971037 0.971470

Source (-0.497304 -0.511197 -0.486029 0.505116) and (-0.280449 -0.571046 -0.669434 0.383554) bland 0.386144 result length 0.976528
Source (result) (-0.413567 -0.534307 -0.556850 0.458175)
Result scale 0.971640 0.977153 0.978334

As you see resultng scales may lead up to 3% deformation in any axis so on higher scale the resulting part may look to be deformed. Especially if it's multipied by some higher scale for example scale 10 would lead to 30% deformation etc..

Its true that using more "spherical interpolation" means a bit more floating point computation however it's not much more and resulting quaterion after linear interpolation of quaternions without same angle may lead to this kind of deformation.
Post Reply