Oculus VR DK2 Support
[Torque-3d.git] / Engine / source / math / util / frustum.h
blob205e075a14d7ea5309cbebb244148a9193fb684a
1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 //-----------------------------------------------------------------------------
23 #ifndef _MATHUTIL_FRUSTUM_H_
24 #define _MATHUTIL_FRUSTUM_H_
26 #ifndef _MPOLYHEDRON_H_
27 #include "math/mPolyhedron.h"
28 #endif
30 #ifndef _MBOX_H_
31 #include "math/mBox.h"
32 #endif
34 #ifndef _MPLANE_H_
35 #include "math/mPlane.h"
36 #endif
38 #ifndef _MMATRIX_H_
39 #include "math/mMatrix.h"
40 #endif
42 #ifndef _MQUAT_H_
43 #include "math/mQuat.h"
44 #endif
46 #ifndef _MSPHERE_H_
47 #include "math/mSphere.h"
48 #endif
51 //TODO: Specialize intersection tests for frustums using octant tests
54 class OrientedBox3F;
56 /// Advanced fov specification for oculus
57 struct FovPort
59 float upTan;
60 float downTan;
61 float leftTan;
62 float rightTan;
65 /// Polyhedron data for use by frustums. Uses fixed-size vectors
66 /// and a static vector for the edge list as that never changes
67 /// between frustums.
68 struct FrustumData : public PolyhedronData
70 enum
72 EdgeCount = 12
75 /// Indices for the planes in a frustum.
76 ///
77 /// Note the planes are ordered left, right, near,
78 /// far, top, bottom for getting early rejections
79 /// from the typical horizontal scene.
80 enum
82 PlaneLeft,
83 PlaneRight,
84 PlaneNear,
85 PlaneFar,
86 PlaneTop,
87 PlaneBottom,
89 /// The total number of frustum planes.
90 PlaneCount
93 /// Indices for the corner points of the frustum.
94 enum CornerPoints
96 NearTopLeft,
97 NearTopRight,
98 NearBottomLeft,
99 NearBottomRight,
100 FarTopLeft,
101 FarTopRight,
102 FarBottomLeft,
103 FarBottomRight,
105 /// Total number of corner points.
106 CornerPointCount
109 /// Indices for the center points of the frustum planes.
110 enum PlaneCenters
112 PlaneLeftCenter,
113 PlaneRightCenter,
114 PlaneTopCenter,
115 PlaneBottomCenter,
116 PlaneNearCenter,
117 PlaneFarCenter,
120 /// Used to mask out planes for testing.
121 enum
123 PlaneMaskLeft = ( 1 << PlaneLeft ),
124 PlaneMaskRight = ( 1 << PlaneRight ),
125 PlaneMaskTop = ( 1 << PlaneTop ),
126 PlaneMaskBottom = ( 1 << PlaneBottom ),
127 PlaneMaskNear = ( 1 << PlaneNear ),
128 PlaneMaskFar = ( 1 << PlaneFar ),
130 PlaneMaskAll = 0xFFFFFFFF,
133 typedef FixedSizeVector< PlaneF, PlaneCount > PlaneListType;
134 typedef FixedSizeVector< Point3F, CornerPointCount > PointListType;
135 typedef FixedSizeVector< Edge, EdgeCount > EdgeListType;
137 protected:
139 /// @name Lazily Updated Data
140 /// @{
142 /// When true, points, planes and bounds must be re-calculated before use.
143 mutable bool mDirty;
145 mutable PlaneListType mPlanes;
146 mutable PointListType mPoints;
148 /// The center points of the individual faces of the frustum.
149 mutable Point3F mPlaneCenters[ PlaneCount ];
151 /// The clipping-space axis-aligned bounding box which contains
152 /// the extents of the frustum.
153 mutable Box3F mBounds;
155 /// @}
157 /// Static edge list. Shared by all frustum polyhedrons
158 /// since they are always constructed the same way.
159 static EdgeListType smEdges;
161 /// Determines whether this Frustum
162 /// is orthographic or perspective.
163 bool mIsOrtho;
165 /// Whether the frustum is inverted, i.e. whether the planes are
166 /// facing outwards rather than inwards.
167 bool mIsInverted;
169 /// Used to transform the frustum points from camera
170 /// space into the desired clipping space.
171 MatrixF mTransform;
173 /// Camera position extracted from tarnsform.
174 Point3F mPosition;
176 /// The size of the near plane used to generate
177 /// the frustum points and planes.
178 F32 mNearLeft;
179 F32 mNearRight;
180 F32 mNearTop;
181 F32 mNearBottom;
182 F32 mNearDist;
183 F32 mFarDist;
185 /// Update the point and plane data from the current frustum settings.
186 void _update() const;
188 FrustumData()
189 : mDirty( false ),
190 mIsInverted( false ) {}
192 public:
194 /// @name Accessors
195 /// @{
197 /// Return the number of planes that a frustum has.
198 static U32 getNumPlanes() { return PlaneCount; }
200 /// Return the planes that make up the polyhedron.
201 /// @note The normals of these planes are facing *inwards*.
202 const PlaneF* getPlanes() const { _update(); return mPlanes.address(); }
204 /// Return the number of corner points that a frustum has.
205 static U32 getNumPoints() { return CornerPointCount; }
208 const Point3F* getPoints() const { _update(); return mPoints.address(); }
210 /// Return the number of edges that a frustum has.
211 static U32 getNumEdges() { return EdgeCount; }
213 /// Return the edge definitions for a frustum.
214 static const Edge* getEdges() { return smEdges.address(); }
216 /// @}
218 operator AnyPolyhedron() const
220 return AnyPolyhedron(
221 AnyPolyhedron::PlaneListType( const_cast< PlaneF* >( getPlanes() ), getNumPlanes() ),
222 AnyPolyhedron::PointListType( const_cast< Point3F* >( getPoints() ), getNumPoints() ),
223 AnyPolyhedron::EdgeListType( const_cast< Edge* >( getEdges() ), getNumEdges() )
229 /// This class implements a view frustum for use in culling scene objects and
230 /// rendering the scene.
232 /// @warn Frustums are always non-inverted by default which means that even if
233 /// the frustum transform applies a negative scale, the frustum will still be
234 /// non-inverted.
235 class Frustum : public PolyhedronImpl< FrustumData >
237 public:
239 typedef PolyhedronImpl< FrustumData > Parent;
241 protected:
243 /// @name Tiling
244 /// @{
246 /// Number of subdivisions.
247 U32 mNumTiles;
249 /// Current rendering tile.
250 Point2I mCurrTile;
252 /// Tile overlap percentage.
253 Point2F mTileOverlap;
255 /// @}
257 /// Offset used for projection matrix calculations
258 Point2F mProjectionOffset;
260 /// The calculated projection offset matrix
261 MatrixF mProjectionOffsetMatrix;
263 public:
265 /// @name Constructors
266 /// @{
268 /// Construct a non-inverted frustum.
270 /// @note If the given transform has a negative scale, the plane
271 /// normals will automatically be inverted so that the frustum
272 /// will still be non-inverted. Use invert() to actually cause
273 /// the frustum to be inverted.
274 Frustum( bool orthographic = false,
275 F32 nearLeft = -1.0f,
276 F32 nearRight = 1.0f,
277 F32 nearTop = 1.0f,
278 F32 nearBottom = -1.0f,
279 F32 nearDist = 0.1f,
280 F32 farDist = 1.0f,
281 const MatrixF &transform = MatrixF( true ) );
283 /// @}
286 /// @name Operators
287 /// @{
289 bool operator==( const Frustum& frustum ) const
291 return ( ( mNearLeft == frustum.mNearLeft ) &&
292 ( mNearTop == frustum.mNearTop ) &&
293 ( mNearBottom == frustum.mNearBottom ) &&
294 ( mNearDist == frustum.mNearDist ) &&
295 ( mFarDist == frustum.mFarDist ) &&
296 ( mProjectionOffset.x == frustum.mProjectionOffset.x ) &&
297 ( mProjectionOffset.y == frustum.mProjectionOffset.y ) );
300 bool operator!=( const Frustum& frustum ) const { return !( *this == frustum ); }
302 /// @}
305 /// @name Initialization
307 /// Functions used to initialize the frustum.
309 /// @{
311 /// Sets the frustum from the field of view, screen aspect
312 /// ratio, and the near and far distances. You can pass an
313 /// matrix to transform the frustum.
314 void set( bool isOrtho,
315 F32 fovYInRadians,
316 F32 aspectRatio,
317 F32 nearDist,
318 F32 farDist,
319 const MatrixF &mat = MatrixF( true ) );
321 /// Sets the frustum from the near plane dimensions and
322 /// near and far distances.
323 void set( bool isOrtho,
324 F32 nearLeft,
325 F32 nearRight,
326 F32 nearTop,
327 F32 nearBottom,
328 F32 nearDist,
329 F32 farDist,
330 const MatrixF &transform = MatrixF( true ) );
332 /// Sets the frustum by extracting the planes from a projection,
333 /// view-projection, or world-view-projection matrix.
334 //void set( const MatrixF& projMatrix, bool normalize );
336 /// Changes the near distance of the frustum.
337 void setNearDist( F32 nearDist );
339 /// Changes the far distance of the frustum.
340 void setFarDist( F32 farDist );
342 /// Changes the near and far distance of the frustum.
343 void setNearFarDist( F32 nearDist, F32 farDist );
346 void cropNearFar(F32 newNearDist, F32 newFarDist);
348 /// Returns the far clip distance used to create
349 /// the frustum planes.
350 F32 getFarDist() const { return mFarDist; }
352 /// Returns the far clip distance used to create
353 /// the frustum planes.
354 F32 getNearDist() const { return mNearDist; }
356 /// Return the camera-space minimum X coordinate on the near plane.
357 F32 getNearLeft() const { return mNearLeft; }
359 /// Return the camera-space maximum X coordinate on the near plane.
360 F32 getNearRight() const { return mNearRight; }
362 /// Return the camera-space maximum Z coordinate on the near plane.
363 F32 getNearTop() const { return mNearTop; }
365 /// Return the camera-space minimum Z coordinate on the near plane.
366 F32 getNearBottom() const { return mNearBottom; }
368 /// Return the camera-space width of the frustum.
369 F32 getWidth() const { return mFabs( mNearRight - mNearLeft ); }
371 /// Return the camera-space height of the frustum.
372 F32 getHeight() const { return mFabs( mNearTop - mNearBottom ); }
375 F32 getFov() const
377 F32 nonTiledHeight = getHeight()*mNumTiles;
378 return mAtan2( nonTiledHeight/2.0f, mNearDist ) * 2.0f;
382 F32 getAspectRatio() const { return (mNearRight - mNearLeft)/(mNearTop - mNearBottom); }
384 /// @}
387 /// @name Transformation
389 /// These functions for transforming the frustum from
390 /// one space to another.
392 /// @{
394 /// Sets a new transform for the frustum.
395 void setTransform( const MatrixF &transform );
397 /// Returns the current transform matrix for the frustum.
398 const MatrixF& getTransform() const { return mTransform; }
400 /// Scales up the frustum from its center point.
401 void scaleFromCenter( F32 scale );
403 /// Transforms the frustum by F = F * mat.
404 void mul( const MatrixF &mat );
406 /// Transforms the frustum by F = mat * F.
407 void mulL( const MatrixF &mat );
409 /// Flip the plane normals which has the result
410 /// of reversing the culling results.
411 void invert();
413 /// Returns true if the frustum planes point outwards.
414 bool isInverted() const { return mIsInverted; }
416 /// Returns the origin point of the frustum.
417 const Point3F& getPosition() const { return mPosition; }
419 /// Returns the axis aligned bounding box of the frustum
420 /// points typically used for early rejection.
421 const Box3F& getBounds() const { _update(); return mBounds; }
423 // Does the frustum have a projection offset?
424 bool hasProjectionOffset() const { return !mProjectionOffset.isZero(); }
426 /// Get the offset used when calculating the projection matrix
427 const Point2F& getProjectionOffset() const { return mProjectionOffset; }
429 /// Get the offset matrix used when calculating the projection matrix
430 const MatrixF& getProjectionOffsetMatrix() const { return mProjectionOffsetMatrix; }
432 /// Set the offset used when calculating the projection matrix
433 void setProjectionOffset(const Point2F& offsetMat);
435 /// Clear any offset used when calculating the projection matrix
436 void clearProjectionOffset() { mProjectionOffset.zero(); mProjectionOffsetMatrix.identity(); }
438 /// Enlarges the frustum to contain the planes generated by a project offset, if any.
439 /// Used by scene culling to ensure that all object are contained within the asymetrical frustum.
440 bool bakeProjectionOffset();
442 /// Generates a projection matrix from the frustum.
443 void getProjectionMatrix( MatrixF *proj, bool gfxRotate=true ) const;
445 /// Will update the frustum if it is dirty
446 void update() { _update(); }
447 /// @}
449 /// @name Culling
450 /// @{
452 /// Return true if the contents of the given AABB can be culled.
453 bool isCulled( const Box3F& aabb ) const { return ( testPotentialIntersection( aabb ) == GeometryOutside ); }
455 /// Return true if the contents of the given OBB can be culled.
456 bool isCulled( const OrientedBox3F& obb ) const { return ( testPotentialIntersection( obb ) == GeometryOutside ); }
458 /// Return true if the contents of the given sphere can be culled.
459 bool isCulled( const SphereF& sphere ) const { return ( testPotentialIntersection( sphere ) == GeometryOutside ); }
461 /// @}
463 /// @name Projection Type
464 /// @{
466 bool isOrtho() const { return mIsOrtho; }
468 /// @}
470 /// @name Tile settings
471 /// @{
473 U32 getNumTiles() const { return mNumTiles; }
474 const Point2I& getCurTile() const { return mCurrTile; }
475 void tileFrustum(U32 numTiles, const Point2I& curTile, Point2F overlap);
476 static void tile( F32 *left, F32 *right, F32 *top, F32 *bottom, U32 numTiles, const Point2I& curTile, Point2F overlap );
478 /// @}
481 #endif // _MATHUTIL_FRUSTUM_H_