// ╔════════════════════════════════════════════════════════════════╗ // ║ Copyright © 2025 NWH Coding d.o.o. All rights reserved. ║ // ║ Licensed under Unity Asset Store Terms of Service: ║ // ║ https://unity.com/legal/as-terms ║ // ║ Use permitted only in compliance with the License. ║ // ║ Distributed "AS IS", without warranty of any kind. ║ // ╚════════════════════════════════════════════════════════════════╝ #region using UnityEngine; #endregion namespace NWH.Common.Utility { /// /// Extension methods for advanced Quaternion operations. /// Provides interpolation methods with control over rotation direction. /// public static class QuaternionExtensions { /// /// Linear interpolation between two quaternions with optional short/long path control. /// Unlike Unity's Quaternion.Lerp, this allows choosing rotation direction. /// /// Starting rotation. /// Target rotation. /// Interpolation factor (0 to 1). /// True for shortest rotation path, false for longest. /// Interpolated quaternion. public static Quaternion Lerp(Quaternion p, Quaternion q, float t, bool shortWay) { if (shortWay) { float dot = Quaternion.Dot(p, q); if (dot < 0.0f) { return Lerp(ScalarMultiply(p, -1.0f), q, t, true); } } Quaternion r = Quaternion.identity; r.x = p.x * (1f - t) + q.x * t; r.y = p.y * (1f - t) + q.y * t; r.z = p.z * (1f - t) + q.z * t; r.w = p.w * (1f - t) + q.w * t; return r; } /// /// Spherical linear interpolation between two quaternions with optional short/long path control. /// Provides smooth rotation interpolation with control over rotation direction. /// /// Starting rotation. /// Target rotation. /// Interpolation factor (0 to 1). /// True for shortest rotation path, false for longest. /// Interpolated quaternion. public static Quaternion Slerp(Quaternion p, Quaternion q, float t, bool shortWay) { float dot = Quaternion.Dot(p, q); if (shortWay) { if (dot < 0.0f) { return Slerp(ScalarMultiply(p, -1.0f), q, t, true); } } float angle = Mathf.Acos(dot); Quaternion first = ScalarMultiply(p, Mathf.Sin((1f - t) * angle)); Quaternion second = ScalarMultiply(q, Mathf.Sin(t * angle)); float division = 1f / Mathf.Sin(angle); return ScalarMultiply(Add(first, second), division); } /// /// Multiplies all components of a quaternion by a scalar value. /// /// Input quaternion. /// Scalar multiplier. /// Scaled quaternion. public static Quaternion ScalarMultiply(Quaternion input, float scalar) { return new Quaternion(input.x * scalar, input.y * scalar, input.z * scalar, input.w * scalar); } /// /// Adds two quaternions component-wise. /// /// First quaternion. /// Second quaternion. /// Component-wise sum. public static Quaternion Add(Quaternion p, Quaternion q) { return new Quaternion(p.x + q.x, p.y + q.y, p.z + q.z, p.w + q.w); } } }