Segment3D.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. namespace O3DWB
  4. {
  5. public struct Segment3D
  6. {
  7. #region Private Variables
  8. private Vector3 _startPoint;
  9. private Vector3 _normalizedDirection;
  10. private Vector3 _direction;
  11. private float _length;
  12. private float _sqrLength;
  13. #endregion
  14. #region Public Properties
  15. public Vector3 StartPoint { get { return _startPoint; } }
  16. public Vector3 EndPoint { get { return _startPoint + _normalizedDirection * _length; } }
  17. public Vector3 NormalizedDirection { get { return _normalizedDirection; } }
  18. public Vector3 Direction { get { return _direction; } }
  19. public float Length { get { return _length; } }
  20. public float SqrLength { get { return _sqrLength; } }
  21. public float HalfLength { get { return _length * 0.5f; } }
  22. #endregion
  23. #region Constructors
  24. public Segment3D(Vector3 startPoint, Vector3 endPoint)
  25. {
  26. _startPoint = startPoint;
  27. _direction = endPoint - _startPoint;
  28. _length = _direction.magnitude;
  29. _sqrLength = _direction.sqrMagnitude;
  30. _normalizedDirection = _direction;
  31. _normalizedDirection.Normalize();
  32. }
  33. public Segment3D(Ray3D ray)
  34. {
  35. _startPoint = ray.Origin;
  36. _direction = ray.Direction;
  37. _length = _direction.magnitude;
  38. _sqrLength = _direction.sqrMagnitude;
  39. _normalizedDirection = _direction;
  40. _normalizedDirection.Normalize();
  41. }
  42. #endregion
  43. #region Public Methods
  44. public Vector3 GetRandomPoint()
  45. {
  46. float randomT = UnityEngine.Random.Range(0.0f, 1.0f);
  47. return _startPoint + randomT * _direction;
  48. }
  49. public Vector3 GetPoint(float t)
  50. {
  51. return _startPoint + t * _direction;
  52. }
  53. public bool IsPerpendicualrTo(Segment3D segment)
  54. {
  55. return Direction.IsPerpendicularTo(segment.Direction);
  56. }
  57. public bool IntersectsWith(Segment3D segment)
  58. {
  59. float t1, t2;
  60. return IntersectsWith(segment, out t1, out t2);
  61. }
  62. public bool IntersectsWith(Segment3D segment, out float t1, out float t2)
  63. {
  64. t1 = t2 = 0.0f;
  65. if (_length == 0.0f || segment.Length == 0.0f) return false;
  66. // If the segments are parallel, they don't intersect
  67. if (segment.NormalizedDirection.IsAlignedWith(_normalizedDirection)) return false;
  68. // Check if the 2 segments are coplanar
  69. Vector3 segmentPlaneNormal = Vector3.Cross(segment.NormalizedDirection, _normalizedDirection);
  70. Vector3 fromThisSegmentStartToOtherSegmentStart = segment.StartPoint - _startPoint;
  71. if (!fromThisSegmentStartToOtherSegmentStart.IsPerpendicularTo(segmentPlaneNormal)) return false;
  72. // Build a plane which slices thorough the segment
  73. Vector3 slicingPlaneNormal = Vector3.Cross(segmentPlaneNormal, _normalizedDirection);
  74. slicingPlaneNormal.Normalize();
  75. Plane slicingPlane = new Plane(slicingPlaneNormal, _startPoint);
  76. // Check if the query segment intersects the plane
  77. float t;
  78. Ray3D querySegmentRay = new Ray3D(segment.StartPoint, segment.Direction);
  79. if (querySegmentRay.IntersectsPlane(slicingPlane, out t))
  80. {
  81. // The segment intersect the plane, but we have to ensure that the intersection point lies somewehre along 'this' segment.
  82. Vector3 intersectionPoint = querySegmentRay.Origin + t * querySegmentRay.Direction;
  83. Vector3 toIntersectionPoint = intersectionPoint - _startPoint;
  84. if (Vector3.Dot(toIntersectionPoint, _normalizedDirection) < 0.0f) return false;
  85. if (toIntersectionPoint.sqrMagnitude > _sqrLength) return false;
  86. t1 = toIntersectionPoint.magnitude / _length;
  87. t2 = t;
  88. return true;
  89. }
  90. return false;
  91. }
  92. #endregion
  93. }
  94. }
  95. #endif