/******************************************************************************/ /* Project - MudBun Publisher - Long Bunny Labs http://LongBunnyLabs.com Author - Ming-Lun "Allen" Chou http://AllenChou.net */ /******************************************************************************/ #if MUDBUN_BURST using Unity.Burst; #endif using UnityEngine; namespace MudBun { public static class VectorUtil { private static Vector3 s_invalid = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); public static Vector3 Invalid => s_invalid; public static bool IsValid(Vector3 v) { return (v - s_invalid).sqrMagnitude > MathUtil.Epsilon; } public static Vector3 Saturate(Vector3 v) { return new Vector3(MathUtil.Saturate(v.x), MathUtil.Saturate(v.y), MathUtil.Saturate(v.z)); } public static Vector3 CompMul(Vector3 a, Vector3 b) { return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z); } public static Vector3 CompDiv(Vector3 a, Vector3 b) { return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z); } public static float MinComp(Vector3 v) { return Mathf.Min(v.x, Mathf.Min(v.y, v.z)); } public static float MaxComp(Vector3 v) { return Mathf.Max(v.x, Mathf.Max(v.y, v.z)); } public static Vector3 Rotate2D(Vector3 v, float deg) { Vector3 results = v; float cos = Mathf.Cos(MathUtil.Deg2Rad * deg); float sin = Mathf.Sin(MathUtil.Deg2Rad * deg); results.x = cos * v.x - sin * v.y; results.y = sin * v.x + cos * v.y; return results; } public static Vector3 NormalizeSafe(Vector3 v, Vector3 fallback, float epsilon = 1e-9f) { return v.sqrMagnitude > epsilon ? v.normalized : fallback; } // Returns a vector orthogonal to given vector. // If the given vector is a unit vector, the returned vector will also be a unit vector. public static Vector3 FindOrthogonal(Vector3 v) { if (v.x >= MathUtil.Sqrt3Inv) return new Vector3(v.y, -v.x, 0.0f); else return new Vector3(0.0f, v.z, -v.y); } // Yields two extra vectors that form an orthogonal basis with the given vector. // If the given vector is a unit vector, the returned vectors will also be unit vectors. public static void FormOrthonormalBasis(Vector3 v, out Vector3 a, out Vector3 b) { a = FindOrthogonal(v).normalized; b = Vector3.Cross(v, a); } public static Vector3 ClampLength(Vector3 v, float minLen, float maxLen) { float lenSqr = v.sqrMagnitude; if (lenSqr < MathUtil.Epsilon) return v; float len = Mathf.Sqrt(lenSqr); return v * (Mathf.Clamp(len, minLen, maxLen) / len); } // Both vectors must be unit vectors. public static Vector3 Slerp(Vector3 a, Vector3 b, float t) { float dot = Vector3.Dot(a, b); if (dot > 0.99999f) { // singularity: two vectors point in the same direction return Vector3.Lerp(a, b, t); } else if (dot < -0.99999f) { // singularity: two vectors point in the opposite direction Vector3 axis = FindOrthogonal(a); return Quaternion.AngleAxis(180.0f * t, axis) * a; } float rad = MathUtil.AcosSafe(dot); return (Mathf.Sin((1.0f - t) * rad) * a + Mathf.Sin(t * rad) * b) / Mathf.Sin(rad); } public static Vector3 BezierQuad(Vector3 a, Vector3 b, Vector3 controlPoint, float t) { return Vector3.Lerp(Vector3.Lerp(a, controlPoint, t), Vector3.Lerp(controlPoint, b, t), t); } public static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) { float tt = t * t; return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * tt + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * tt * t ); } public static Vector3 Abs(Vector3 v) { return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z)); } public static Vector3 Min(Vector3 a, Vector3 b) { return new Vector3(Mathf.Min(a.x, b.x), Mathf.Min(a.y, b.y), Mathf.Min(a.z, b.z)); } public static Vector3 Max(Vector3 a, Vector3 b) { return new Vector3(Mathf.Max(a.x, b.x), Mathf.Max(a.y, b.y), Mathf.Max(a.z, b.z)); } public static float GetComopnent(Vector3 v, int i) { switch (i) { case 0: return v.x; case 1: return v.y; case 2: return v.z; } return float.MinValue; } } }