namespace UnityEngine.Animations.Rigging { /// /// Supplementary functions for Quaternion. /// public static class QuaternionExt { const float k_FloatMin = 1e-10f; /// Zero quaternion. All quaternion channels are set to zero. public static readonly Quaternion zero = new Quaternion(0f, 0f, 0f, 0f); /// /// Calculates a Quaternion rotation of one vector to another. /// /// Starting vector. /// Destination vector. /// Quaternion rotation. public static Quaternion FromToRotation(Vector3 from, Vector3 to) { float theta = Vector3.Dot(from.normalized, to.normalized); if (theta >= 1f) return Quaternion.identity; if (theta <= -1f) { Vector3 axis = Vector3.Cross(from, Vector3.right); if (axis.sqrMagnitude == 0f) axis = Vector3.Cross(from, Vector3.up); return Quaternion.AngleAxis(180f, axis); } return Quaternion.AngleAxis(Mathf.Acos(theta) * Mathf.Rad2Deg, Vector3.Cross(from, to).normalized); } /// /// Adds two quaternion. /// /// Quaternion value. /// Quaternion value. /// Added Quaternion. public static Quaternion Add(Quaternion rhs, Quaternion lhs) { float sign = Mathf.Sign(Quaternion.Dot(rhs, lhs)); return new Quaternion(rhs.x + sign * lhs.x, rhs.y + sign * lhs.y, rhs.z + sign * lhs.z, rhs.w + sign * lhs.w); } /// /// Multiplies all Quaternion channels by a scale value. /// /// Quaternion value. /// Scale value. /// Scaled Quaternion. public static Quaternion Scale(Quaternion q, float scale) { return new Quaternion(q.x * scale, q.y * scale, q.z * scale, q.w * scale); } /// /// Normalizes a Quaternion. Returns identity if normalized Quaternion is not finite. /// /// Quaternion value. /// Normalized Quaternion. public static Quaternion NormalizeSafe(Quaternion q) { float dot = Quaternion.Dot(q, q); if (dot > k_FloatMin) { float rsqrt = 1.0f / Mathf.Sqrt(dot); return new Quaternion(q.x * rsqrt, q.y * rsqrt, q.z * rsqrt, q.w * rsqrt); } return Quaternion.identity; } } }