Added Q_Slerp() for spherical interpolation between two quaterions.

This commit is contained in:
Revar Desmera 2019-02-01 23:33:07 -08:00
parent 497ddb15ae
commit 851dec95ac

View file

@ -31,6 +31,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
use <math.scad>
// Quaternions are stored internally as a 4-value vector: // Quaternions are stored internally as a 4-value vector:
// [X, Y, Z, W] = W + Xi + Yj + Zk // [X, Y, Z, W] = W + Xi + Yj + Zk
function _Quat(a,s,w) = [a[0]*s, a[1]*s, a[2]*s, w]; function _Quat(a,s,w) = [a[0]*s, a[1]*s, a[2]*s, w];
@ -60,6 +63,17 @@ function Q_Normalize(q) = q/Q_Norm(q);
function Q_Dist(q1, q2) = Q_Norm(Q_Sub(q1-q2)); function Q_Dist(q1, q2) = Q_Norm(Q_Sub(q1-q2));
// Returns a spherical interpolation between two quaternions.
function Q_Slerp(q1, q2, t) = let(
dot = Q_Dot(q1, q2),
qq2 = dot<0? Q_Neg(q2) : q2,
dott = dot<0? -dot : dot,
theta = t * acos(constrain(dott,-1,1))
) (dott>0.9995)?
Q_Normalize(Q_Add(q1, Q_Mul_S(Q_Sub(qq2,q1), t))) :
Q_Add(Q_Mul_S(q1,cos(theta)), Q_Mul_S(Q_Normalize(Q_Sub(qq2, Q_Mul_S(q1, dott))), sin(theta)));
// Returns the 3x3 rotation matrix for the given normalized quaternion q. // Returns the 3x3 rotation matrix for the given normalized quaternion q.
function Q_Matrix3(q) = [ function Q_Matrix3(q) = [
[1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3]], [1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3]],