BsConvexVolume.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsConvexVolume.h"
  4. #include "BsAABox.h"
  5. #include "BsSphere.h"
  6. #include "BsPlane.h"
  7. #include "BsMath.h"
  8. namespace bs
  9. {
  10. /** Clip planes that form the camera frustum (visible area). */
  11. enum FrustumPlane
  12. {
  13. FRUSTUM_PLANE_NEAR = 0,
  14. FRUSTUM_PLANE_FAR = 1,
  15. FRUSTUM_PLANE_LEFT = 2,
  16. FRUSTUM_PLANE_RIGHT = 3,
  17. FRUSTUM_PLANE_TOP = 4,
  18. FRUSTUM_PLANE_BOTTOM = 5
  19. };
  20. ConvexVolume::ConvexVolume(const Vector<Plane>& planes)
  21. :mPlanes(planes)
  22. { }
  23. ConvexVolume::ConvexVolume(const Matrix4& projectionMatrix)
  24. {
  25. mPlanes.resize(6);
  26. const Matrix4& proj = projectionMatrix;
  27. mPlanes[FRUSTUM_PLANE_LEFT].normal.x = proj[3][0] + proj[0][0];
  28. mPlanes[FRUSTUM_PLANE_LEFT].normal.y = proj[3][1] + proj[0][1];
  29. mPlanes[FRUSTUM_PLANE_LEFT].normal.z = proj[3][2] + proj[0][2];
  30. mPlanes[FRUSTUM_PLANE_LEFT].d = proj[3][3] + proj[0][3];
  31. mPlanes[FRUSTUM_PLANE_RIGHT].normal.x = proj[3][0] - proj[0][0];
  32. mPlanes[FRUSTUM_PLANE_RIGHT].normal.y = proj[3][1] - proj[0][1];
  33. mPlanes[FRUSTUM_PLANE_RIGHT].normal.z = proj[3][2] - proj[0][2];
  34. mPlanes[FRUSTUM_PLANE_RIGHT].d = proj[3][3] - proj[0][3];
  35. mPlanes[FRUSTUM_PLANE_TOP].normal.x = proj[3][0] - proj[1][0];
  36. mPlanes[FRUSTUM_PLANE_TOP].normal.y = proj[3][1] - proj[1][1];
  37. mPlanes[FRUSTUM_PLANE_TOP].normal.z = proj[3][2] - proj[1][2];
  38. mPlanes[FRUSTUM_PLANE_TOP].d = proj[3][3] - proj[1][3];
  39. mPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = proj[3][0] + proj[1][0];
  40. mPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = proj[3][1] + proj[1][1];
  41. mPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = proj[3][2] + proj[1][2];
  42. mPlanes[FRUSTUM_PLANE_BOTTOM].d = proj[3][3] + proj[1][3];
  43. mPlanes[FRUSTUM_PLANE_NEAR].normal.x = proj[3][0] + proj[2][0];
  44. mPlanes[FRUSTUM_PLANE_NEAR].normal.y = proj[3][1] + proj[2][1];
  45. mPlanes[FRUSTUM_PLANE_NEAR].normal.z = proj[3][2] + proj[2][2];
  46. mPlanes[FRUSTUM_PLANE_NEAR].d = proj[3][3] + proj[2][3];
  47. mPlanes[FRUSTUM_PLANE_FAR].normal.x = proj[3][0] - proj[2][0];
  48. mPlanes[FRUSTUM_PLANE_FAR].normal.y = proj[3][1] - proj[2][1];
  49. mPlanes[FRUSTUM_PLANE_FAR].normal.z = proj[3][2] - proj[2][2];
  50. mPlanes[FRUSTUM_PLANE_FAR].d = proj[3][3] - proj[2][3];
  51. for (UINT32 i = 0; i < 6; i++)
  52. {
  53. float length = mPlanes[i].normal.normalize();
  54. mPlanes[i].d /= -length;
  55. }
  56. }
  57. bool ConvexVolume::intersects(const AABox& box) const
  58. {
  59. Vector3 center = box.getCenter();
  60. Vector3 extents = box.getHalfSize();
  61. Vector3 absExtents(Math::abs(extents.x), Math::abs(extents.y), Math::abs(extents.z));
  62. for (auto& plane : mPlanes)
  63. {
  64. float dist = center.dot(plane.normal) - plane.d;
  65. float effectiveRadius = absExtents.x * Math::abs(plane.normal.x);
  66. effectiveRadius += absExtents.y * Math::abs(plane.normal.y);
  67. effectiveRadius += absExtents.z * Math::abs(plane.normal.z);
  68. if (dist < -effectiveRadius)
  69. return false;
  70. }
  71. return true;
  72. }
  73. bool ConvexVolume::intersects(const Sphere& sphere) const
  74. {
  75. Vector3 center = sphere.getCenter();
  76. float radius = sphere.getRadius();
  77. for (auto& plane : mPlanes)
  78. {
  79. float dist = center.dot(plane.normal) - plane.d;
  80. if (dist < -radius)
  81. return false;
  82. }
  83. return true;
  84. }
  85. }