Frustum.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //
  2. // Copyright (c) 2008-2014 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "BoundingBox.h"
  24. #include "Matrix3x4.h"
  25. #include "Plane.h"
  26. #include "Rect.h"
  27. #include "Sphere.h"
  28. namespace Urho3D
  29. {
  30. /// Frustum planes.
  31. enum FrustumPlane
  32. {
  33. PLANE_NEAR = 0,
  34. PLANE_LEFT,
  35. PLANE_RIGHT,
  36. PLANE_UP,
  37. PLANE_DOWN,
  38. PLANE_FAR,
  39. };
  40. static const unsigned NUM_FRUSTUM_PLANES = 6;
  41. static const unsigned NUM_FRUSTUM_VERTICES = 8;
  42. /// Convex constructed of 6 planes.
  43. class URHO3D_API Frustum
  44. {
  45. public:
  46. /// Construct a degenerate frustum with all points at origin.
  47. Frustum();
  48. /// Copy-construct from another frustum.
  49. Frustum(const Frustum& frustum);
  50. /// Assign from another frustum.
  51. Frustum& operator = (const Frustum& rhs);
  52. /// Define with projection parameters and a transform matrix.
  53. void Define(float fov, float aspectRatio, float zoom, float nearZ, float farZ, const Matrix3x4& transform = Matrix3x4::IDENTITY);
  54. /// Define with near and far dimension vectors and a transform matrix.
  55. void Define(const Vector3& near, const Vector3& far, const Matrix3x4& transform = Matrix3x4::IDENTITY);
  56. /// Define with a bounding box and a transform matrix.
  57. void Define(const BoundingBox& box, const Matrix3x4& transform = Matrix3x4::IDENTITY);
  58. /// Define with orthographic projection parameters and a transform matrix.
  59. void DefineOrtho(float orthoSize, float aspectRatio, float zoom, float nearZ, float farZ, const Matrix3x4& transform = Matrix3x4::IDENTITY);
  60. /// Transform by a 3x3 matrix.
  61. void Transform(const Matrix3& transform);
  62. /// Transform by a 3x4 matrix.
  63. void Transform(const Matrix3x4& transform);
  64. /// Test if a point is inside or outside.
  65. Intersection IsInside(const Vector3& point) const
  66. {
  67. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  68. {
  69. if (planes_[i].Distance(point) < 0.0f)
  70. return OUTSIDE;
  71. }
  72. return INSIDE;
  73. }
  74. /// Test if a sphere is inside, outside or intersects.
  75. Intersection IsInside(const Sphere& sphere) const
  76. {
  77. bool allInside = true;
  78. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  79. {
  80. float dist = planes_[i].Distance(sphere.center_);
  81. if (dist < -sphere.radius_)
  82. return OUTSIDE;
  83. else if (dist < sphere.radius_)
  84. allInside = false;
  85. }
  86. return allInside ? INSIDE : INTERSECTS;
  87. }
  88. /// Test if a sphere if (partially) inside or outside.
  89. Intersection IsInsideFast(const Sphere& sphere) const
  90. {
  91. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  92. {
  93. if (planes_[i].Distance(sphere.center_) < -sphere.radius_)
  94. return OUTSIDE;
  95. }
  96. return INSIDE;
  97. }
  98. /// Test if a bounding box is inside, outside or intersects.
  99. Intersection IsInside(const BoundingBox& box) const
  100. {
  101. Vector3 center = box.Center();
  102. Vector3 edge = center - box.min_;
  103. bool allInside = true;
  104. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  105. {
  106. const Plane& plane = planes_[i];
  107. float dist = plane.normal_.DotProduct(center) + plane.d_;
  108. float absDist = plane.absNormal_.DotProduct(edge);
  109. if (dist < -absDist)
  110. return OUTSIDE;
  111. else if (dist < absDist)
  112. allInside = false;
  113. }
  114. return allInside ? INSIDE : INTERSECTS;
  115. }
  116. /// Test if a bounding box is (partially) inside or outside.
  117. Intersection IsInsideFast(const BoundingBox& box) const
  118. {
  119. Vector3 center = box.Center();
  120. Vector3 edge = center - box.min_;
  121. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  122. {
  123. const Plane& plane = planes_[i];
  124. float dist = plane.normal_.DotProduct(center) + plane.d_;
  125. float absDist = plane.absNormal_.DotProduct(edge);
  126. if (dist < -absDist)
  127. return OUTSIDE;
  128. }
  129. return INSIDE;
  130. }
  131. /// Return distance of a point to the frustum, or 0 if inside.
  132. float Distance(const Vector3& point) const
  133. {
  134. float distance = 0.0f;
  135. for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
  136. distance = Max(-planes_[i].Distance(point), distance);
  137. return distance;
  138. }
  139. /// Return transformed by a 3x3 matrix.
  140. Frustum Transformed(const Matrix3& transform) const;
  141. /// Return transformed by a 3x4 matrix.
  142. Frustum Transformed(const Matrix3x4& transform) const;
  143. /// Return projected by a 4x4 projection matrix.
  144. Rect Projected(const Matrix4& transform) const;
  145. /// Update the planes. Called internally.
  146. void UpdatePlanes();
  147. /// Frustum planes.
  148. Plane planes_[NUM_FRUSTUM_PLANES];
  149. /// Frustum vertices.
  150. Vector3 vertices_[NUM_FRUSTUM_VERTICES];
  151. };
  152. }