Sphere.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. namespace O3DWB
  5. {
  6. public struct Sphere
  7. {
  8. #region Private Variables
  9. private float _radius;
  10. private Vector3 _center;
  11. #endregion
  12. #region Constructors
  13. public Sphere(Vector3 center)
  14. {
  15. _radius = 1.0f;
  16. _center = center;
  17. }
  18. public Sphere(float radius)
  19. {
  20. _radius = radius;
  21. _center = Vector3.zero;
  22. }
  23. public Sphere(Vector3 center, float radius)
  24. {
  25. _radius = radius;
  26. _center = center;
  27. }
  28. public Sphere(Sphere source)
  29. {
  30. _radius = source._radius;
  31. _center = source._center;
  32. }
  33. #endregion
  34. #region Public Properties
  35. public float Radius { get { return _radius; } set { _radius = value; } }
  36. public Vector3 Center { get { return _center; } set { _center = value; } }
  37. #endregion
  38. #region Public Methods
  39. public bool Raycast(Ray ray)
  40. {
  41. float t;
  42. return Raycast(ray, out t);
  43. }
  44. public bool Raycast(Ray ray, out float t)
  45. {
  46. t = 0.0f;
  47. // Calculate the coefficients of the quadratic equation
  48. Vector3 sphereCenterToRayOrigin = ray.origin - _center;
  49. float a = Vector3.SqrMagnitude(ray.direction);
  50. float b = 2.0f * Vector3.Dot(ray.direction, sphereCenterToRayOrigin);
  51. float c = Vector3.SqrMagnitude(sphereCenterToRayOrigin) - _radius * _radius;
  52. // If we have a solution to the equation, the ray most likely intersects the sphere.
  53. float t1, t2;
  54. if (Equation.SolveQuadratic(a, b, c, out t1, out t2))
  55. {
  56. // Make sure the ray doesn't intersect the sphere only from behind
  57. if (t1 < 0.0f && t2 < 0.0f) return false;
  58. // Make sure we are using the smallest positive t value
  59. if (t1 < 0.0f)
  60. {
  61. float temp = t1;
  62. t1 = t2;
  63. t2 = temp;
  64. }
  65. t = t1;
  66. return true;
  67. }
  68. // If we reach this point it means the ray does not intersect the sphere in any way
  69. return false;
  70. }
  71. public float GetDistanceBetweenCenters(Sphere sphere)
  72. {
  73. return (_center - sphere.Center).magnitude;
  74. }
  75. public float GetDistanceBetweenCentersSq(Sphere sphere)
  76. {
  77. return (Center - sphere.Center).sqrMagnitude;
  78. }
  79. public bool FullyOverlaps(Sphere sphere)
  80. {
  81. return GetDistanceBetweenCenters(sphere) + sphere.Radius <= _radius;
  82. }
  83. public bool OverlapsFullyOrPartially(Sphere sphere)
  84. {
  85. float distanceBetweenCenters = GetDistanceBetweenCenters(sphere);
  86. // Fully?
  87. if (distanceBetweenCenters + sphere.Radius <= _radius) return true;
  88. // Partially?
  89. return distanceBetweenCenters - sphere.Radius <= _radius;
  90. }
  91. public bool OverlapsFullyOrPartially(OrientedBox orientedBox)
  92. {
  93. Vector3 closestPointToSphereCenter = orientedBox.GetClosestPointToPoint(_center);
  94. return (closestPointToSphereCenter - _center).sqrMagnitude <= _radius * _radius;
  95. }
  96. public Sphere Encapsulate(Sphere sphere)
  97. {
  98. float distanceBetweenCenters = GetDistanceBetweenCenters(sphere);
  99. float newDiameter = distanceBetweenCenters + _radius + sphere.Radius;
  100. float newRadius = newDiameter * 0.5f;
  101. Vector3 fromThisToOther = sphere.Center - Center;
  102. fromThisToOther.Normalize();
  103. Vector3 newCenter = Center - fromThisToOther * _radius + fromThisToOther * newRadius;
  104. return new Sphere(newCenter, newRadius);
  105. }
  106. #endregion
  107. }
  108. }
  109. #endif