Sphere.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Math/Vector3.h"
  5. namespace Urho3D
  6. {
  7. class BoundingBox;
  8. class Polyhedron;
  9. class Frustum;
  10. /// %Sphere in three-dimensional space.
  11. /// @allfloats
  12. class URHO3D_API Sphere
  13. {
  14. public:
  15. /// Construct undefined.
  16. Sphere() noexcept :
  17. center_(Vector3::ZERO),
  18. radius_(-M_INFINITY)
  19. {
  20. }
  21. /// Copy-construct from another sphere.
  22. Sphere(const Sphere& sphere) noexcept = default;
  23. /// Construct from center and radius.
  24. Sphere(const Vector3& center, float radius) noexcept :
  25. center_(center),
  26. radius_(radius)
  27. {
  28. }
  29. /// Construct from an array of vertices.
  30. Sphere(const Vector3* vertices, i32 count) noexcept
  31. {
  32. Define(vertices, count);
  33. }
  34. /// Construct from a bounding box.
  35. explicit Sphere(const BoundingBox& box) noexcept
  36. {
  37. Define(box);
  38. }
  39. /// Construct from a frustum.
  40. explicit Sphere(const Frustum& frustum) noexcept
  41. {
  42. Define(frustum);
  43. }
  44. /// Construct from a polyhedron.
  45. explicit Sphere(const Polyhedron& poly) noexcept
  46. {
  47. Define(poly);
  48. }
  49. /// Assign from another sphere.
  50. Sphere& operator =(const Sphere& rhs) noexcept = default;
  51. /// Test for equality with another sphere.
  52. bool operator ==(const Sphere& rhs) const { return center_ == rhs.center_ && radius_ == rhs.radius_; }
  53. /// Test for inequality with another sphere.
  54. bool operator !=(const Sphere& rhs) const { return center_ != rhs.center_ || radius_ != rhs.radius_; }
  55. /// Define from another sphere.
  56. void Define(const Sphere& sphere)
  57. {
  58. Define(sphere.center_, sphere.radius_);
  59. }
  60. /// Define from center and radius.
  61. void Define(const Vector3& center, float radius)
  62. {
  63. center_ = center;
  64. radius_ = radius;
  65. }
  66. /// Define from an array of vertices.
  67. void Define(const Vector3* vertices, i32 count);
  68. /// Define from a bounding box.
  69. void Define(const BoundingBox& box);
  70. /// Define from a frustum.
  71. void Define(const Frustum& frustum);
  72. /// Define from a polyhedron.
  73. void Define(const Polyhedron& poly);
  74. /// Merge a point.
  75. void Merge(const Vector3& point)
  76. {
  77. if (radius_ < 0.0f)
  78. {
  79. center_ = point;
  80. radius_ = 0.0f;
  81. return;
  82. }
  83. Vector3 offset = point - center_;
  84. float dist = offset.Length();
  85. if (dist > radius_)
  86. {
  87. float half = (dist - radius_) * 0.5f;
  88. radius_ += half;
  89. center_ += (half / dist) * offset;
  90. }
  91. }
  92. /// Merge an array of vertices.
  93. void Merge(const Vector3* vertices, i32 count);
  94. /// Merge a bounding box.
  95. void Merge(const BoundingBox& box);
  96. /// Merge a frustum.
  97. void Merge(const Frustum& frustum);
  98. /// Merge a polyhedron.
  99. void Merge(const Polyhedron& poly);
  100. /// Merge a sphere.
  101. void Merge(const Sphere& sphere);
  102. /// Clear to undefined state.
  103. void Clear()
  104. {
  105. center_ = Vector3::ZERO;
  106. radius_ = -M_INFINITY;
  107. }
  108. /// Return true if this sphere is defined via a previous call to Define() or Merge().
  109. bool Defined() const
  110. {
  111. return radius_ >= 0.0f;
  112. }
  113. /// Test if a point is inside.
  114. Intersection IsInside(const Vector3& point) const
  115. {
  116. float distSquared = (point - center_).LengthSquared();
  117. if (distSquared < radius_ * radius_)
  118. return INSIDE;
  119. else
  120. return OUTSIDE;
  121. }
  122. /// Test if another sphere is inside, outside or intersects.
  123. Intersection IsInside(const Sphere& sphere) const
  124. {
  125. float dist = (sphere.center_ - center_).Length();
  126. if (dist >= sphere.radius_ + radius_)
  127. return OUTSIDE;
  128. else if (dist + sphere.radius_ < radius_)
  129. return INSIDE;
  130. else
  131. return INTERSECTS;
  132. }
  133. /// Test if another sphere is (partially) inside or outside.
  134. Intersection IsInsideFast(const Sphere& sphere) const
  135. {
  136. float distSquared = (sphere.center_ - center_).LengthSquared();
  137. float combined = sphere.radius_ + radius_;
  138. if (distSquared >= combined * combined)
  139. return OUTSIDE;
  140. else
  141. return INSIDE;
  142. }
  143. /// Test if a bounding box is inside, outside or intersects.
  144. Intersection IsInside(const BoundingBox& box) const;
  145. /// Test if a bounding box is (partially) inside or outside.
  146. Intersection IsInsideFast(const BoundingBox& box) const;
  147. /// Return distance of a point to the surface, or 0 if inside.
  148. float Distance(const Vector3& point) const { return Max((point - center_).Length() - radius_, 0.0f); }
  149. /// Return point on the sphere relative to sphere position.
  150. Vector3 GetLocalPoint(float theta, float phi) const;
  151. /// Return point on the sphere.
  152. Vector3 GetPoint(float theta, float phi) const { return center_ + GetLocalPoint(theta, phi); }
  153. /// Sphere center.
  154. Vector3 center_;
  155. /// Sphere radius.
  156. float radius_{};
  157. };
  158. }