• Advertisement
Sign in to follow this  

Quaternion Slerp - Shorter way around?

Recommended Posts

I seem to be having an issue with making a quaternion interpolate through the shortest path. I am making use of Bullet's math/phyiscs package and the quaternion slerp function it provides. My research tells me that when the dot product of two quaternions is negative you should negate one of them. Is my approach correct? It doesn't seem to be producing the correct result.

void vSlerp(btQuaternion& start, btQuaternion& end, float t, btQuaternion& result)
{
	 
	start = start.normalize();
	end = end.normalize();

	float dot = start.dot(end);

	if (dot > 0.999995)
	{
		result=start;
	}
	else if (dot >= 0)
	{
		result = slerp(start,end,t); // Bullet quaternion slerp 
	}
	else
	{
		result = slerp(start, -end, t); // avoid going the longer way around?
	}
	
	result.normalize();
}

Any idea or suggestion is greatly appreciated! Thanks!

Share this post


Link to post
Share on other sites
Advertisement

The bullet slerp should already be a a slerp function. Meaning that inside of it, there is already a way to deal with a shortest path; it is what slerp is made for.

Just use slerp() as is.


Here is a look into what your slerp function should look like.

Spoiler

 


void vSlerp(btQuaternion& start, btQuaternion& end, float t)
{
	 
	start = start.normalize();
	end = end.normalize();

	float dot = start.dot(end); //Finds the dot product
  
  	//We need the absolute value of dot
	if (dot < 0){
		dot = dot *-1; //don't know if your start.dot does this.
	}
  
	if (dot > 0.999995)
	{
	//Interpolate, this is where everything gets done
     	btQuaternion& Result = start + t*(end  start);//This is just liniar interpolation
      
      	dot = Result.normalize();
	}
  	
	//Now if dot is negative it means it's taking the long path, we want it to take the shorter path
	//To do this we reverse one of the Quaternion so that the rotation goes to the other side
	else if (dot < 0)
	{
	end = end *-1;//Now it thinks the end is on the other side
	dot = dot *-1;
	}
  
	//We want some kind of safty here because of floating point errors.
  	dot = clamp(dot,-1,1);
  
  	float StartToEndAngle = acos(dot);
  	float StartToResultAngle = StartToEndAngle * t;
  	
  	Quaternion basis = end  start*dot;
  	basis.normalize();
  
  	//Now we should get a smooth animation with it always taking the shortest path
  	return start*cos(StartToResultAngle) + basis*sin(StartToResultAngle);
}

 

 

 

 

Edited by Scouting Ninja

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement