💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.0 KiB

  1. /*
  2. * Copyright (C) 2020 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_VIEW_FRUSTUM_HPP
  20. #define ANTKEEPER_VIEW_FRUSTUM_HPP
  21. #include "convex-hull.hpp"
  22. #include <array>
  23. #include <vmq/vmq.hpp>
  24. using vmq::vector;
  25. using vmq::matrix;
  26. using namespace vmq::operators;
  27. template <class T>
  28. class view_frustum
  29. {
  30. public:
  31. /**
  32. * Creates a view frustum from a view-projection matrix.
  33. *
  34. * @param view_projection View-projection matrix.
  35. */
  36. view_frustum(const matrix<T, 4, 4>& view_projection);
  37. /// Creates an uninitialized view frustum.
  38. view_frustum();
  39. /**
  40. * Recalculates the view frustum from a view-projection matrix.
  41. *
  42. * @param view_projection View-projection matrix.
  43. */
  44. void set_matrix(const matrix<T, 4, 4>& view_projection);
  45. /// Returns a convex hull which describes the bounds of the view frustum.
  46. const convex_hull<T>& get_bounds() const;
  47. /// Returns the left clipping plane.
  48. const plane<T>& get_left() const;
  49. /// Returns the right clipping plane.
  50. const plane<T>& get_right() const;
  51. /// Returns the bottom clipping plane.
  52. const plane<T>& get_bottom() const;
  53. /// Returns the top clipping plane.
  54. const plane<T>& get_top() const;
  55. /// Returns the near clipping plane.
  56. const plane<T>& get_near() const;
  57. /// Returns the far clipping plane.
  58. const plane<T>& get_far() const;
  59. /**
  60. * Returns an array containing the corners of the view frustum bounds.
  61. *
  62. * @return Array containing the corners of the view frustum bounds. Corners are stored in the following order: NTL, NTR, NBL, NBR, FTL, FTR, FBL, FBR; where N is near, F is far, T is top, B is bottom, L is left, and R is right, therefore NTL refers to the corner shared between the near, top, and left clipping planes.
  63. */
  64. const std::array<vector<T, 3>, 8>& get_corners() const;
  65. private:
  66. void recalculate_planes(const matrix<T, 4, 4>& view_projection);
  67. void recalculate_corners();
  68. convex_hull<T> bounds;
  69. std::array<vector<T, 3>, 8> corners;
  70. };
  71. template <class T>
  72. view_frustum<T>::view_frustum(const matrix<T, 4, 4>& view_projection):
  73. bounds(6)
  74. {
  75. set_matrix(view_projection);
  76. }
  77. template <class T>
  78. view_frustum<T>::view_frustum():
  79. view_frustum(vmq::identity4x4<T>)
  80. {}
  81. template <class T>
  82. void view_frustum<T>::set_matrix(const matrix<T, 4, 4>& view_projection)
  83. {
  84. recalculate_planes(view_projection);
  85. recalculate_corners();
  86. }
  87. template <class T>
  88. inline const convex_hull<T>& view_frustum<T>::get_bounds() const
  89. {
  90. return bounds;
  91. }
  92. template <class T>
  93. inline const plane<T>& view_frustum<T>::get_left() const
  94. {
  95. return bounds.planes[0];
  96. }
  97. template <class T>
  98. inline const plane<T>& view_frustum<T>::get_right() const
  99. {
  100. return bounds.planes[1];
  101. }
  102. template <class T>
  103. inline const plane<T>& view_frustum<T>::get_bottom() const
  104. {
  105. return bounds.planes[2];
  106. }
  107. template <class T>
  108. inline const plane<T>& view_frustum<T>::get_top() const
  109. {
  110. return bounds.planes[3];
  111. }
  112. template <class T>
  113. inline const plane<T>& view_frustum<T>::get_near() const
  114. {
  115. return bounds.planes[4];
  116. }
  117. template <class T>
  118. inline const plane<T>& view_frustum<T>::get_far() const
  119. {
  120. return bounds.planes[5];
  121. }
  122. template <class T>
  123. inline const std::array<vector<T, 3>, 8>& view_frustum<T>::get_corners() const
  124. {
  125. return corners;
  126. }
  127. template <class T>
  128. void view_frustum<T>::recalculate_planes(const matrix<T, 4, 4>& view_projection)
  129. {
  130. matrix<T, 4, 4> transpose = vmq::transpose(view_projection);
  131. bounds.planes[0] = plane<T>(transpose[3] + transpose[0]);
  132. bounds.planes[1] = plane<T>(transpose[3] - transpose[0]);
  133. bounds.planes[2] = plane<T>(transpose[3] + transpose[1]);
  134. bounds.planes[3] = plane<T>(transpose[3] - transpose[1]);
  135. bounds.planes[4] = plane<T>(transpose[3] + transpose[2]);
  136. bounds.planes[5] = plane<T>(transpose[3] - transpose[2]);
  137. }
  138. template <class T>
  139. void view_frustum<T>::recalculate_corners()
  140. {
  141. corners[0] = intersection(get_near(), get_top(), get_left());
  142. corners[1] = intersection(get_near(), get_top(), get_right());
  143. corners[2] = intersection(get_near(), get_bottom(), get_left());
  144. corners[3] = intersection(get_near(), get_bottom(), get_right());
  145. corners[4] = intersection(get_far(), get_top(), get_left());
  146. corners[5] = intersection(get_far(), get_top(), get_right());
  147. corners[6] = intersection(get_far(), get_bottom(), get_left());
  148. corners[7] = intersection(get_far(), get_bottom(), get_right());
  149. }
  150. #endif // ANTKEEPER_VIEW_FRUSTUM_HPP