/Frog_Fight_Club/How To Dematerialize Completely/Assets/Scripts/AdjustmentScripts/Math/UtilsMathFunc/MathUtils.cs

https://bitbucket.org/yamasakai/frog-fight-club · C# · 279 lines · 193 code · 56 blank · 30 comment · 15 complexity · 6c0d2609d0de1e53ec3e68b4146dbf8b MD5 · raw file

  1. using UnityEngine;
  2. using System;
  3. public class MathUtils
  4. {
  5. public static float CompareEpsilon = 0.00001f;
  6. public static float ExponentialEase(float easeSpeed, float start, float end, float dt)
  7. {
  8. float diff = end - start;
  9. diff *= Mathf.Clamp(dt * easeSpeed, 0.0f, 1.0f);
  10. return diff + start;
  11. }
  12. public static Vector3 ExponentialEase(float easeSpeed, Vector3 start, Vector3 end, float dt)
  13. {
  14. Vector3 diff = end - start;
  15. diff *= Mathf.Clamp(dt * easeSpeed, 0.0f, 1.0f);
  16. return diff + start;
  17. }
  18. public static float CalcRotationDegs(float x, float y)
  19. {
  20. return Mathf.Atan2(y, x) * Mathf.Rad2Deg;
  21. }
  22. public static bool AlmostEquals(float v1, float v2, float epsilon)
  23. {
  24. return Mathf.Abs(v2 - v1) <= epsilon;
  25. }
  26. public static bool AlmostEquals(float v1, float v2)
  27. {
  28. return AlmostEquals(v1, v2, CompareEpsilon);
  29. }
  30. public static Vector2 RandomUnitVector2()
  31. {
  32. float angleRadians = UnityEngine.Random.Range(0.0f, 2.0f * Mathf.PI);
  33. Vector2 unitVector = new Vector2(
  34. Mathf.Cos(angleRadians),
  35. Mathf.Sin(angleRadians)
  36. );
  37. return unitVector;
  38. }
  39. public static Vector3 ReflectIfAgainstNormal(Vector3 vec, Vector3 normal)
  40. {
  41. //If the move direction is going back into the wall reflect the movement away from the wall
  42. float amountAlongNormal = Vector3.Dot(vec, normal);
  43. //If this value is negative it means it's going in the opposite direction of the normal. This means we
  44. //need to reflect it.
  45. if (amountAlongNormal < 0.0f)
  46. {
  47. //Calculate the projection onto the normal
  48. Vector3 directionAlongNormal = normal * amountAlongNormal / normal.sqrMagnitude;
  49. //Subtract the projection once to remove the movement into the wall, and another time to make it move
  50. //away from the wall the same amount. (this adds up to subtracting twice the projection)
  51. vec -= directionAlongNormal * 2.0f;
  52. }
  53. return vec;
  54. }
  55. //This will get the closest point on a sphere.
  56. public static Vector3 GetClosestPtOnSphere(
  57. Vector3 samplePt,
  58. Vector3 sphereCenter,
  59. float sphereRadius
  60. )
  61. {
  62. //Calculate the projection direction to the sample point
  63. Vector3 displacementDir = samplePt - sphereCenter;
  64. float distToSphere = displacementDir.magnitude;
  65. if (distToSphere > 0.0f)
  66. {
  67. displacementDir /= distToSphere;
  68. }
  69. else
  70. {
  71. displacementDir.Set(1.0f, 0.0f, 0.0f);
  72. }
  73. //The closest point on the capsule will be from the closest line segment point, in the direction
  74. //of the sample point, at a distance of the capsule radius.
  75. return sphereCenter + displacementDir * sphereRadius;
  76. }
  77. //This will get the closest point on a capsule.
  78. public static Vector3 GetClosestPtOnCapsule(
  79. Vector3 samplePt,
  80. Vector3 capsuleCenter,
  81. float capsuleHeight,
  82. float capsuleRadius
  83. )
  84. {
  85. //Calculating the length of the line segment part of the capsule
  86. float lineSegmentLength = capsuleHeight - 2.0f * capsuleRadius;
  87. //if the linesegment lenght is less than or equal to zero just treat it like a sphere
  88. if (lineSegmentLength <= 0.0f)
  89. {
  90. return GetClosestPtOnSphere(samplePt, capsuleCenter, capsuleRadius);
  91. }
  92. //Calculate the line segment that goes along the capsules "Height"
  93. Vector3 lineSegPt1 = capsuleCenter;
  94. Vector3 lineSegPt2 = capsuleCenter;
  95. lineSegPt1.y += lineSegmentLength * 0.5f;
  96. lineSegPt2.y -= lineSegmentLength * 0.5f;
  97. Vector3 lineSegPtDiff = lineSegPt2 - lineSegPt1;
  98. //This formula will give the projected percent along the line segment.
  99. //If the number is between 0 and 1 the point is on the line segment, otherwise it will be
  100. //a point collinear to the line segment. Because of this we need to clamp the value bettween 0
  101. //and 1
  102. float sampleProjectedT = Vector3.Dot(lineSegPtDiff, samplePt - lineSegPt1) / lineSegPtDiff.sqrMagnitude;
  103. sampleProjectedT = Mathf.Clamp01(sampleProjectedT);
  104. //Calculate the closest pt on the line segment to our sample point. This is based on the
  105. //projected percent we calculated above.
  106. Vector3 closestLineSegPt = lineSegPtDiff * sampleProjectedT + lineSegPt1;
  107. //Calculate the projection direction to the sample point
  108. Vector3 displacementDir = samplePt - closestLineSegPt;
  109. float sampleLineSegDist = displacementDir.magnitude;
  110. if (sampleLineSegDist > 0.0f)
  111. {
  112. displacementDir /= sampleLineSegDist;
  113. }
  114. else
  115. {
  116. displacementDir.Set(1.0f, 0.0f, 0.0f);
  117. }
  118. //The closest point on the capsule will be from the closest line segment point, in the direction
  119. //of the sample point, at a distance of the capsule radius.
  120. return closestLineSegPt + displacementDir * capsuleRadius;
  121. }
  122. public static float CalcSpringForce(
  123. float currentLength,
  124. float restLength,
  125. float minLength,
  126. float maxLength,
  127. Vector3 dir,
  128. Vector3 velocity,
  129. float maxForce,
  130. float damping
  131. )
  132. {
  133. float forceAmount = maxForce * (currentLength - restLength) / (maxLength - minLength);
  134. float dampingAmount = damping * Vector3.Dot(dir, velocity);
  135. return Mathf.Max(0.0f, forceAmount - dampingAmount);
  136. }
  137. public static Vector3 ClampToCylinder(
  138. Vector3 position,
  139. Vector3 cylinderCenter,
  140. float cylinderRadius,
  141. float cylinderHeight
  142. )
  143. {
  144. //Horizontal Clamping
  145. Vector3 horizOffset = position - cylinderCenter;
  146. horizOffset.y = 0.0f;
  147. float horizDist = horizOffset.magnitude;
  148. if (horizDist > cylinderRadius)
  149. {
  150. horizOffset *= cylinderRadius / horizDist;
  151. position.x = cylinderCenter.x + horizOffset.x;
  152. position.z = cylinderCenter.z + horizOffset.z;
  153. }
  154. //VerticalClamping
  155. float halfHeight = cylinderHeight * 0.5f;
  156. float playerVertOffset = position.y - cylinderCenter.y;
  157. if (playerVertOffset > halfHeight)
  158. {
  159. position.y = cylinderCenter.y + halfHeight;
  160. }
  161. else if (playerVertOffset < -halfHeight)
  162. {
  163. position.y = cylinderCenter.y - halfHeight;
  164. }
  165. return position;
  166. }
  167. public static Vector3 ClampToCylinder(
  168. Vector3 position,
  169. Vector3 cylinderCenter,
  170. float cylinderMinRadius,
  171. float cylinderMaxRadius,
  172. float cylinderHeight
  173. )
  174. {
  175. //Horizontal Clamping
  176. Vector3 horizOffset = position - cylinderCenter;
  177. horizOffset.y = 0.0f;
  178. float horizDist = horizOffset.magnitude;
  179. if (horizDist > cylinderMaxRadius)
  180. {
  181. horizOffset *= cylinderMaxRadius / horizDist;
  182. position.x = cylinderCenter.x + horizOffset.x;
  183. position.z = cylinderCenter.z + horizOffset.z;
  184. }
  185. else if (horizDist < cylinderMinRadius)
  186. {
  187. if (horizDist > 0.0f)
  188. {
  189. horizOffset *= cylinderMinRadius / horizDist;
  190. position.x = cylinderCenter.x + horizOffset.x;
  191. position.z = cylinderCenter.z + horizOffset.z;
  192. }
  193. else
  194. {
  195. //The direction to push the position is undefined here, so we are just choosing
  196. //an arbitrary offset from the center.
  197. position.x = cylinderCenter.x + cylinderMinRadius;
  198. position.z = cylinderCenter.z;
  199. }
  200. }
  201. //VerticalClamping
  202. float halfHeight = cylinderHeight * 0.5f;
  203. float playerVertOffset = position.y - cylinderCenter.y;
  204. if (playerVertOffset > halfHeight)
  205. {
  206. position.y = cylinderCenter.y + halfHeight;
  207. }
  208. else if (playerVertOffset < -halfHeight)
  209. {
  210. position.y = cylinderCenter.y - halfHeight;
  211. }
  212. return position;
  213. }
  214. //This formula was taken from here: http://en.wikipedia.org/wiki/Spherical_cap
  215. public static float CalcSphereCapVolume(float sphereRadius, float capHeight)
  216. {
  217. return (Mathf.PI * capHeight * capHeight / 3) * (3 * sphereRadius - capHeight);
  218. }
  219. public static float CalcSphereVolume(float sphereRadius)
  220. {
  221. return (Mathf.PI * 4.0f / 3.0f) * sphereRadius * sphereRadius * sphereRadius;
  222. }
  223. }