MathUtility.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using System;
  2. using UnityEngine;
  3. namespace UnityEditor.U2D.Animation
  4. {
  5. internal static class MathUtility
  6. {
  7. public static float DistanceToSegmentClamp(Vector3 p, Vector3 p1, Vector3 p2)
  8. {
  9. float l2 = (p2 - p1).sqrMagnitude; // i.e. |b-a|^2 - avoid a sqrt
  10. if (l2 == 0.0)
  11. return float.MaxValue; // a == b case
  12. float t = Vector3.Dot(p - p1, p2 - p1) / l2;
  13. if (t < 0.0)
  14. return float.MaxValue; // Beyond the 'a' end of the segment
  15. if (t > 1.0)
  16. return float.MaxValue; // Beyond the 'b' end of the segment
  17. Vector3 projection = p1 + t * (p2 - p1); // Projection falls on the segment
  18. return (p - projection).magnitude;
  19. }
  20. public static Vector2 ClampPositionToRect(Vector2 position, Rect rect)
  21. {
  22. return new Vector2(Mathf.Clamp(position.x, rect.xMin, rect.xMax), Mathf.Clamp(position.y, rect.yMin, rect.yMax));
  23. }
  24. public static Vector2 MoveRectInsideFrame(Rect rect, Rect frame, Vector2 delta)
  25. {
  26. if (frame.size.x <= rect.size.x)
  27. delta.x = 0f;
  28. if (frame.size.y <= rect.size.y)
  29. delta.y = 0f;
  30. Vector2 min = rect.min + delta;
  31. Vector2 max = rect.max + delta;
  32. Vector2 size = rect.size;
  33. Vector2 position = rect.position;
  34. max.x = Mathf.Clamp(max.x, frame.min.x, frame.max.x);
  35. max.y = Mathf.Clamp(max.y, frame.min.y, frame.max.y);
  36. min = max - size;
  37. min.x = Mathf.Clamp(min.x, frame.min.x, frame.max.x);
  38. min.y = Mathf.Clamp(min.y, frame.min.y, frame.max.y);
  39. max = min + size;
  40. rect.min = min;
  41. rect.max = max;
  42. delta = rect.position - position;
  43. return delta;
  44. }
  45. public static bool SegmentIntersection(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3, ref Vector2 point)
  46. {
  47. Vector2 s1 = p1 - p0;
  48. Vector2 s2 = p3 - p2;
  49. float s, t, determinant;
  50. determinant = (s1.x * s2.y - s2.x * s1.y);
  51. if (Mathf.Approximately(determinant, 0f))
  52. return false;
  53. s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / determinant;
  54. t = (s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / determinant;
  55. if (s >= 0f && s <= 1f && t >= 0f && t <= 1f)
  56. {
  57. point = p0 + (t * s1);
  58. return true;
  59. }
  60. return false;
  61. }
  62. //https://gamedev.stackexchange.com/a/49370
  63. public static void Barycentric(Vector2 p, Vector2 a, Vector2 b, Vector2 c, out Vector3 coords)
  64. {
  65. Vector2 v0 = b - a, v1 = c - a, v2 = p - a;
  66. float d00 = Vector2.Dot(v0, v0);
  67. float d01 = Vector2.Dot(v0, v1);
  68. float d11 = Vector2.Dot(v1, v1);
  69. float d20 = Vector2.Dot(v2, v0);
  70. float d21 = Vector2.Dot(v2, v1);
  71. float invDenom = 1f / (d00 * d11 - d01 * d01);
  72. coords.y = (d11 * d20 - d01 * d21) * invDenom;
  73. coords.z = (d00 * d21 - d01 * d20) * invDenom;
  74. coords.x = 1f - coords.y - coords.z;
  75. }
  76. public static Quaternion NormalizeQuaternion(Quaternion q)
  77. {
  78. Vector4 v = new Vector4(q.x, q.y, q.z, q.w).normalized;
  79. return new Quaternion(v.x, v.y, v.z, v.w);
  80. }
  81. //From: https://answers.unity.com/questions/861719/a-fast-triangle-triangle-intersection-algorithm-fo.html
  82. public static bool Intersect(Vector3 p1, Vector3 p2, Vector3 p3, Ray ray)
  83. {
  84. Vector3 e1, e2;
  85. Vector3 p, q, t;
  86. float det, invDet, u, v;
  87. e1 = p2 - p1;
  88. e2 = p3 - p1;
  89. p = Vector3.Cross(ray.direction, e2);
  90. det = Vector3.Dot(e1, p);
  91. if (Mathf.Approximately(det, 0f))
  92. return false;
  93. invDet = 1.0f / det;
  94. t = ray.origin - p1;
  95. u = Vector3.Dot(t, p) * invDet;
  96. if (u < 0 || u > 1)
  97. return false;
  98. q = Vector3.Cross(t, e1);
  99. v = Vector3.Dot(ray.direction, q) * invDet;
  100. if (v < 0 || u + v > 1)
  101. return false;
  102. if ((Vector3.Dot(e2, q) * invDet) > 0f)
  103. return true;
  104. return false;
  105. }
  106. }
  107. }