mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 12:44:46 +00:00
- Updated to work with 0.5.x SDK - Uses Oculus Rendering rather than PostFX - Stereo rendering refactored so more rendering info is grabbed from the DisplayDevice - Implements an Offscreen Canvas for in-game gui with oculus - Message dialogs and metrics display can now go to the OffScreen Canvas (if oculus demo is setup correctly)
590 lines
22 KiB
C++
590 lines
22 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.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
#include "math/util/frustum.h"
|
|
|
|
#include "math/mMathFn.h"
|
|
#include "math/mathUtils.h"
|
|
#include "math/mSphere.h"
|
|
#include "platform/profiler.h"
|
|
|
|
static const MatrixF sGFXProjRotMatrix( EulerF( (M_PI_F / 2.0f), 0.0f, 0.0f ) );
|
|
|
|
|
|
//TODO: For OBB/frustum intersections and ortho frustums, we can resort to a much quicker AABB/OBB test
|
|
|
|
|
|
// Must be CW ordered for face[0] of each edge! Keep in mind that normals
|
|
// are pointing *inwards* and thus what appears CCW outside is CW inside.
|
|
FrustumData::EdgeListType FrustumData::smEdges
|
|
(
|
|
PolyhedronData::Edge( PlaneNear, PlaneTop, NearTopRight, NearTopLeft ),
|
|
PolyhedronData::Edge( PlaneNear, PlaneBottom, NearBottomLeft, NearBottomRight ),
|
|
PolyhedronData::Edge( PlaneNear, PlaneLeft, NearTopLeft, NearBottomLeft ),
|
|
PolyhedronData::Edge( PlaneNear, PlaneRight, NearTopRight, NearBottomRight ),
|
|
PolyhedronData::Edge( PlaneFar, PlaneTop, FarTopLeft, FarTopRight ),
|
|
PolyhedronData::Edge( PlaneFar, PlaneBottom, FarBottomRight, FarBottomLeft ),
|
|
PolyhedronData::Edge( PlaneFar, PlaneLeft, FarBottomLeft, FarTopLeft ),
|
|
PolyhedronData::Edge( PlaneFar, PlaneRight, FarTopRight, FarBottomRight ),
|
|
PolyhedronData::Edge( PlaneTop, PlaneLeft, FarTopLeft, NearTopLeft ),
|
|
PolyhedronData::Edge( PlaneTop, PlaneRight, NearTopRight, FarTopRight ),
|
|
PolyhedronData::Edge( PlaneBottom, PlaneLeft, NearBottomLeft, FarBottomLeft ),
|
|
PolyhedronData::Edge( PlaneBottom, PlaneRight, FarBottomRight, NearBottomRight )
|
|
);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
Frustum::Frustum( bool isOrtho,
|
|
F32 nearLeft,
|
|
F32 nearRight,
|
|
F32 nearTop,
|
|
F32 nearBottom,
|
|
F32 nearDist,
|
|
F32 farDist,
|
|
const MatrixF &transform )
|
|
{
|
|
mTransform = transform;
|
|
mPosition = transform.getPosition();
|
|
|
|
mNearLeft = nearLeft;
|
|
mNearRight = nearRight;
|
|
mNearTop = nearTop;
|
|
mNearBottom = nearBottom;
|
|
mNearDist = nearDist;
|
|
mFarDist = farDist;
|
|
mIsOrtho = isOrtho;
|
|
|
|
mNumTiles = 1;
|
|
mCurrTile.set(0,0);
|
|
mTileOverlap.set(0.0f, 0.0f);
|
|
|
|
mProjectionOffset.zero();
|
|
mProjectionOffsetMatrix.identity();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::set( bool isOrtho,
|
|
F32 fovYInRadians,
|
|
F32 aspectRatio,
|
|
F32 nearDist,
|
|
F32 farDist,
|
|
const MatrixF &transform )
|
|
{
|
|
F32 left, right, top, bottom;
|
|
MathUtils::makeFrustum( &left, &right, &top, &bottom, fovYInRadians, aspectRatio, nearDist );
|
|
|
|
tile( &left, &right, &top, &bottom, mNumTiles, mCurrTile, mTileOverlap );
|
|
set( isOrtho, left, right, top, bottom, nearDist, farDist, transform );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::set( bool isOrtho,
|
|
F32 nearLeft,
|
|
F32 nearRight,
|
|
F32 nearTop,
|
|
F32 nearBottom,
|
|
F32 nearDist,
|
|
F32 farDist,
|
|
const MatrixF &transform )
|
|
{
|
|
mTransform = transform;
|
|
mPosition = mTransform.getPosition();
|
|
|
|
mNearLeft = nearLeft;
|
|
mNearRight = nearRight;
|
|
mNearTop = nearTop;
|
|
mNearBottom = nearBottom;
|
|
mNearDist = nearDist;
|
|
mFarDist = farDist;
|
|
mIsOrtho = isOrtho;
|
|
|
|
mDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#if 0
|
|
void Frustum::set( const MatrixF &projMat, bool normalize )
|
|
{
|
|
// From "Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix"
|
|
// by Gil Gribb and Klaus Hartmann.
|
|
//
|
|
// http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
|
|
|
|
// Right clipping plane.
|
|
mPlanes[ PlaneRight ].set( projMat[3] - projMat[0],
|
|
projMat[7] - projMat[4],
|
|
projMat[11] - projMat[8],
|
|
projMat[15] - projMat[12] );
|
|
|
|
// Left clipping plane.
|
|
mPlanes[ PlaneLeft ].set( projMat[3] + projMat[0],
|
|
projMat[7] + projMat[4],
|
|
projMat[11] + projMat[8],
|
|
projMat[15] + projMat[12] );
|
|
|
|
// Bottom clipping plane.
|
|
mPlanes[ PlaneBottom ].set( projMat[3] + projMat[1],
|
|
projMat[7] + projMat[5],
|
|
projMat[11] + projMat[9],
|
|
projMat[15] + projMat[13] );
|
|
|
|
// Top clipping plane.
|
|
mPlanes[ PlaneTop ].set( projMat[3] - projMat[1],
|
|
projMat[7] - projMat[5],
|
|
projMat[11] - projMat[9],
|
|
projMat[15] - projMat[13] );
|
|
|
|
// Near clipping plane
|
|
mPlanes[ PlaneNear ].set( projMat[3] + projMat[2],
|
|
projMat[7] + projMat[6],
|
|
projMat[11] + projMat[10],
|
|
projMat[15] + projMat[14] );
|
|
|
|
// Far clipping plane.
|
|
mPlanes[ PlaneFar ].set( projMat[3] - projMat[2],
|
|
projMat[7] - projMat[6],
|
|
projMat[11] - projMat[10],
|
|
projMat[15] - projMat[14] );
|
|
|
|
if( normalize )
|
|
{
|
|
for( S32 i = 0; i < PlaneCount; ++ i )
|
|
mPlanes[ i ].normalize();
|
|
}
|
|
|
|
/*// Create the corner points via plane intersections.
|
|
mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneLeft ], &mPoints[ NearTopLeft ] );
|
|
mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneRight ], &mPoints[ NearTopRight ] );
|
|
mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneLeft ], &mPoints[ NearBottomLeft ] );
|
|
mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneRight ], &mPoints[ NearBottomRight ] );
|
|
mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneLeft ], &mPoints[ FarTopLeft ] );
|
|
mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneRight ], &mPoints[ FarTopRight ] );
|
|
mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneLeft ], &mPoints[ FarBottomLeft ] );
|
|
mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneRight ], &mPoints[ FarBottomRight ] );
|
|
*/
|
|
|
|
// Update the axis aligned bounding box.
|
|
_updateBounds();
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::setNearDist( F32 nearDist )
|
|
{
|
|
setNearFarDist( nearDist, mFarDist );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::setFarDist( F32 farDist )
|
|
{
|
|
setNearFarDist( mNearDist, farDist );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::setNearFarDist( F32 nearDist, F32 farDist )
|
|
{
|
|
if( mNearDist == nearDist && mFarDist == farDist )
|
|
return;
|
|
|
|
// Recalculate the frustum.
|
|
MatrixF xfm( mTransform );
|
|
set( mIsOrtho, getFov(), getAspectRatio(), nearDist, farDist, xfm );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::cropNearFar(F32 newNearDist, F32 newFarDist)
|
|
{
|
|
const F32 newOverOld = newNearDist / mNearDist;
|
|
|
|
set( mIsOrtho, mNearLeft * newOverOld, mNearRight * newOverOld, mNearTop * newOverOld, mNearBottom * newOverOld,
|
|
newNearDist, newFarDist, mTransform);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool Frustum::bakeProjectionOffset()
|
|
{
|
|
// Nothing to bake if ortho
|
|
if( mIsOrtho )
|
|
return false;
|
|
|
|
// Nothing to bake if no offset
|
|
if( mProjectionOffset.isZero() )
|
|
return false;
|
|
|
|
// Near plane points in camera space
|
|
Point3F np[4];
|
|
np[0].set( mNearLeft, mNearDist, mNearTop ); // NearTopLeft
|
|
np[1].set( mNearRight, mNearDist, mNearTop ); // NearTopRight
|
|
np[2].set( mNearLeft, mNearDist, mNearBottom ); // NearBottomLeft
|
|
np[3].set( mNearRight, mNearDist, mNearBottom ); // NearBottomRight
|
|
|
|
// Generate the near plane
|
|
PlaneF nearPlane( np[0], np[1], np[3] );
|
|
|
|
// Far plane points in camera space
|
|
const F32 farOverNear = mFarDist / mNearDist;
|
|
Point3F fp0( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopLeft
|
|
Point3F fp1( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopRight
|
|
Point3F fp2( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomLeft
|
|
Point3F fp3( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomRight
|
|
|
|
// Generate the far plane
|
|
PlaneF farPlane( fp0, fp1, fp3 );
|
|
|
|
// The offset camera point
|
|
Point3F offsetCamera( mProjectionOffset.x, 0.0f, mProjectionOffset.y );
|
|
|
|
// The near plane point we'll be using for our calculations below
|
|
U32 nIndex = 0;
|
|
if( mProjectionOffset.x < 0.0 )
|
|
{
|
|
// Offset to the left so we'll need to use the near plane point on the right
|
|
nIndex = 1;
|
|
}
|
|
if( mProjectionOffset.y > 0.0 )
|
|
{
|
|
// Offset to the top so we'll need to use the near plane point at the bottom
|
|
nIndex += 2;
|
|
}
|
|
|
|
// Begin by calculating the offset point on the far plane as it goes
|
|
// from the offset camera to the edge of the near plane.
|
|
Point3F farPoint;
|
|
Point3F fdir = np[nIndex] - offsetCamera;
|
|
fdir.normalize();
|
|
if( farPlane.intersect(offsetCamera, fdir, &farPoint) )
|
|
{
|
|
// Calculate the new near plane edge from the non-offset camera position
|
|
// to the far plane point from above.
|
|
Point3F nearPoint;
|
|
Point3F ndir = farPoint;
|
|
ndir.normalize();
|
|
if( nearPlane.intersect( Point3F::Zero, ndir, &nearPoint) )
|
|
{
|
|
// Handle a x offset
|
|
if( mProjectionOffset.x < 0.0 )
|
|
{
|
|
// The new near plane right side
|
|
mNearRight = nearPoint.x;
|
|
}
|
|
else if( mProjectionOffset.x > 0.0 )
|
|
{
|
|
// The new near plane left side
|
|
mNearLeft = nearPoint.x;
|
|
}
|
|
|
|
// Handle a y offset
|
|
if( mProjectionOffset.y < 0.0 )
|
|
{
|
|
// The new near plane top side
|
|
mNearTop = nearPoint.y;
|
|
}
|
|
else if( mProjectionOffset.y > 0.0 )
|
|
{
|
|
// The new near plane bottom side
|
|
mNearBottom = nearPoint.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
mDirty = true;
|
|
|
|
// Indicate that we've modified the frustum
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FrustumData::_update() const
|
|
{
|
|
if( !mDirty )
|
|
return;
|
|
|
|
PROFILE_SCOPE( Frustum_update );
|
|
|
|
const Point3F& cameraPos = mPosition;
|
|
|
|
// Build the frustum points in camera space first.
|
|
|
|
if( mIsOrtho )
|
|
{
|
|
mPoints[ NearTopLeft ].set( mNearLeft, mNearDist, mNearTop );
|
|
mPoints[ NearTopRight ].set( mNearRight, mNearDist, mNearTop );
|
|
mPoints[ NearBottomLeft ].set( mNearLeft, mNearDist, mNearBottom );
|
|
mPoints[ NearBottomRight ].set( mNearRight, mNearDist, mNearBottom );
|
|
mPoints[ FarTopLeft ].set( mNearLeft, mFarDist, mNearTop );
|
|
mPoints[ FarTopRight ].set( mNearRight, mFarDist, mNearTop );
|
|
mPoints[ FarBottomLeft ].set( mNearLeft, mFarDist, mNearBottom );
|
|
mPoints[ FarBottomRight ].set( mNearRight, mFarDist, mNearBottom );
|
|
}
|
|
else
|
|
{
|
|
const F32 farOverNear = mFarDist / mNearDist;
|
|
|
|
mPoints[ NearTopLeft ].set( mNearLeft, mNearDist, mNearTop );
|
|
mPoints[ NearTopRight ].set( mNearRight, mNearDist, mNearTop );
|
|
mPoints[ NearBottomLeft ].set( mNearLeft, mNearDist, mNearBottom );
|
|
mPoints[ NearBottomRight ].set( mNearRight, mNearDist, mNearBottom );
|
|
mPoints[ FarTopLeft ].set( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear );
|
|
mPoints[ FarTopRight ].set( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear );
|
|
mPoints[ FarBottomLeft ].set( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear );
|
|
mPoints[ FarBottomRight ].set( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear );
|
|
}
|
|
|
|
// Transform the points into the desired culling space.
|
|
|
|
for( U32 i = 0; i < mPoints.size(); ++ i )
|
|
mTransform.mulP( mPoints[ i ] );
|
|
|
|
// Update the axis aligned bounding box from
|
|
// the newly transformed points.
|
|
|
|
mBounds = Box3F::aroundPoints( mPoints.address(), mPoints.size() );
|
|
|
|
// Finally build the planes.
|
|
|
|
if( mIsOrtho )
|
|
{
|
|
mPlanes[ PlaneLeft ].set( mPoints[ NearBottomLeft ],
|
|
mPoints[ FarTopLeft ],
|
|
mPoints[ FarBottomLeft ] );
|
|
|
|
mPlanes[ PlaneRight ].set( mPoints[ NearTopRight ],
|
|
mPoints[ FarBottomRight ],
|
|
mPoints[ FarTopRight ] );
|
|
|
|
mPlanes[ PlaneTop ].set( mPoints[ FarTopRight ],
|
|
mPoints[ NearTopLeft ],
|
|
mPoints[ NearTopRight ] );
|
|
|
|
mPlanes[ PlaneBottom ].set( mPoints[ NearBottomRight ],
|
|
mPoints[ FarBottomLeft ],
|
|
mPoints[ FarBottomRight ] );
|
|
|
|
mPlanes[ PlaneNear ].set( mPoints[ NearTopLeft ],
|
|
mPoints[ NearBottomLeft ],
|
|
mPoints[ NearTopRight ] );
|
|
|
|
mPlanes[ PlaneFar ].set( mPoints[ FarTopLeft ],
|
|
mPoints[ FarTopRight ],
|
|
mPoints[ FarBottomLeft ] );
|
|
}
|
|
else
|
|
{
|
|
mPlanes[ PlaneLeft ].set( cameraPos,
|
|
mPoints[ NearTopLeft ],
|
|
mPoints[ NearBottomLeft ] );
|
|
|
|
mPlanes[ PlaneRight ].set( cameraPos,
|
|
mPoints[ NearBottomRight ],
|
|
mPoints[ NearTopRight ] );
|
|
|
|
mPlanes[ PlaneTop ].set( cameraPos,
|
|
mPoints[ NearTopRight ],
|
|
mPoints[ NearTopLeft ] );
|
|
|
|
mPlanes[ PlaneBottom ].set( cameraPos,
|
|
mPoints[ NearBottomLeft ],
|
|
mPoints[ NearBottomRight ] );
|
|
|
|
mPlanes[ PlaneNear ].set( mPoints[ NearTopLeft ],
|
|
mPoints[ NearBottomLeft ],
|
|
mPoints[ NearTopRight ] );
|
|
|
|
mPlanes[ PlaneFar ].set( mPoints[ FarTopLeft ],
|
|
mPoints[ FarTopRight ],
|
|
mPoints[ FarBottomLeft ] );
|
|
}
|
|
|
|
// If the frustum plane orientation doesn't match mIsInverted
|
|
// now, invert all the plane normals.
|
|
//
|
|
// Note that if we have a transform matrix with a negative scale,
|
|
// then the initial planes we have computed will always be inverted.
|
|
|
|
const bool inverted = mPlanes[ PlaneNear ].whichSide( cameraPos ) == PlaneF::Front;
|
|
if( inverted != mIsInverted )
|
|
{
|
|
for( U32 i = 0; i < mPlanes.size(); ++ i )
|
|
mPlanes[ i ].invert();
|
|
}
|
|
|
|
AssertFatal( mPlanes[ PlaneNear ].whichSide( cameraPos ) != PlaneF::Front,
|
|
"Frustum::_update - Viewpoint lies on front side of near plane!" );
|
|
|
|
// And now the center points which are mostly just used in debug rendering.
|
|
|
|
mPlaneCenters[ PlaneLeftCenter ] = ( mPoints[ NearTopLeft ] +
|
|
mPoints[ NearBottomLeft ] +
|
|
mPoints[ FarTopLeft ] +
|
|
mPoints[ FarBottomLeft ] ) / 4.0f;
|
|
|
|
mPlaneCenters[ PlaneRightCenter ] = ( mPoints[ NearTopRight ] +
|
|
mPoints[ NearBottomRight ] +
|
|
mPoints[ FarTopRight ] +
|
|
mPoints[ FarBottomRight ] ) / 4.0f;
|
|
|
|
mPlaneCenters[ PlaneTopCenter ] = ( mPoints[ NearTopLeft ] +
|
|
mPoints[ NearTopRight ] +
|
|
mPoints[ FarTopLeft ] +
|
|
mPoints[ FarTopRight ] ) / 4.0f;
|
|
|
|
mPlaneCenters[ PlaneBottomCenter ] = ( mPoints[ NearBottomLeft ] +
|
|
mPoints[ NearBottomRight ] +
|
|
mPoints[ FarBottomLeft ] +
|
|
mPoints[ FarBottomRight ] ) / 4.0f;
|
|
|
|
mPlaneCenters[ PlaneNearCenter ] = ( mPoints[ NearTopLeft ] +
|
|
mPoints[ NearTopRight ] +
|
|
mPoints[ NearBottomLeft ] +
|
|
mPoints[ NearBottomRight ] ) / 4.0f;
|
|
|
|
mPlaneCenters[ PlaneFarCenter ] = ( mPoints[ FarTopLeft ] +
|
|
mPoints[ FarTopRight ] +
|
|
mPoints[ FarBottomLeft ] +
|
|
mPoints[ FarBottomRight ] ) / 4.0f;
|
|
|
|
// Done.
|
|
|
|
mDirty = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::invert()
|
|
{
|
|
mIsInverted = !mIsInverted;
|
|
_update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::setTransform( const MatrixF &mat )
|
|
{
|
|
mTransform = mat;
|
|
mPosition = mTransform.getPosition();
|
|
mDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::scaleFromCenter( F32 scale )
|
|
{
|
|
// Extract the fov and aspect ratio.
|
|
F32 fovInRadians = mAtan2( (mNearTop - mNearBottom)*mNumTiles/2.0f, mNearDist ) * 2.0f;
|
|
F32 aspectRatio = (mNearRight - mNearLeft)/(mNearTop - mNearBottom);
|
|
|
|
// Now move the near and far planes out.
|
|
F32 halfDist = ( mFarDist - mNearDist ) / 2.0f;
|
|
mNearDist -= halfDist * ( scale - 1.0f );
|
|
mFarDist += halfDist * ( scale - 1.0f );
|
|
|
|
// Setup the new scaled frustum.
|
|
set( mIsOrtho, fovInRadians, aspectRatio, mNearDist, mFarDist, mTransform );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::mul( const MatrixF& mat )
|
|
{
|
|
mTransform.mul( mat );
|
|
mDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::mulL( const MatrixF& mat )
|
|
{
|
|
MatrixF last( mTransform );
|
|
mTransform.mul( mat, last );
|
|
|
|
mDirty = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::setProjectionOffset(const Point2F& offsetMat)
|
|
{
|
|
mProjectionOffset = offsetMat;
|
|
mProjectionOffsetMatrix.identity();
|
|
mProjectionOffsetMatrix.setPosition(Point3F(mProjectionOffset.x, mProjectionOffset.y, 0.0f));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::getProjectionMatrix( MatrixF *proj, bool gfxRotate ) const
|
|
{
|
|
if (mIsOrtho)
|
|
{
|
|
MathUtils::makeOrthoProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate);
|
|
proj->mulL(mProjectionOffsetMatrix);
|
|
}
|
|
else
|
|
{
|
|
MathUtils::makeProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate);
|
|
proj->mulL(mProjectionOffsetMatrix);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::tileFrustum(U32 numTiles, const Point2I& curTile, Point2F overlap)
|
|
{
|
|
//These will be stored to re-tile the frustum if needed
|
|
mNumTiles = numTiles;
|
|
mCurrTile = curTile;
|
|
mTileOverlap = overlap;
|
|
|
|
tile(&mNearLeft, &mNearRight, &mNearTop, &mNearBottom, mNumTiles, mCurrTile, mTileOverlap);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Frustum::tile( F32 *left, F32 *right, F32 *top, F32 *bottom, U32 numTiles, const Point2I& curTile, Point2F overlap )
|
|
{
|
|
if (numTiles == 1)
|
|
return;
|
|
|
|
Point2F tileSize( ( *right - *left ) / (F32)numTiles,
|
|
( *top - *bottom ) / (F32)numTiles );
|
|
|
|
F32 leftOffset = tileSize.x*overlap.x;
|
|
F32 rightOffset = tileSize.x*overlap.x*2;
|
|
F32 bottomOffset = tileSize.y*overlap.y;
|
|
F32 topOffset = tileSize.y*overlap.y*2;
|
|
|
|
*left += tileSize.x * curTile.x - leftOffset;
|
|
*right = *left + tileSize.x + rightOffset;
|
|
*bottom += tileSize.y * curTile.y - bottomOffset;
|
|
*top = *bottom + tileSize.y + topOffset;
|
|
}
|