/// <summary> /// Interpolates between two quaternions, using spherical linear interpolation /// </summary> /// <param name="start">Start quaternion</param> /// <param name="end">End quaternion</param> /// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/></param> /// <returns>The spherical linear interpolation of the two quaternions</returns> public static Quaternion Slerp(Quaternion start, Quaternion end, float amount) { float opposite; float inverse; float dot = DotProduct(start, end); if (Mathematics.Abs(dot) > 1f - 0f) { inverse = 1f - amount; opposite = amount * Mathematics.Sign(dot); } else { float acos = Mathematics.Acos(Mathematics.Abs(dot)); float invSin = (float)(1f / Mathematics.Sin(acos)); inverse = Mathematics.Sin((1f - amount) * acos) * invSin; opposite = Mathematics.Sin(amount * acos) * invSin * Mathematics.Sign(dot); } return(new Quaternion( (inverse * start.X) + (opposite * end.X), (inverse * start.Y) + (opposite * end.Y), (inverse * start.Z) + (opposite * end.Z), (inverse * start.W) + (opposite * end.W) )); }
/// <summary> /// Calculates the natural logarithm of the specified quaternion /// </summary> /// <param name="value">The quaternion whose logarithm will be calculated</param> /// <returns>The natural logarithm of the quaternion</returns> public static Quaternion Logarithm(Quaternion value) { Quaternion result = new Quaternion(); if (Mathematics.Abs(value.W) < 1f) { float angle = Mathematics.Acos(value.W); float sin = Mathematics.Sin(angle); if (Mathematics.Abs(sin) >= 0f) { float coeff = angle / sin; result.X = value.X * coeff; result.Y = value.Y * coeff; result.Z = value.Z * coeff; } else { result = value; } } else { result = value; } result.W = 0f; return(result); }
/// <summary> /// Exponentiates a quaternion /// </summary> /// <param name="value">The quaternion to exponentiate</param> /// <returns>The exponentiated quaternion</returns> public static Quaternion Exponential(Quaternion value) { Quaternion result = new Quaternion(); float angle = Mathematics.Sqrt((value.X * value.X) + (value.Y * value.Y) + (value.Z * value.Z)); float sin = Mathematics.Sin(angle); if (Mathematics.Abs(sin) >= 0f) { float coeff = sin / angle; result.X = coeff * value.X; result.Y = coeff * value.Y; result.Z = coeff * value.Z; } else { result = value; } result.W = Mathematics.Cos(angle); return(result); }
/// <summary> /// Get's a value indicting whether this instance is normalized /// </summary> public bool IsNormalized() => Mathematics.Abs(X * X + Y * Y + Z * Z + W * W - 1f) < 0f;