BezierLogic.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //### Bezier Logic
  2. //This is an utilety class for all major calculations related to vectorized bezier curve.
  3. //
  4. //License information: [ASSET STORE TERMS OF SERVICE AND EULA](https://unity3d.com/legal/as_terms)
  5. //
  6. //Developed by [MathArtCode](https://www.assetstore.unity3d.com/en/#!/search/page=1/sortby=popularity/query=publisher:8738) team, 2015
  7. using System;
  8. using System.Linq;
  9. using Assets.Scripts.BezierCurvedParticlesFlow.Interfaces;
  10. using UnityEngine;
  11. namespace Assets.Scripts.BezierCurvedParticlesFlow.Utilities {
  12. [Serializable]
  13. public sealed class BezierLogic : IBezierLogic {
  14. [SerializeField]
  15. private Vector3[] _points;
  16. //All points are handeled inside a single array
  17. //- positioning (end points) have indexes 0, 3, 6, ...
  18. //- angles (control points) have indexes 1,2, 4,5, ...
  19. private Vector3[] Points {
  20. get {
  21. if (_points == null) {
  22. Reset();
  23. }
  24. return _points;
  25. }
  26. }
  27. // Provides ammount of all points (end points + control pouints in AI terminolagy)
  28. public int ControlPointCount {
  29. get { return Points.Length; }
  30. }
  31. // Provides ammount of all curved segments of Bezier curve
  32. private int CurveCount {
  33. get { return (Points.Length - 1)/3; }
  34. }
  35. // Returns a coordinate point relative to curve 'time' where 0 is bezier curve beginning and 1 is end of the bezier curve (length vise)
  36. public Vector3 GetPoint(float t) {
  37. int i;
  38. if (t >= 1f) {
  39. t = 1f;
  40. i = _points.Length - 4;
  41. }
  42. else {
  43. t = Mathf.Clamp01(t)*CurveCount;
  44. i = (int) t;
  45. t -= i;
  46. i *= 3;
  47. }
  48. return GetPoint(_points[i], _points[i + 1], _points[i + 2], _points[i + 3], t);
  49. }
  50. // Returns a velocity point relative to curve 'time' where 0 is bezier curve beginning and 1 is end of the bezier curve (length vise)
  51. public Vector3 GetVelocity(float t) {
  52. int i;
  53. if (t >= 1f) {
  54. t = 1f;
  55. i = _points.Length - 4;
  56. }
  57. else {
  58. t = Mathf.Clamp01(t)*CurveCount;
  59. i = (int) t;
  60. t -= i;
  61. i *= 3;
  62. }
  63. return
  64. GetFirstDerivative(_points[i], _points[i + 1], _points[i + 2], _points[i + 3], t);
  65. }
  66. // Returns a normalized velocity point relative to curve 'time' where 0 is bezier curve beginning and 1 is end of the bezier curve (length vise)
  67. public Vector3 GetDirection(float t) {
  68. return GetVelocity(t).normalized;
  69. }
  70. //### Mathematical core of Bezier Logic
  71. private static Vector3 GetPoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
  72. t = Mathf.Clamp01(t);
  73. var oneMinusT = 1f - t;
  74. return
  75. oneMinusT*oneMinusT*oneMinusT*p0 +
  76. 3f*oneMinusT*oneMinusT*t*p1 +
  77. 3f*oneMinusT*t*t*p2 +
  78. t*t*t*p3;
  79. }
  80. private static Vector3 GetFirstDerivative(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
  81. t = Mathf.Clamp01(t);
  82. var oneMinusT = 1f - t;
  83. return
  84. 3f*oneMinusT*oneMinusT*(p1 - p0) +
  85. 6f*oneMinusT*t*(p2 - p1) +
  86. 3f*t*t*(p3 - p2);
  87. }
  88. //Resets component to its default 2 points (forming a straight line)
  89. public void Reset() {
  90. _points = new[] {
  91. new Vector3(0f, 0f, 0f),
  92. new Vector3(2f, 0f, 0f),
  93. new Vector3(3f, 0f, 0f),
  94. new Vector3(4f, 0f, 0f)
  95. };
  96. }
  97. //Returns a point by its index
  98. //- positioning (end points) have indexes 0, 3, 6, ...
  99. //- angles (control points) have indexes 1,2, 4,5, ...
  100. public Vector3 GetControlPoint(int index) {
  101. return Points[index];
  102. }
  103. //Sets a point value by its index
  104. //- positioning (end points) have indexes 0, 3, 6 ...
  105. //- angles (control points) have indexes 1,2, 4,5, ...
  106. public void SetControlPoint(int index, Vector3 point) {
  107. if (index%3 == 0) {
  108. var delta = point - Points[index];
  109. if (index > 0) {
  110. _points[index - 1] += delta;
  111. }
  112. if (index + 1 < _points.Length) {
  113. _points[index + 1] += delta;
  114. }
  115. }
  116. Points[index] = point;
  117. }
  118. // Adds a position point + 2 angle points
  119. public void AddPoint() {
  120. var length = Points.Length;
  121. var point = _points[length - 1];
  122. var velocity = GetDirection(1f);
  123. Array.Resize(ref _points, length + 3);
  124. length = Points.Length;
  125. point += velocity;
  126. _points[length - 3] = point;
  127. point += velocity;
  128. _points[length - 2] = point;
  129. point += velocity;
  130. _points[length - 1] = point;
  131. }
  132. // Removes a position point + 2 angle points. gets an end point index as an argument
  133. //- positioning (end points) have indexes 0, 3, 6...
  134. public void RemovePoint(int selectedIndex) {
  135. var points = Points.ToList();
  136. if (selectedIndex == _points.Length - 1) {
  137. points.RemoveRange(selectedIndex - 2, 3);
  138. }
  139. else {
  140. points.RemoveRange(selectedIndex - 1, 3);
  141. }
  142. _points = points.ToArray();
  143. }
  144. }
  145. }