public static Quaternion Slerp(Quaternion start, Quaternion end, decimal blend) { // Clone to avoid modifying the parameters var q1 = start.Clone(); var q2 = end.Clone(); // if either input is zero, return the other. if (q1.Magnitude() == 0) { return(q2.Magnitude() == 0 ? Identity : q2); } if (q2.Magnitude() == 0) { return(q1); } var cosHalfAngle = q1.Dot(q2); if (cosHalfAngle >= 1 || cosHalfAngle <= -1) { return(q1); } if (cosHalfAngle < 0) { q2.Vector = -q2.Vector; q2.Scalar = -q2.Scalar; cosHalfAngle = -cosHalfAngle; } decimal blendA; decimal blendB; if (cosHalfAngle < 0.99m) { // do proper slerp for big angles var halfAngle = DMath.Acos(cosHalfAngle); var sinHalfAngle = DMath.Sin(halfAngle); var oneOverSinHalfAngle = 1 / sinHalfAngle; blendA = DMath.Sin(halfAngle * (1 - blend)) * oneOverSinHalfAngle; blendB = DMath.Sin(halfAngle * blend) * oneOverSinHalfAngle; } else { // do lerp if angle is really small. blendA = 1 - blend; blendB = blend; } var result = new Quaternion(blendA * q1.Vector + blendB * q2.Vector, blendA * q1.W + blendB * q2.W); return(result.Magnitude() > 0 ? result.Normalise() : Identity); }
public static Quaternion Lerp(Quaternion start, Quaternion end, decimal blend) { // Clone to avoid modifying the parameters var q1 = start.Clone(); var q2 = end.Clone(); // if either input is zero, return the other. if (q1.Magnitude() == 0) { return(q2.Magnitude() == 0 ? Identity : q2); } if (q2.Magnitude() == 0) { return(q1); } var blendA = 1 - blend; var blendB = blend; var result = new Quaternion(blendA * q1.Vector + blendB * q2.Vector, blendA * q1.W + blendB * q2.W); return(result.Magnitude() > 0 ? result.Normalise() : Identity); }