Overte C++ Documentation
ViewFrustum.h
1 //
2 // ViewFrustum.h
3 // libraries/shared/src
4 //
5 // Created by Brad Hefta-Gaub on 04/11/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Simple view frustum class.
9 //
10 // Distributed under the Apache License, Version 2.0.
11 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12 //
13 
14 #ifndef hifi_ViewFrustum_h
15 #define hifi_ViewFrustum_h
16 
17 #include <glm/glm.hpp>
18 #include <glm/gtc/quaternion.hpp>
19 
20 #include "AABox.h"
21 #include "AACube.h"
22 #include "CubeProjectedPolygon.h"
23 #include "Plane.h"
24 #include "RegisteredMetaTypes.h"
25 #include "Transform.h"
26 
27 const int NUM_FRUSTUM_CORNERS = 8;
28 const int NUM_FRUSTUM_PLANES = 6;
29 
30 const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f;
31 const float DEFAULT_FIELD_OF_VIEW_DEGREES = 55.0f;
32 const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
33 const float DEFAULT_NEAR_CLIP = 0.08f;
34 const float DEFAULT_FAR_CLIP = 16384.0f;
35 
36 class ViewFrustum {
37 public:
38  // setters for camera attributes
39  void setPosition(const glm::vec3& position);
40  void setOrientation(const glm::quat& orientation);
41 
42  // getters for camera attributes
43  const glm::vec3& getPosition() const { return _position; }
44  const glm::quat& getOrientation() const { return _orientation; }
45  const glm::vec3& getDirection() const { return _direction; }
46  const glm::vec3& getUp() const { return _up; }
47  const glm::vec3& getRight() const { return _right; }
48 
49  // setters for lens attributes
50  void setProjection(const glm::mat4& projection, bool isOblique = false);
51  void setProjection(float cameraFov, float cameraAspectRatio, float cameraNearClip, float cameraFarClip);
52  void setFocalLength(float focalLength) { _focalLength = focalLength; }
53  bool isPerspective() const;
54 
55  // getters for lens attributes
56  const glm::mat4& getProjection() const { return _projection; }
57  const glm::mat4& getView() const { return _view; }
58  float getWidth() const { return _width; }
59  float getHeight() const { return _height; }
60  float getFieldOfView() const { return _fieldOfView; }
61  float getAspectRatio() const { return _aspectRatio; }
62  float getNearClip() const { return _nearClip; }
63  float getFarClip() const { return _farClip; }
64  float getFocalLength() const { return _focalLength; }
65 
66  class Corners {
67  public:
68  Corners(glm::vec3&& topLeft, glm::vec3&& topRight, glm::vec3&& bottomLeft, glm::vec3&& bottomRight)
69  : topLeft{ topLeft }, topRight{ topRight }, bottomLeft{ bottomLeft }, bottomRight{ bottomRight } {}
70  glm::vec3 topLeft;
71  glm::vec3 topRight;
72  glm::vec3 bottomLeft;
73  glm::vec3 bottomRight;
74  // Get the corners depth units from frustum position, along frustum orientation
75  };
76  const Corners getCorners(const float depth) const;
77 
78  // getters for corners
79  const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
80  const glm::vec3& getFarTopRight() const { return _cornersWorld[TOP_RIGHT_FAR]; }
81  const glm::vec3& getFarBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_FAR]; }
82  const glm::vec3& getFarBottomRight() const { return _cornersWorld[BOTTOM_RIGHT_FAR]; }
83  const glm::vec3& getNearTopLeft() const { return _cornersWorld[TOP_LEFT_NEAR]; }
84  const glm::vec3& getNearTopRight() const { return _cornersWorld[TOP_RIGHT_NEAR]; }
85  const glm::vec3& getNearBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_NEAR]; }
86  const glm::vec3& getNearBottomRight() const { return _cornersWorld[BOTTOM_RIGHT_NEAR]; }
87 
88  // get/set for central spherek attribute
89  void setCenterRadius(float radius) { _centerSphereRadius = radius; }
90  float getCenterRadius() const { return _centerSphereRadius; }
91 
92  void tesselateSides(Triangle triangles[8]) const;
93  void tesselateSides(const Transform& transform, Triangle triangles[8]) const;
94  void tesselateSidesAndFar(const Transform& transform, Triangle triangles[10], float farDistance) const;
95 
96  void calculate();
97 
98  typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } intersection;
99 
101  ViewFrustum::intersection calculateCubeFrustumIntersection(const AACube& cube) const;
102  ViewFrustum::intersection calculateCubeKeyholeIntersection(const AACube& cube) const;
103 
104  bool pointIntersectsFrustum(const glm::vec3& point) const;
105  bool sphereIntersectsFrustum(const glm::vec3& center, float radius) const;
106  bool boxIntersectsFrustum(const AABox& box) const;
107  bool boxInsideFrustum(const AABox& box) const;
108 
109  bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const;
110  bool cubeIntersectsKeyhole(const AACube& cube) const;
111  bool boxIntersectsKeyhole(const AABox& box) const;
112 
113  bool isVerySimilar(const ViewFrustum& compareTo) const;
114 
115  PickRay computePickRay(float x, float y);
116  void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
117 
118  void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearValue, float& farValue,
119  glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
120 
121  void printDebugDetails() const;
122 
123  glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
124  CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
125  CubeProjectedPolygon getProjectedPolygon(const AABox& box) const;
126  bool getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm::vec2& topRight) const;
127  void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
128 
129  float distanceToCameraSquared(const glm::vec3& point) const;
130  float distanceToCamera(const glm::vec3& point) const { return sqrtf(distanceToCameraSquared(point)); }
131 
132  void evalProjectionMatrix(glm::mat4& proj) const;
133 
134  glm::mat4 evalProjectionMatrixRange(float rangeNear, float rangeFar) const;
135 
136  void evalViewTransform(Transform& view) const;
137 
138  enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
139 
140  const ::Plane* getPlanes() const { return _planes; }
141  void getSidePlanes(::Plane planes[4]) const;
142  // Transform can have a different scale value in X,Y,Z components
143  void getTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
144  // Transform is assumed to have the same scale value in all three X,Y,Z components, which
145  // allows for a faster computation.
146  void getUniformlyTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
147 
148  void invalidate(); // causes all reasonable intersection tests to fail
149 
150 private:
151  glm::mat4 _view;
152  glm::mat4 _projection;
153 
154  ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum
155 
156  glm::vec3 _position; // position in world-frame
157  glm::quat _orientation; // orientation in world-frame
158 
159  // calculated from orientation
160  glm::vec3 _direction = IDENTITY_FORWARD;
161  glm::vec3 _up = IDENTITY_UP;
162  glm::vec3 _right = IDENTITY_RIGHT;
163 
164  // calculated from projection
165  glm::vec4 _corners[NUM_FRUSTUM_CORNERS];
166  glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS];
167  float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS;
168  float _width { 1.0f };
169  float _height { 1.0f };
170  float _aspectRatio { 1.0f };
171  float _focalLength { 0.25f };
172  float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES };
173 
174  float _nearClip { DEFAULT_NEAR_CLIP };
175  float _farClip { DEFAULT_FAR_CLIP };
176 
177  bool _isOblique { false };
178 
179  const char* debugPlaneName (int plane) const;
180 
181  // Used to project points
182  glm::mat4 _ourModelViewProjectionMatrix;
183 
184  template <typename TBOX>
185  CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const;
186 
187  static void tesselateSides(const glm::vec3 points[8], Triangle triangles[8]);
188 
189 };
190 using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
191 using ViewFrustums = std::vector<ViewFrustum>;
192 
193 #endif // hifi_ViewFrustum_h