🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Quaternion Slerp - Shorter way around?

Started by
1 comment, last by Scouting Ninja 6 years, 7 months ago

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!

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);
}

 

 

 

 

This topic is closed to new replies.

Advertisement