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 = 45.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);
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 cubeIntersectsFrustum(const AACube& box) const;
107  bool boxIntersectsFrustum(const AABox& box) const;
108  bool boxInsideFrustum(const AABox& box) const;
109 
110  bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const;
111  bool cubeIntersectsKeyhole(const AACube& cube) const;
112  bool boxIntersectsKeyhole(const AABox& box) const;
113 
114  bool isVerySimilar(const ViewFrustum& compareTo) const;
115 
116  PickRay computePickRay(float x, float y);
117  void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
118 
119  void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearValue, float& farValue,
120  glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
121 
122  void printDebugDetails() const;
123 
124  glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
125  CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
126  CubeProjectedPolygon getProjectedPolygon(const AABox& box) const;
127  bool getProjectedRect(const AABox& box, glm::vec2& bottomLeft, glm::vec2& topRight) const;
128  void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
129 
130  float distanceToCameraSquared(const glm::vec3& point) const;
131  float distanceToCamera(const glm::vec3& point) const { return sqrtf(distanceToCameraSquared(point)); }
132 
133  void evalProjectionMatrix(glm::mat4& proj) const;
134 
135  glm::mat4 evalProjectionMatrixRange(float rangeNear, float rangeFar) const;
136 
137  void evalViewTransform(Transform& view) const;
138 
139  enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
140 
141  const ::Plane* getPlanes() const { return _planes; }
142  void getSidePlanes(::Plane planes[4]) const;
143  // Transform can have a different scale value in X,Y,Z components
144  void getTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
145  // Transform is assumed to have the same scale value in all three X,Y,Z components, which
146  // allows for a faster computation.
147  void getUniformlyTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
148 
149  void invalidate(); // causes all reasonable intersection tests to fail
150 
151 private:
152  glm::mat4 _view;
153  glm::mat4 _projection;
154 
155  ::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum
156 
157  glm::vec3 _position; // position in world-frame
158  glm::quat _orientation; // orientation in world-frame
159 
160  // calculated from orientation
161  glm::vec3 _direction = IDENTITY_FORWARD;
162  glm::vec3 _up = IDENTITY_UP;
163  glm::vec3 _right = IDENTITY_RIGHT;
164 
165  // calculated from projection
166  glm::vec4 _corners[NUM_FRUSTUM_CORNERS];
167  glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS];
168  float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS;
169  float _width { 1.0f };
170  float _height { 1.0f };
171  float _aspectRatio { 1.0f };
172  float _focalLength { 0.25f };
173  float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES };
174 
175  float _nearClip { DEFAULT_NEAR_CLIP };
176  float _farClip { DEFAULT_FAR_CLIP };
177 
178  const char* debugPlaneName (int plane) const;
179 
180  // Used to project points
181  glm::mat4 _ourModelViewProjectionMatrix;
182 
183  template <typename TBOX>
184  CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const;
185 
186  static void tesselateSides(const glm::vec3 points[8], Triangle triangles[8]);
187 
188 };
189 using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
190 using ViewFrustums = std::vector<ViewFrustum>;
191 
192 #endif // hifi_ViewFrustum_h