mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
- Frustum comparison now includes comparing the projection offset. - Fixes objects that only set the projection matrix if the frustum has changed during side-by-side rendering, such as the WaterPlane.
466 lines
14 KiB
C++
466 lines
14 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef _MATHUTIL_FRUSTUM_H_
|
|
#define _MATHUTIL_FRUSTUM_H_
|
|
|
|
#ifndef _MPOLYHEDRON_H_
|
|
#include "math/mPolyhedron.h"
|
|
#endif
|
|
|
|
#ifndef _MBOX_H_
|
|
#include "math/mBox.h"
|
|
#endif
|
|
|
|
#ifndef _MPLANE_H_
|
|
#include "math/mPlane.h"
|
|
#endif
|
|
|
|
#ifndef _MMATRIX_H_
|
|
#include "math/mMatrix.h"
|
|
#endif
|
|
|
|
#ifndef _MQUAT_H_
|
|
#include "math/mQuat.h"
|
|
#endif
|
|
|
|
#ifndef _MSPHERE_H_
|
|
#include "math/mSphere.h"
|
|
#endif
|
|
|
|
|
|
//TODO: Specialize intersection tests for frustums using octant tests
|
|
|
|
|
|
class OrientedBox3F;
|
|
|
|
|
|
/// Polyhedron data for use by frustums. Uses fixed-size vectors
|
|
/// and a static vector for the edge list as that never changes
|
|
/// between frustums.
|
|
struct FrustumData : public PolyhedronData
|
|
{
|
|
enum
|
|
{
|
|
EdgeCount = 12
|
|
};
|
|
|
|
/// Indices for the planes in a frustum.
|
|
///
|
|
/// Note the planes are ordered left, right, near,
|
|
/// far, top, bottom for getting early rejections
|
|
/// from the typical horizontal scene.
|
|
enum
|
|
{
|
|
PlaneLeft,
|
|
PlaneRight,
|
|
PlaneNear,
|
|
PlaneFar,
|
|
PlaneTop,
|
|
PlaneBottom,
|
|
|
|
/// The total number of frustum planes.
|
|
PlaneCount
|
|
};
|
|
|
|
/// Indices for the corner points of the frustum.
|
|
enum CornerPoints
|
|
{
|
|
NearTopLeft,
|
|
NearTopRight,
|
|
NearBottomLeft,
|
|
NearBottomRight,
|
|
FarTopLeft,
|
|
FarTopRight,
|
|
FarBottomLeft,
|
|
FarBottomRight,
|
|
|
|
/// Total number of corner points.
|
|
CornerPointCount
|
|
};
|
|
|
|
/// Indices for the center points of the frustum planes.
|
|
enum PlaneCenters
|
|
{
|
|
PlaneLeftCenter,
|
|
PlaneRightCenter,
|
|
PlaneTopCenter,
|
|
PlaneBottomCenter,
|
|
PlaneNearCenter,
|
|
PlaneFarCenter,
|
|
};
|
|
|
|
/// Used to mask out planes for testing.
|
|
enum
|
|
{
|
|
PlaneMaskLeft = ( 1 << PlaneLeft ),
|
|
PlaneMaskRight = ( 1 << PlaneRight ),
|
|
PlaneMaskTop = ( 1 << PlaneTop ),
|
|
PlaneMaskBottom = ( 1 << PlaneBottom ),
|
|
PlaneMaskNear = ( 1 << PlaneNear ),
|
|
PlaneMaskFar = ( 1 << PlaneFar ),
|
|
|
|
PlaneMaskAll = 0xFFFFFFFF,
|
|
};
|
|
|
|
typedef FixedSizeVector< PlaneF, PlaneCount > PlaneListType;
|
|
typedef FixedSizeVector< Point3F, CornerPointCount > PointListType;
|
|
typedef FixedSizeVector< Edge, EdgeCount > EdgeListType;
|
|
|
|
protected:
|
|
|
|
/// @name Lazily Updated Data
|
|
/// @{
|
|
|
|
/// When true, points, planes and bounds must be re-calculated before use.
|
|
mutable bool mDirty;
|
|
|
|
mutable PlaneListType mPlanes;
|
|
mutable PointListType mPoints;
|
|
|
|
/// The center points of the individual faces of the frustum.
|
|
mutable Point3F mPlaneCenters[ PlaneCount ];
|
|
|
|
/// The clipping-space axis-aligned bounding box which contains
|
|
/// the extents of the frustum.
|
|
mutable Box3F mBounds;
|
|
|
|
/// @}
|
|
|
|
/// Static edge list. Shared by all frustum polyhedrons
|
|
/// since they are always constructed the same way.
|
|
static EdgeListType smEdges;
|
|
|
|
/// Determines whether this Frustum
|
|
/// is orthographic or perspective.
|
|
bool mIsOrtho;
|
|
|
|
/// Whether the frustum is inverted, i.e. whether the planes are
|
|
/// facing outwards rather than inwards.
|
|
bool mIsInverted;
|
|
|
|
/// Used to transform the frustum points from camera
|
|
/// space into the desired clipping space.
|
|
MatrixF mTransform;
|
|
|
|
/// Camera position extracted from tarnsform.
|
|
Point3F mPosition;
|
|
|
|
/// The size of the near plane used to generate
|
|
/// the frustum points and planes.
|
|
F32 mNearLeft;
|
|
F32 mNearRight;
|
|
F32 mNearTop;
|
|
F32 mNearBottom;
|
|
F32 mNearDist;
|
|
F32 mFarDist;
|
|
|
|
/// Update the point and plane data from the current frustum settings.
|
|
void _update() const;
|
|
|
|
FrustumData()
|
|
: mDirty( false ),
|
|
mIsInverted( false ) {}
|
|
|
|
public:
|
|
|
|
/// @name Accessors
|
|
/// @{
|
|
|
|
/// Return the number of planes that a frustum has.
|
|
static U32 getNumPlanes() { return PlaneCount; }
|
|
|
|
/// Return the planes that make up the polyhedron.
|
|
/// @note The normals of these planes are facing *inwards*.
|
|
const PlaneF* getPlanes() const { _update(); return mPlanes.address(); }
|
|
|
|
/// Return the number of corner points that a frustum has.
|
|
static U32 getNumPoints() { return CornerPointCount; }
|
|
|
|
///
|
|
const Point3F* getPoints() const { _update(); return mPoints.address(); }
|
|
|
|
/// Return the number of edges that a frustum has.
|
|
static U32 getNumEdges() { return EdgeCount; }
|
|
|
|
/// Return the edge definitions for a frustum.
|
|
static const Edge* getEdges() { return smEdges.address(); }
|
|
|
|
/// @}
|
|
|
|
operator AnyPolyhedron() const
|
|
{
|
|
return AnyPolyhedron(
|
|
AnyPolyhedron::PlaneListType( const_cast< PlaneF* >( getPlanes() ), getNumPlanes() ),
|
|
AnyPolyhedron::PointListType( const_cast< Point3F* >( getPoints() ), getNumPoints() ),
|
|
AnyPolyhedron::EdgeListType( const_cast< Edge* >( getEdges() ), getNumEdges() )
|
|
);
|
|
}
|
|
};
|
|
|
|
|
|
/// This class implements a view frustum for use in culling scene objects and
|
|
/// rendering the scene.
|
|
///
|
|
/// @warn Frustums are always non-inverted by default which means that even if
|
|
/// the frustum transform applies a negative scale, the frustum will still be
|
|
/// non-inverted.
|
|
class Frustum : public PolyhedronImpl< FrustumData >
|
|
{
|
|
public:
|
|
|
|
typedef PolyhedronImpl< FrustumData > Parent;
|
|
|
|
protected:
|
|
|
|
/// @name Tiling
|
|
/// @{
|
|
|
|
/// Number of subdivisions.
|
|
U32 mNumTiles;
|
|
|
|
/// Current rendering tile.
|
|
Point2I mCurrTile;
|
|
|
|
/// Tile overlap percentage.
|
|
Point2F mTileOverlap;
|
|
|
|
/// @}
|
|
|
|
/// Offset used for projection matrix calculations
|
|
Point2F mProjectionOffset;
|
|
|
|
/// The calculated projection offset matrix
|
|
MatrixF mProjectionOffsetMatrix;
|
|
|
|
public:
|
|
|
|
/// @name Constructors
|
|
/// @{
|
|
|
|
/// Construct a non-inverted frustum.
|
|
///
|
|
/// @note If the given transform has a negative scale, the plane
|
|
/// normals will automatically be inverted so that the frustum
|
|
/// will still be non-inverted. Use invert() to actually cause
|
|
/// the frustum to be inverted.
|
|
Frustum( bool orthographic = false,
|
|
F32 nearLeft = -1.0f,
|
|
F32 nearRight = 1.0f,
|
|
F32 nearTop = 1.0f,
|
|
F32 nearBottom = -1.0f,
|
|
F32 nearDist = 0.1f,
|
|
F32 farDist = 1.0f,
|
|
const MatrixF &transform = MatrixF( true ) );
|
|
|
|
/// @}
|
|
|
|
|
|
/// @name Operators
|
|
/// @{
|
|
|
|
bool operator==( const Frustum& frustum ) const
|
|
{
|
|
return ( ( mNearLeft == frustum.mNearLeft ) &&
|
|
( mNearTop == frustum.mNearTop ) &&
|
|
( mNearBottom == frustum.mNearBottom ) &&
|
|
( mNearDist == frustum.mNearDist ) &&
|
|
( mFarDist == frustum.mFarDist ) &&
|
|
( mProjectionOffset.x == frustum.mProjectionOffset.x ) &&
|
|
( mProjectionOffset.y == frustum.mProjectionOffset.y ) );
|
|
|
|
}
|
|
bool operator!=( const Frustum& frustum ) const { return !( *this == frustum ); }
|
|
|
|
/// @}
|
|
|
|
|
|
/// @name Initialization
|
|
///
|
|
/// Functions used to initialize the frustum.
|
|
///
|
|
/// @{
|
|
|
|
/// Sets the frustum from the field of view, screen aspect
|
|
/// ratio, and the near and far distances. You can pass an
|
|
/// matrix to transform the frustum.
|
|
void set( bool isOrtho,
|
|
F32 fovYInRadians,
|
|
F32 aspectRatio,
|
|
F32 nearDist,
|
|
F32 farDist,
|
|
const MatrixF &mat = MatrixF( true ) );
|
|
|
|
/// Sets the frustum from the near plane dimensions and
|
|
/// near and far distances.
|
|
void set( bool isOrtho,
|
|
F32 nearLeft,
|
|
F32 nearRight,
|
|
F32 nearTop,
|
|
F32 nearBottom,
|
|
F32 nearDist,
|
|
F32 farDist,
|
|
const MatrixF &transform = MatrixF( true ) );
|
|
|
|
/// Sets the frustum by extracting the planes from a projection,
|
|
/// view-projection, or world-view-projection matrix.
|
|
//void set( const MatrixF& projMatrix, bool normalize );
|
|
|
|
/// Changes the near distance of the frustum.
|
|
void setNearDist( F32 nearDist );
|
|
|
|
/// Changes the far distance of the frustum.
|
|
void setFarDist( F32 farDist );
|
|
|
|
/// Changes the near and far distance of the frustum.
|
|
void setNearFarDist( F32 nearDist, F32 farDist );
|
|
|
|
///
|
|
void cropNearFar(F32 newNearDist, F32 newFarDist);
|
|
|
|
/// Returns the far clip distance used to create
|
|
/// the frustum planes.
|
|
F32 getFarDist() const { return mFarDist; }
|
|
|
|
/// Returns the far clip distance used to create
|
|
/// the frustum planes.
|
|
F32 getNearDist() const { return mNearDist; }
|
|
|
|
/// Return the camera-space minimum X coordinate on the near plane.
|
|
F32 getNearLeft() const { return mNearLeft; }
|
|
|
|
/// Return the camera-space maximum X coordinate on the near plane.
|
|
F32 getNearRight() const { return mNearRight; }
|
|
|
|
/// Return the camera-space maximum Z coordinate on the near plane.
|
|
F32 getNearTop() const { return mNearTop; }
|
|
|
|
/// Return the camera-space minimum Z coordinate on the near plane.
|
|
F32 getNearBottom() const { return mNearBottom; }
|
|
|
|
/// Return the camera-space width of the frustum.
|
|
F32 getWidth() const { return mFabs( mNearRight - mNearLeft ); }
|
|
|
|
/// Return the camera-space height of the frustum.
|
|
F32 getHeight() const { return mFabs( mNearTop - mNearBottom ); }
|
|
|
|
///
|
|
F32 getFov() const
|
|
{
|
|
F32 nonTiledHeight = getHeight()*mNumTiles;
|
|
return mAtan2( nonTiledHeight/2.0f, mNearDist ) * 2.0f;
|
|
}
|
|
|
|
///
|
|
F32 getAspectRatio() const { return (mNearRight - mNearLeft)/(mNearTop - mNearBottom); }
|
|
|
|
/// @}
|
|
|
|
|
|
/// @name Transformation
|
|
///
|
|
/// These functions for transforming the frustum from
|
|
/// one space to another.
|
|
///
|
|
/// @{
|
|
|
|
/// Sets a new transform for the frustum.
|
|
void setTransform( const MatrixF &transform );
|
|
|
|
/// Returns the current transform matrix for the frustum.
|
|
const MatrixF& getTransform() const { return mTransform; }
|
|
|
|
/// Scales up the frustum from its center point.
|
|
void scaleFromCenter( F32 scale );
|
|
|
|
/// Transforms the frustum by F = F * mat.
|
|
void mul( const MatrixF &mat );
|
|
|
|
/// Transforms the frustum by F = mat * F.
|
|
void mulL( const MatrixF &mat );
|
|
|
|
/// Flip the plane normals which has the result
|
|
/// of reversing the culling results.
|
|
void invert();
|
|
|
|
/// Returns true if the frustum planes point outwards.
|
|
bool isInverted() const { return mIsInverted; }
|
|
|
|
/// Returns the origin point of the frustum.
|
|
const Point3F& getPosition() const { return mPosition; }
|
|
|
|
/// Returns the axis aligned bounding box of the frustum
|
|
/// points typically used for early rejection.
|
|
const Box3F& getBounds() const { _update(); return mBounds; }
|
|
|
|
/// Get the offset used when calculating the projection matrix
|
|
const Point2F& getProjectionOffset() const { return mProjectionOffset; }
|
|
|
|
/// Get the offset matrix used when calculating the projection matrix
|
|
const MatrixF& getProjectionOffsetMatrix() const { return mProjectionOffsetMatrix; }
|
|
|
|
/// Set the offset used when calculating the projection matrix
|
|
void setProjectionOffset(const Point2F& offsetMat);
|
|
|
|
/// Clear any offset used when calculating the projection matrix
|
|
void clearProjectionOffset() { mProjectionOffset.zero(); mProjectionOffsetMatrix.identity(); }
|
|
|
|
/// Generates a projection matrix from the frustum.
|
|
void getProjectionMatrix( MatrixF *proj, bool gfxRotate=true ) const;
|
|
|
|
/// Will update the frustum if it is dirty
|
|
void update() { _update(); }
|
|
/// @}
|
|
|
|
/// @name Culling
|
|
/// @{
|
|
|
|
/// Return true if the contents of the given AABB can be culled.
|
|
bool isCulled( const Box3F& aabb ) const { return ( testPotentialIntersection( aabb ) == GeometryOutside ); }
|
|
|
|
/// Return true if the contents of the given OBB can be culled.
|
|
bool isCulled( const OrientedBox3F& obb ) const { return ( testPotentialIntersection( obb ) == GeometryOutside ); }
|
|
|
|
/// Return true if the contents of the given sphere can be culled.
|
|
bool isCulled( const SphereF& sphere ) const { return ( testPotentialIntersection( sphere ) == GeometryOutside ); }
|
|
|
|
/// @}
|
|
|
|
/// @name Projection Type
|
|
/// @{
|
|
|
|
bool isOrtho() const { return mIsOrtho; }
|
|
|
|
/// @}
|
|
|
|
/// @name Tile settings
|
|
/// @{
|
|
|
|
U32 getNumTiles() const { return mNumTiles; }
|
|
const Point2I& getCurTile() const { return mCurrTile; }
|
|
void tileFrustum(U32 numTiles, const Point2I& curTile, Point2F overlap);
|
|
static void tile( F32 *left, F32 *right, F32 *top, F32 *bottom, U32 numTiles, const Point2I& curTile, Point2F overlap );
|
|
|
|
/// @}
|
|
};
|
|
|
|
#endif // _MATHUTIL_FRUSTUM_H_
|