function quat_slerp(QUATERNION *q, QUATERNION *u, QUATERNION *v, double t) {
QUATERNION qa, qb;
quat_set(&qa, u);
quat_set(&qb, v);
double cosHalfTheta=qa.w*qb.w + qa.x*qb.x + qa.y*qb.y + qa.z*qb.z;
if(abs(cosHalfTheta)>=1.0)
quat_set(&q,&qa);
else
{
double halfTheta=acos(cosHalfTheta);
double sinHalfTheta=sqrt(1.0 - cosHalfTheta*cosHalfTheta);
if (abs(sinHalfTheta) < 0.001)
{
q.w = (qa.w * 0.5 + qb.w * 0.5);
q.x = (qa.x * 0.5 + qb.x * 0.5);
q.y = (qa.y * 0.5 + qb.y * 0.5);
q.z = (qa.z * 0.5 + qb.z * 0.5);
}
else
{
double ratioA = sin((1 - t) * halfTheta) / sinHalfTheta;
double ratioB = sin(t * halfTheta) / sinHalfTheta;
q.w = (qa.w * ratioA + qb.w * ratioB);
q.x = (qa.x * ratioA + qb.x * ratioB);
q.y = (qa.y * ratioA + qb.y * ratioB);
q.z = (qa.z * ratioA + qb.z * ratioB);
}
}
}