FrustumComponent.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Scene/Components/FrustumComponent.h>
  6. #include <AnKi/Scene/SceneNode.h>
  7. #include <AnKi/Collision/Functions.h>
  8. namespace anki {
  9. ANKI_SCENE_COMPONENT_STATICS(FrustumComponent)
  10. FrustumComponent::FrustumComponent(SceneNode* node)
  11. : SceneComponent(node, getStaticClassId())
  12. , m_node(node)
  13. , m_shapeMarkedForUpdate(true)
  14. , m_trfMarkedForUpdate(true)
  15. {
  16. ANKI_ASSERT(&m_perspective.m_far == &m_ortho.m_far);
  17. ANKI_ASSERT(node);
  18. // Set some default values
  19. setFrustumType(FrustumType::kPerspective);
  20. updateInternal();
  21. }
  22. FrustumComponent::~FrustumComponent()
  23. {
  24. m_coverageBuff.m_depthMap.destroy(m_node->getAllocator());
  25. }
  26. Bool FrustumComponent::updateInternal()
  27. {
  28. ANKI_ASSERT(m_frustumType != FrustumType::kCount);
  29. Bool updated = false;
  30. for(U32 i = kPrevMatrixHistory - 1; i != 0; --i)
  31. {
  32. m_prevViewProjMats[i] = m_prevViewProjMats[i - 1];
  33. m_prevViewMats[i] = m_prevViewMats[i - 1];
  34. m_prevProjMats[i] = m_prevProjMats[i - 1];
  35. }
  36. m_prevViewProjMats[0] = m_viewProjMat;
  37. m_prevViewMats[0] = m_viewMat;
  38. m_prevProjMats[0] = m_projMat;
  39. // Update the shape
  40. if(m_shapeMarkedForUpdate)
  41. {
  42. updated = true;
  43. if(m_frustumType == FrustumType::kPerspective)
  44. {
  45. m_projMat = Mat4::calculatePerspectiveProjectionMatrix(m_perspective.m_fovX, m_perspective.m_fovY,
  46. m_perspective.m_near, m_perspective.m_far);
  47. computeEdgesOfFrustum(m_perspective.m_far, m_perspective.m_fovX, m_perspective.m_fovY,
  48. &m_perspective.m_edgesL[0]);
  49. // Planes
  50. F32 c, s; // cos & sine
  51. sinCos(kPi + m_perspective.m_fovX / 2.0f, s, c);
  52. // right
  53. m_viewPlanesL[FrustumPlaneType::kRight] = Plane(Vec4(c, 0.0f, s, 0.0f), 0.0f);
  54. // left
  55. m_viewPlanesL[FrustumPlaneType::kLeft] = Plane(Vec4(-c, 0.0f, s, 0.0f), 0.0f);
  56. sinCos((kPi + m_perspective.m_fovY) * 0.5f, s, c);
  57. // bottom
  58. m_viewPlanesL[FrustumPlaneType::kBottom] = Plane(Vec4(0.0f, s, c, 0.0f), 0.0f);
  59. // top
  60. m_viewPlanesL[FrustumPlaneType::kTop] = Plane(Vec4(0.0f, -s, c, 0.0f), 0.0f);
  61. // near
  62. m_viewPlanesL[FrustumPlaneType::kNear] = Plane(Vec4(0.0f, 0.0f, -1.0, 0.0f), m_perspective.m_near);
  63. // far
  64. m_viewPlanesL[FrustumPlaneType::kFar] = Plane(Vec4(0.0f, 0.0f, 1.0, 0.0f), -m_perspective.m_far);
  65. }
  66. else
  67. {
  68. m_projMat = Mat4::calculateOrthographicProjectionMatrix(m_ortho.m_right, m_ortho.m_left, m_ortho.m_top,
  69. m_ortho.m_bottom, m_ortho.m_near, m_ortho.m_far);
  70. // OBB
  71. const Vec4 c((m_ortho.m_right + m_ortho.m_left) * 0.5f, (m_ortho.m_top + m_ortho.m_bottom) * 0.5f,
  72. -(m_ortho.m_far + m_ortho.m_near) * 0.5f, 0.0f);
  73. const Vec4 e = Vec4(m_ortho.m_right, m_ortho.m_top, -m_ortho.m_far, 0.0f) - c;
  74. m_ortho.m_obbL = Obb(c, Mat3x4::getIdentity(), e);
  75. // Planes
  76. m_viewPlanesL[FrustumPlaneType::kLeft] = Plane(Vec4(1.0f, 0.0f, 0.0f, 0.0f), m_ortho.m_left);
  77. m_viewPlanesL[FrustumPlaneType::kRight] = Plane(Vec4(-1.0f, 0.0f, 0.0f, 0.0f), -m_ortho.m_right);
  78. m_viewPlanesL[FrustumPlaneType::kNear] = Plane(Vec4(0.0f, 0.0f, -1.0f, 0.0f), m_ortho.m_near);
  79. m_viewPlanesL[FrustumPlaneType::kFar] = Plane(Vec4(0.0f, 0.0f, 1.0f, 0.0f), -m_ortho.m_far);
  80. m_viewPlanesL[FrustumPlaneType::kTop] = Plane(Vec4(0.0f, -1.0f, 0.0f, 0.0f), -m_ortho.m_top);
  81. m_viewPlanesL[FrustumPlaneType::kBottom] = Plane(Vec4(0.0f, 1.0f, 0.0f, 0.0f), m_ortho.m_bottom);
  82. }
  83. }
  84. // Update transform related things
  85. if(m_trfMarkedForUpdate)
  86. {
  87. updated = true;
  88. m_viewMat = Mat3x4(m_trf.getInverse());
  89. }
  90. // Updates that are affected by transform & shape updates
  91. if(updated)
  92. {
  93. m_viewProjMat = m_projMat * Mat4(m_viewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
  94. m_shapeMarkedForUpdate = false;
  95. m_trfMarkedForUpdate = false;
  96. if(m_frustumType == FrustumType::kPerspective)
  97. {
  98. m_perspective.m_edgesW[0] = m_trf.getOrigin();
  99. m_perspective.m_edgesW[1] = m_trf.transform(m_perspective.m_edgesL[0]);
  100. m_perspective.m_edgesW[2] = m_trf.transform(m_perspective.m_edgesL[1]);
  101. m_perspective.m_edgesW[3] = m_trf.transform(m_perspective.m_edgesL[2]);
  102. m_perspective.m_edgesW[4] = m_trf.transform(m_perspective.m_edgesL[3]);
  103. m_perspective.m_hull = ConvexHullShape(&m_perspective.m_edgesW[0], m_perspective.m_edgesW.getSize());
  104. }
  105. else
  106. {
  107. m_ortho.m_obbW = m_ortho.m_obbL.getTransformed(m_trf);
  108. }
  109. for(FrustumPlaneType planeId : EnumIterable<FrustumPlaneType>())
  110. {
  111. m_viewPlanesW[planeId] = m_viewPlanesL[planeId].getTransformed(m_trf);
  112. }
  113. }
  114. return updated;
  115. }
  116. void FrustumComponent::fillCoverageBufferCallback(void* userData, F32* depthValues, U32 width, U32 height)
  117. {
  118. ANKI_ASSERT(userData && depthValues && width > 0 && height > 0);
  119. FrustumComponent& self = *static_cast<FrustumComponent*>(userData);
  120. self.m_coverageBuff.m_depthMap.destroy(self.m_node->getAllocator());
  121. self.m_coverageBuff.m_depthMap.create(self.m_node->getAllocator(), width * height);
  122. memcpy(&self.m_coverageBuff.m_depthMap[0], depthValues, self.m_coverageBuff.m_depthMap.getSizeInBytes());
  123. self.m_coverageBuff.m_depthMapWidth = width;
  124. self.m_coverageBuff.m_depthMapHeight = height;
  125. }
  126. void FrustumComponent::setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag bits)
  127. {
  128. m_flags = FrustumComponentVisibilityTestFlag::NONE;
  129. m_flags |= bits;
  130. #if ANKI_ENABLE_ASSERTIONS
  131. if(!!(m_flags & FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
  132. || !!(m_flags & FrustumComponentVisibilityTestFlag::SHADOW_CASTERS))
  133. {
  134. if((m_flags & FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
  135. == (m_flags & FrustumComponentVisibilityTestFlag::SHADOW_CASTERS))
  136. {
  137. ANKI_ASSERT(0 && "Cannot have them both");
  138. }
  139. }
  140. // TODO
  141. #endif
  142. }
  143. } // end namespace anki