Frustum.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (C) 2009-present, 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/Frustum.h>
  6. #include <AnKi/Collision/Functions.h>
  7. namespace anki {
  8. Array<Mat3x4, 6> Frustum::m_omnidirectionalRotations = {Mat3x4(Vec3(0.0f), Mat3(Euler(0.0f, -kPi / 2.0f, 0.0f))), // +x
  9. Mat3x4(Vec3(0.0f), Mat3(Euler(0.0f, kPi / 2.0f, 0.0f))), // -x
  10. Mat3x4(Vec3(0.0f), Mat3(Euler(kPi / 2.0f, 0.0f, 0.0f))), // +y
  11. Mat3x4(Vec3(0.0f), Mat3(Euler(-kPi / 2.0f, 0.0f, 0.0f))), // -y
  12. Mat3x4(Vec3(0.0f), Mat3::getIdentity()), // -z
  13. Mat3x4(Vec3(0.0f), Mat3(Euler(0.0f, kPi, 0.0f)))}; // +z
  14. Frustum::Frustum()
  15. {
  16. // Set some default values
  17. init(FrustumType::kPerspective);
  18. update();
  19. }
  20. Frustum::~Frustum()
  21. {
  22. }
  23. void Frustum::init(FrustumType type)
  24. {
  25. ANKI_ASSERT(type < FrustumType::kCount);
  26. m_frustumType = type;
  27. setNear(kDefaultNear);
  28. setFar(kDefaultFar);
  29. if(m_frustumType == FrustumType::kPerspective)
  30. {
  31. setFovX(kDefaultFovAngle);
  32. setFovY(kDefaultFovAngle);
  33. }
  34. else
  35. {
  36. setLeft(-5.0f);
  37. setRight(5.0f);
  38. setBottom(-1.0f);
  39. setTop(1.0f);
  40. }
  41. }
  42. Bool Frustum::update()
  43. {
  44. Bool updated = false;
  45. // Update the shape
  46. if(m_shapeDirty)
  47. {
  48. updated = true;
  49. if(m_frustumType == FrustumType::kPerspective)
  50. {
  51. m_projMat =
  52. Mat4::calculatePerspectiveProjectionMatrix(m_perspective.m_fovX, m_perspective.m_fovY, m_perspective.m_near, m_perspective.m_far);
  53. computeEdgesOfFrustum(m_perspective.m_far, m_perspective.m_fovX, m_perspective.m_fovY, &m_perspective.m_edgesL[0]);
  54. // Planes
  55. F32 c, s; // cos & sine
  56. sinCos(kPi + m_perspective.m_fovX / 2.0f, s, c);
  57. // right
  58. m_viewPlanesL[FrustumPlaneType::kRight] = Plane(Vec4(c, 0.0f, s, 0.0f), 0.0f);
  59. // left
  60. m_viewPlanesL[FrustumPlaneType::kLeft] = Plane(Vec4(-c, 0.0f, s, 0.0f), 0.0f);
  61. sinCos((kPi + m_perspective.m_fovY) * 0.5f, s, c);
  62. // bottom
  63. m_viewPlanesL[FrustumPlaneType::kBottom] = Plane(Vec4(0.0f, s, c, 0.0f), 0.0f);
  64. // top
  65. m_viewPlanesL[FrustumPlaneType::kTop] = Plane(Vec4(0.0f, -s, c, 0.0f), 0.0f);
  66. // near
  67. m_viewPlanesL[FrustumPlaneType::kNear] = Plane(Vec4(0.0f, 0.0f, -1.0, 0.0f), m_perspective.m_near);
  68. // far
  69. m_viewPlanesL[FrustumPlaneType::kFar] = Plane(Vec4(0.0f, 0.0f, 1.0, 0.0f), -m_perspective.m_far);
  70. }
  71. else
  72. {
  73. m_projMat = Mat4::calculateOrthographicProjectionMatrix(m_ortho.m_right, m_ortho.m_left, m_ortho.m_top, m_ortho.m_bottom, m_ortho.m_near,
  74. m_ortho.m_far);
  75. // OBB
  76. const Vec4 c((m_ortho.m_right + m_ortho.m_left) * 0.5f, (m_ortho.m_top + m_ortho.m_bottom) * 0.5f,
  77. -(m_ortho.m_far + m_ortho.m_near) * 0.5f, 0.0f);
  78. const Vec4 e = Vec4(m_ortho.m_right, m_ortho.m_top, -m_ortho.m_far, 0.0f) - c;
  79. m_ortho.m_obbL = Obb(c, Mat3x4::getIdentity(), e);
  80. // Planes
  81. m_viewPlanesL[FrustumPlaneType::kLeft] = Plane(Vec4(1.0f, 0.0f, 0.0f, 0.0f), m_ortho.m_left);
  82. m_viewPlanesL[FrustumPlaneType::kRight] = Plane(Vec4(-1.0f, 0.0f, 0.0f, 0.0f), -m_ortho.m_right);
  83. m_viewPlanesL[FrustumPlaneType::kNear] = Plane(Vec4(0.0f, 0.0f, -1.0f, 0.0f), m_ortho.m_near);
  84. m_viewPlanesL[FrustumPlaneType::kFar] = Plane(Vec4(0.0f, 0.0f, 1.0f, 0.0f), -m_ortho.m_far);
  85. m_viewPlanesL[FrustumPlaneType::kTop] = Plane(Vec4(0.0f, -1.0f, 0.0f, 0.0f), -m_ortho.m_top);
  86. m_viewPlanesL[FrustumPlaneType::kBottom] = Plane(Vec4(0.0f, 1.0f, 0.0f, 0.0f), m_ortho.m_bottom);
  87. }
  88. }
  89. // Update transform related things
  90. if(m_worldTransformDirty)
  91. {
  92. updated = true;
  93. m_viewMat = Mat3x4(m_worldTransform.getInverse());
  94. }
  95. // Updates that are affected by transform & shape updates
  96. if(updated)
  97. {
  98. m_shapeDirty = false;
  99. m_worldTransformDirty = false;
  100. m_viewProjMat = m_projMat * Mat4(m_viewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
  101. if(m_frustumType == FrustumType::kPerspective)
  102. {
  103. m_perspective.m_edgesW[0] = m_worldTransform.getOrigin();
  104. m_perspective.m_edgesW[1] = m_worldTransform.transform(m_perspective.m_edgesL[0].xyz0());
  105. m_perspective.m_edgesW[2] = m_worldTransform.transform(m_perspective.m_edgesL[1].xyz0());
  106. m_perspective.m_edgesW[3] = m_worldTransform.transform(m_perspective.m_edgesL[2].xyz0());
  107. m_perspective.m_edgesW[4] = m_worldTransform.transform(m_perspective.m_edgesL[3].xyz0());
  108. m_perspective.m_hull = ConvexHullShape(&m_perspective.m_edgesW[0], m_perspective.m_edgesW.getSize());
  109. }
  110. else
  111. {
  112. m_ortho.m_obbW = m_ortho.m_obbL.getTransformed(m_worldTransform);
  113. }
  114. for(FrustumPlaneType planeId : EnumIterable<FrustumPlaneType>())
  115. {
  116. m_viewPlanesW[planeId] = m_viewPlanesL[planeId].getTransformed(m_worldTransform);
  117. }
  118. }
  119. return updated;
  120. }
  121. } // end namespace anki