Saga3D API Documentation  1.0-RC4
SViewFrustum.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __SVIEW_FRUSTUM_H_INCLUDED__
6 #define __SVIEW_FRUSTUM_H_INCLUDED__
7 
8 #include "plane3d.h"
9 #include "line3d.h"
10 #include "aabbox3d.h"
11 
12 #include "ETransformStates.h"
13 #include "GraphicsConstants.h"
14 #include "enumType.hpp"
15 #include <glm/vec3.hpp>
16 #include <glm/gtc/type_ptr.hpp>
17 #include <array>
18 
19 namespace saga
20 {
21 namespace scene
22 {
23 
25 
29  struct SViewFrustum
30  {
31  enum class E_PLANES
32  {
34  FAR,
36  NEAR,
38  LEFT,
40  RIGHT,
42  BOTTOM,
44  TOP,
45  };
46 
48  SViewFrustum() : BoundingRadius(0.f), FarNearDistance(0.f) {}
49 
51  SViewFrustum(const SViewFrustum& other);
52 
54  SViewFrustum(const glm::mat4& mat);
55 
57  inline void setFrom(const glm::mat4& mat);
58 
60 
61  void transform(const glm::mat4& mat);
62 
64  glm::vec3 getFarLeftUp() const;
65 
67  glm::vec3 getFarLeftDown() const;
68 
70  glm::vec3 getFarRightUp() const;
71 
73  glm::vec3 getFarRightDown() const;
74 
76  glm::vec3 getNearLeftUp() const;
77 
79  glm::vec3 getNearLeftDown() const;
80 
82  glm::vec3 getNearRightUp() const;
83 
85  glm::vec3 getNearRightDown() const;
86 
89 
91  inline void recalculateBoundingBox();
92 
94  float getBoundingRadius() const;
95 
97  glm::vec3 getBoundingCenter() const;
98 
100  void setFarNearDistance(float distance);
101 
103  glm::mat4& getTransform(video::E_TRANSFORM_STATE state);
104 
106  const glm::mat4& getTransform(video::E_TRANSFORM_STATE state) const;
107 
109 
110  bool clipLine(core::line3d<float>& line) const;
111 
113  glm::vec3 cameraPosition;
114 
116 
117  core::plane3d<float> plane(E_PLANES type) const { return planes.at(core::enumToPOD(type)); }
118 
120  std::array<core::plane3d<float>, VIEW_FRUSTUM_PLANE_COUNT> planes;
121 
124 
125  private:
127  // TODO: port to enum class
128  enum class E_TRANSFORM_STATE_FRUSTUM
129  {
130  VIEW = 0,
131  PROJECTION = 1,
132  };
133 
135  inline void recalculateBoundingSphere();
136 
138  std::array<glm::mat4, TRANSFORM_FRUSTUM_COUNT> Matrices;
139 
140  float BoundingRadius;
141  float FarNearDistance;
142  glm::vec3 BoundingCenter;
143  };
144 
149  {
151  boundingBox=other.boundingBox;
152 
153  std::uint32_t i;
154  for (i = 0; i < VIEW_FRUSTUM_PLANE_COUNT; ++i)
155  planes[i]=other.planes[i];
156 
157  for (i = 0; i < TRANSFORM_FRUSTUM_COUNT; ++i)
158  Matrices[i]=other.Matrices[i];
159 
160  BoundingRadius = other.BoundingRadius;
161  FarNearDistance = other.FarNearDistance;
162  BoundingCenter = other.BoundingCenter;
163  }
164 
165  inline SViewFrustum::SViewFrustum(const glm::mat4& mat)
166  {
167  setFrom(mat);
168  }
169 
170  inline void SViewFrustum::transform(const glm::mat4& mat)
171  {
172  for (std::uint32_t i = 0; i < VIEW_FRUSTUM_PLANE_COUNT; ++i)
173  planes[i].transform(mat);
174 
175  cameraPosition = glm::vec4(cameraPosition, 1) * mat;
177  }
178 
179  inline glm::vec3 SViewFrustum::getFarLeftUp() const
180  {
181  glm::vec3 p;
182  plane(scene::SViewFrustum::E_PLANES::FAR).getIntersectionWithPlanes(
185 
186  return p;
187  }
188 
189  inline glm::vec3 SViewFrustum::getFarLeftDown() const
190  {
191  glm::vec3 p;
192  plane(scene::SViewFrustum::E_PLANES::FAR).getIntersectionWithPlanes(
195 
196  return p;
197  }
198 
199  inline glm::vec3 SViewFrustum::getFarRightUp() const
200  {
201  glm::vec3 p;
202  plane(scene::SViewFrustum::E_PLANES::FAR).getIntersectionWithPlanes(
205 
206  return p;
207  }
208 
209  inline glm::vec3 SViewFrustum::getFarRightDown() const
210  {
211  glm::vec3 p;
212  plane(scene::SViewFrustum::E_PLANES::FAR).getIntersectionWithPlanes(
215 
216  return p;
217  }
218 
219  inline glm::vec3 SViewFrustum::getNearLeftUp() const
220  {
221  glm::vec3 p;
222  plane(scene::SViewFrustum::E_PLANES::NEAR).getIntersectionWithPlanes(
225 
226  return p;
227  }
228 
229  inline glm::vec3 SViewFrustum::getNearLeftDown() const
230  {
231  glm::vec3 p;
232  plane(scene::SViewFrustum::E_PLANES::NEAR).getIntersectionWithPlanes(
235 
236  return p;
237  }
238 
239  inline glm::vec3 SViewFrustum::getNearRightUp() const
240  {
241  glm::vec3 p;
242  plane(scene::SViewFrustum::E_PLANES::NEAR).getIntersectionWithPlanes(
245 
246  return p;
247  }
248 
249  inline glm::vec3 SViewFrustum::getNearRightDown() const
250  {
251  glm::vec3 p;
252  plane(scene::SViewFrustum::E_PLANES::NEAR).getIntersectionWithPlanes(
255 
256  return p;
257  }
258 
260  {
261  return boundingBox;
262  }
263 
265  {
267 
272 
273  // Also recalculate the bounding sphere when the bbox changes
274  recalculateBoundingSphere();
275  }
276 
277  inline float SViewFrustum::getBoundingRadius() const
278  {
279  return BoundingRadius;
280  }
281 
282  inline glm::vec3 SViewFrustum::getBoundingCenter() const
283  {
284  return BoundingCenter;
285  }
286 
287  inline void SViewFrustum::setFarNearDistance(float distance)
288  {
289  FarNearDistance = distance;
290  }
291 
294  inline void SViewFrustum::setFrom(const glm::mat4& matrix)
295  {
296  // left clipping plane
297  auto mat = glm::value_ptr(matrix);
298  plane(E_PLANES::LEFT).Normal.x = mat[3 ] + mat[0];
299  plane(E_PLANES::LEFT).Normal.y = mat[7 ] + mat[4];
300  plane(E_PLANES::LEFT).Normal.z = mat[11] + mat[8];
301  plane(E_PLANES::LEFT).D = mat[15] + mat[12];
302 
303  // right clipping plane
304  plane(E_PLANES::RIGHT).Normal.x = mat[3 ] - mat[0];
305  plane(E_PLANES::RIGHT).Normal.y = mat[7 ] - mat[4];
306  plane(E_PLANES::RIGHT).Normal.z = mat[11] - mat[8];
307  plane(E_PLANES::RIGHT).D = mat[15] - mat[12];
308 
309  // top clipping plane
310  plane(E_PLANES::TOP).Normal.x = mat[3 ] - mat[1];
311  plane(E_PLANES::TOP).Normal.y = mat[7 ] - mat[5];
312  plane(E_PLANES::TOP).Normal.z = mat[11] - mat[9];
313  plane(E_PLANES::TOP).D = mat[15] - mat[13];
314 
315  // bottom clipping plane
316  plane(E_PLANES::BOTTOM).Normal.x = mat[3 ] + mat[1];
317  plane(E_PLANES::BOTTOM).Normal.y = mat[7 ] + mat[5];
318  plane(E_PLANES::BOTTOM).Normal.z = mat[11] + mat[9];
319  plane(E_PLANES::BOTTOM).D = mat[15] + mat[13];
320 
321  // far clipping plane
322  plane(E_PLANES::FAR).Normal.x = mat[3 ] - mat[2];
323  plane(E_PLANES::FAR).Normal.y = mat[7 ] - mat[6];
324  plane(E_PLANES::FAR).Normal.z = mat[11] - mat[10];
325  plane(E_PLANES::FAR).D = mat[15] - mat[14];
326 
327  // near clipping plane
328  plane(E_PLANES::NEAR).Normal.x = mat[2];
329  plane(E_PLANES::NEAR).Normal.y = mat[6];
330  plane(E_PLANES::NEAR).Normal.z = mat[10];
331  plane(E_PLANES::NEAR).D = mat[14];
332 
333  // normalize normals
334  std::uint32_t i;
335  for (i = 0; i != VIEW_FRUSTUM_PLANE_COUNT; ++i)
336  {
337  const float len = -core::reciprocal_squareroot(glm::length2(planes[i].Normal));
338  planes[i].Normal *= len;
339  planes[i].D *= len;
340  }
341 
342  // make bounding box
344  }
345 
350  {
351  return Matrices[core::enumToPOD(state)];
352  }
353 
357  inline const glm::mat4& SViewFrustum::getTransform(video::E_TRANSFORM_STATE state) const
358  {
359  return Matrices.at(core::enumToPOD(state));
360  }
361 
364  {
365  bool wasClipped = false;
366  for (std::uint32_t i = 0; i < VIEW_FRUSTUM_PLANE_COUNT; ++i)
367  {
368  if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT)
369  {
370  line.start = glm::mix(line.start, line.end,
371  planes[i].getKnownIntersectionWithLine(line.start, line.end)
372  );
373  wasClipped = true;
374  }
375  if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT)
376  {
377  line.end = glm::mix(line.start, line.end,
378  planes[i].getKnownIntersectionWithLine(line.start, line.end)
379  );
380  wasClipped = true;
381  }
382  }
383  return wasClipped;
384  }
385 
386  inline void SViewFrustum::recalculateBoundingSphere()
387  {
388  // Find the center
389  const float shortlen = glm::length(getNearLeftUp() - getNearRightUp());
390  const float longlen = glm::length(getFarLeftUp() - getFarRightUp());
391 
392  const float farlen = FarNearDistance;
393  const float fartocenter = (farlen + (shortlen - longlen) * (shortlen + longlen)/(4*farlen)) / 2;
394  const float neartocenter = farlen - fartocenter;
395 
396  BoundingCenter = cameraPosition + -plane(E_PLANES::NEAR).Normal * neartocenter;
397 
398  // Find the radius
399  glm::vec3 dir[8];
400  dir[0] = getFarLeftUp() - BoundingCenter;
401  dir[1] = getFarRightUp() - BoundingCenter;
402  dir[2] = getFarLeftDown() - BoundingCenter;
403  dir[3] = getFarRightDown() - BoundingCenter;
404  dir[4] = getNearRightDown() - BoundingCenter;
405  dir[5] = getNearLeftDown() - BoundingCenter;
406  dir[6] = getNearRightUp() - BoundingCenter;
407  dir[7] = getNearLeftUp() - BoundingCenter;
408 
409  std::uint32_t i = 0;
410  float diam[8] = { 0.f };
411 
412  for (i = 0; i < 8; ++i)
413  diam[i] = glm::length2(dir[i]);
414 
415  float longest = 0;
416 
417  for (i = 0; i < 8; ++i)
418  {
419  if (diam[i] > longest)
420  longest = diam[i];
421  }
422 
423  BoundingRadius = sqrtf(longest);
424  }
425 
426 } // namespace scene
427 } // namespace saga
428 
429 #endif
430 
saga::scene::SViewFrustum::getTransform
glm::mat4 & getTransform(video::E_TRANSFORM_STATE state)
get the given state's matrix based on frustum E_TRANSFORM_STATE
Definition: SViewFrustum.h:349
plane3d.h
saga::core::plane3d
Template plane class with some intersection testing methods.
Definition: plane3d.h:34
saga::core::enumToPOD
constexpr auto enumToPOD(E e) noexcept
Definition: enumType.hpp:13
saga::scene::SViewFrustum::E_PLANES::NEAR
@ NEAR
Near plane of the frustum. That is the plane nearest to the eye.
saga::scene::SViewFrustum::plane
core::plane3d< float > & plane(E_PLANES type)
Definition: SViewFrustum.h:115
saga::core::ISREL3D_FRONT
@ ISREL3D_FRONT
Definition: plane3d.h:20
saga::scene::SViewFrustum::transform
void transform(const glm::mat4 &mat)
transforms the frustum by the matrix
Definition: SViewFrustum.h:170
saga::scene::SViewFrustum::getBoundingCenter
glm::vec3 getBoundingCenter() const
get the bounding sphere's radius (of an optimized sphere, not the AABB's)
Definition: SViewFrustum.h:282
saga::scene::SViewFrustum::recalculateBoundingBox
void recalculateBoundingBox()
recalculates the bounding box and sphere based on the planes
Definition: SViewFrustum.h:264
saga::scene::SViewFrustum::getFarLeftUp
glm::vec3 getFarLeftUp() const
returns the point which is on the far left upper corner inside the the view frustum.
Definition: SViewFrustum.h:179
saga::scene::SViewFrustum::E_PLANES::BOTTOM
@ BOTTOM
Bottom plane of the frustum.
saga::scene::SViewFrustum::planes
std::array< core::plane3d< float >, VIEW_FRUSTUM_PLANE_COUNT > planes
all planes enclosing the view frustum.
Definition: SViewFrustum.h:120
saga::scene::SViewFrustum::setFarNearDistance
void setFarNearDistance(float distance)
the cam should tell the frustum the distance between far and near
Definition: SViewFrustum.h:287
saga::scene::SViewFrustum::plane
core::plane3d< float > plane(E_PLANES type) const
Definition: SViewFrustum.h:117
saga::core::reciprocal_squareroot
REALINLINE double reciprocal_squareroot(const double x)
Definition: irrMath.h:571
saga::scene::SViewFrustum::E_PLANES::FAR
@ FAR
Far plane of the frustum. That is the plane furthest away from the eye.
saga::scene::SViewFrustum::E_PLANES::LEFT
@ LEFT
Left plane of the frustum.
saga::scene::SViewFrustum::getNearLeftUp
glm::vec3 getNearLeftUp() const
returns the point which is on the near left upper corner inside the the view frustum.
Definition: SViewFrustum.h:219
aabbox3d.h
saga::core::line3d
3D line between two points with intersection methods.
Definition: line3d.h:17
saga::scene::TRANSFORM_FRUSTUM_COUNT
constexpr auto TRANSFORM_FRUSTUM_COUNT
Definition: GraphicsConstants.h:21
saga::scene::SViewFrustum::getBoundingBox
const core::aabbox3d< float > & getBoundingBox() const
returns a bounding box enclosing the whole view frustum
Definition: SViewFrustum.h:259
saga::scene::VIEW_FRUSTUM_PLANE_COUNT
constexpr auto VIEW_FRUSTUM_PLANE_COUNT
Definition: GraphicsConstants.h:22
saga::scene::SViewFrustum::getNearRightUp
glm::vec3 getNearRightUp() const
returns the point which is on the near right top corner inside the the view frustum.
Definition: SViewFrustum.h:239
saga::core::aabbox3d< float >
saga::scene::SViewFrustum::cameraPosition
glm::vec3 cameraPosition
the position of the camera
Definition: SViewFrustum.h:113
enumType.hpp
saga::scene::SViewFrustum::clipLine
bool clipLine(core::line3d< float > &line) const
clips a line to the view frustum.
Definition: SViewFrustum.h:363
GraphicsConstants.h
saga::video::E_TRANSFORM_STATE
E_TRANSFORM_STATE
enumeration for geometry transformation states
Definition: ETransformStates.h:10
saga::core::aabbox3d::reset
void reset(T x, T y, T z)
Resets the bounding box to a one-point box.
Definition: aabbox3d.h:49
saga::core::line3d::end
glm::vec3 end
End point of line.
Definition: line3d.h:131
saga::core::line3d::start
glm::vec3 start
Start point of line.
Definition: line3d.h:129
saga::scene::SViewFrustum::getFarRightDown
glm::vec3 getFarRightDown() const
returns the point which is on the far right bottom corner inside the the view frustum.
Definition: SViewFrustum.h:209
saga::scene::SViewFrustum::getNearRightDown
glm::vec3 getNearRightDown() const
returns the point which is on the near right bottom corner inside the the view frustum.
Definition: SViewFrustum.h:249
saga::scene::SViewFrustum::getFarRightUp
glm::vec3 getFarRightUp() const
returns the point which is on the far right top corner inside the the view frustum.
Definition: SViewFrustum.h:199
ETransformStates.h
saga::scene::SViewFrustum::getFarLeftDown
glm::vec3 getFarLeftDown() const
returns the point which is on the far left bottom corner inside the the view frustum.
Definition: SViewFrustum.h:189
saga::scene::SViewFrustum::SViewFrustum
SViewFrustum()
Default Constructor.
Definition: SViewFrustum.h:48
saga::scene::SViewFrustum::boundingBox
core::aabbox3d< float > boundingBox
bounding box around the view frustum
Definition: SViewFrustum.h:123
saga::scene::SViewFrustum::getBoundingRadius
float getBoundingRadius() const
get the bounding sphere's radius (of an optimized sphere, not the AABB's)
Definition: SViewFrustum.h:277
saga::scene::SViewFrustum
Defines the view frustum. That's the space visible by the camera.
Definition: SViewFrustum.h:29
saga::core::aabbox3d::addInternalPoint
void addInternalPoint(const glm::vec3 &p)
Adds a point to the bounding box.
Definition: aabbox3d.h:73
saga::scene::SViewFrustum::getNearLeftDown
glm::vec3 getNearLeftDown() const
returns the point which is on the near left bottom corner inside the the view frustum.
Definition: SViewFrustum.h:229
saga::scene::SViewFrustum::E_PLANES::RIGHT
@ RIGHT
Right plane of the frustum.
saga::scene::SViewFrustum::setFrom
void setFrom(const glm::mat4 &mat)
This constructor creates a view frustum based on a projection and/or view matrix.
Definition: SViewFrustum.h:294
line3d.h
saga::scene::SViewFrustum::E_PLANES::TOP
@ TOP
Top plane of the frustum.
saga
Definition: aabbox3d.h:11
saga::scene::SViewFrustum::E_PLANES
E_PLANES
Definition: SViewFrustum.h:31