namespace Zinnia.Extension { using UnityEngine; /// /// Extended methods for the Type. /// public static class QuaternionExtensions { /// /// Determines if two values are equal based on a given tolerance. /// /// The to compare against. /// The to compare with. /// The tolerance in which the two values can be within to be considered equal. /// if the two values are considered equal. public static bool ApproxEquals(this Quaternion a, Quaternion b, float tolerance = float.Epsilon) { return a.x.ApproxEquals(b.x, tolerance) && a.y.ApproxEquals(b.y, tolerance) && a.z.ApproxEquals(b.z, tolerance) && a.w.ApproxEquals(b.w, tolerance); } /// /// Gradually changes a towards a desired goal over time. /// /// The current position. /// The position we are trying to reach. /// The current rotational derivative, this value is modified by the function every time you call it. /// Approximately the time it will take to reach the target. A smaller value will reach the target faster. /// public static Quaternion SmoothDamp(Quaternion current, Quaternion target, ref Quaternion derivative, float smoothTime) { if (Time.deltaTime < Mathf.Epsilon) { return current; } float signedFlip = Quaternion.Dot(current, target) > 0f ? 1f : -1f; target.x *= signedFlip; target.y *= signedFlip; target.z *= signedFlip; target.w *= signedFlip; Vector4 result = new Vector4( Mathf.SmoothDamp(current.x, target.x, ref derivative.x, smoothTime), Mathf.SmoothDamp(current.y, target.y, ref derivative.y, smoothTime), Mathf.SmoothDamp(current.z, target.z, ref derivative.z, smoothTime), Mathf.SmoothDamp(current.w, target.w, ref derivative.w, smoothTime) ).normalized; Vector4 derivativeError = Vector4.Project(new Vector4(derivative.x, derivative.y, derivative.z, derivative.w), result); derivative.x -= derivativeError.x; derivative.y -= derivativeError.y; derivative.z -= derivativeError.z; derivative.w -= derivativeError.w; return new Quaternion(result.x, result.y, result.z, result.w); } } }