mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 06:34:36 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
475
Engine/source/math/util/frustum.cpp
Normal file
475
Engine/source/math/util/frustum.cpp
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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::getProjectionMatrix( MatrixF *proj, bool gfxRotate ) const
|
||||
{
|
||||
if (mIsOrtho)
|
||||
MathUtils::makeOrthoProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate);
|
||||
else
|
||||
MathUtils::makeProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
443
Engine/source/math/util/frustum.h
Normal file
443
Engine/source/math/util/frustum.h
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
/// @}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
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; }
|
||||
|
||||
/// Generates a projection matrix from the frustum.
|
||||
void getProjectionMatrix( MatrixF *proj, bool gfxRotate=true ) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @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_
|
||||
50
Engine/source/math/util/matrixSet.cpp
Normal file
50
Engine/source/math/util/matrixSet.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/matrixSet.h"
|
||||
|
||||
|
||||
MatrixSet::MatrixSet()
|
||||
{
|
||||
// [9/4/2009 Pat] Until we get better control over heap allocations in Torque
|
||||
// this class will provide a place where aligned/specalized matrix math can take place.
|
||||
// We should be able to plug in any kind of platform-specific optimization
|
||||
// behind the delgates.
|
||||
AssertFatal( ((int)this & 0xF) == 0, "MatrixSet has been allocated off a 16-byte boundary!" );
|
||||
|
||||
// Must be initialized by name, not a for(), it's macro magic
|
||||
MATRIX_SET_BIND_VALUE(ObjectToWorld);
|
||||
MATRIX_SET_BIND_VALUE(WorldToCamera);
|
||||
MATRIX_SET_BIND_VALUE(CameraToScreen);
|
||||
MATRIX_SET_BIND_VALUE(ObjectToCamera);
|
||||
MATRIX_SET_BIND_VALUE(WorldToObject);
|
||||
MATRIX_SET_BIND_VALUE(CameraToWorld);
|
||||
MATRIX_SET_BIND_VALUE(ObjectToScreen);
|
||||
MATRIX_SET_BIND_VALUE(CameraToObject);
|
||||
MATRIX_SET_BIND_VALUE(WorldToScreen);
|
||||
MATRIX_SET_BIND_VALUE(SceneView);
|
||||
MATRIX_SET_BIND_VALUE(SceneProjection);
|
||||
|
||||
mViewSource = NULL;
|
||||
mProjectionSource = NULL;
|
||||
}
|
||||
165
Engine/source/math/util/matrixSet.h
Normal file
165
Engine/source/math/util/matrixSet.h
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _MATRIXSET_H_
|
||||
#define _MATRIXSET_H_
|
||||
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "math/mMatrix.h"
|
||||
#endif
|
||||
#ifndef _UTIL_DELEGATE_H_
|
||||
#include "core/util/delegate.h"
|
||||
#endif
|
||||
#ifndef _MATRIXSETDELEGATES_H_
|
||||
#include "math/util/matrixSetDelegateMethods.h"
|
||||
#endif
|
||||
|
||||
|
||||
dALIGN_BEGIN
|
||||
|
||||
class MatrixSet
|
||||
{
|
||||
typedef Delegate<const MatrixF &()> MatrixEvalDelegate;
|
||||
enum _Transforms
|
||||
{
|
||||
ObjectToWorld = 0, // World
|
||||
WorldToCamera, // View
|
||||
CameraToScreen, // Projection
|
||||
ObjectToScreen, // World * View * Proj
|
||||
ObjectToCamera, // World * View
|
||||
WorldToObject, // World^-1
|
||||
CameraToWorld, // View^-1
|
||||
CameraToObject, // (World * View)^-1
|
||||
WorldToScreen, // View * Projection
|
||||
SceneView, // The View matrix for the SceneState
|
||||
SceneProjection, // The Projection matrix for the SceneState
|
||||
NumTransforms,
|
||||
};
|
||||
|
||||
MatrixF mTransform[NumTransforms];
|
||||
MatrixEvalDelegate mEvalDelegate[NumTransforms];
|
||||
|
||||
const MatrixF *mViewSource;
|
||||
const MatrixF *mProjectionSource;
|
||||
|
||||
MATRIX_SET_GET_VALUE(ObjectToWorld);
|
||||
MATRIX_SET_GET_VALUE(WorldToCamera);
|
||||
MATRIX_SET_GET_VALUE(CameraToScreen);
|
||||
MATRIX_SET_GET_VALUE(ObjectToCamera);
|
||||
MATRIX_SET_GET_VALUE(WorldToObject);
|
||||
MATRIX_SET_GET_VALUE(CameraToWorld);
|
||||
MATRIX_SET_GET_VALUE(ObjectToScreen);
|
||||
MATRIX_SET_GET_VALUE(CameraToObject);
|
||||
MATRIX_SET_GET_VALUE(WorldToScreen);
|
||||
MATRIX_SET_GET_VALUE(SceneView);
|
||||
MATRIX_SET_GET_VALUE(SceneProjection);
|
||||
|
||||
MATRIX_SET_IS_INVERSE_OF(WorldToObject, ObjectToWorld);
|
||||
MATRIX_SET_IS_INVERSE_OF(CameraToWorld, WorldToCamera);
|
||||
|
||||
MATRIX_SET_MULT_ASSIGN(WorldToCamera, ObjectToWorld, ObjectToCamera);
|
||||
MATRIX_SET_IS_INVERSE_OF(CameraToObject, ObjectToCamera);
|
||||
|
||||
MATRIX_SET_MULT_ASSIGN(CameraToScreen, WorldToCamera, WorldToScreen);
|
||||
|
||||
MATRIX_SET_MULT_ASSIGN(WorldToScreen, ObjectToWorld, ObjectToScreen);
|
||||
|
||||
public:
|
||||
MatrixSet();
|
||||
|
||||
// Direct accessors
|
||||
inline const MatrixF &getObjectToWorld() const { return mTransform[ObjectToWorld]; }
|
||||
inline const MatrixF &getWorldToCamera() const { return mTransform[WorldToCamera]; }
|
||||
inline const MatrixF &getCameraToScreen() const { return mTransform[CameraToScreen]; }
|
||||
|
||||
// Delegate driven, lazy-evaluation accessors
|
||||
inline const MatrixF &getWorldToScreen() const { return mEvalDelegate[WorldToScreen](); }
|
||||
inline const MatrixF &getWorldViewProjection() const { return mEvalDelegate[ObjectToScreen](); }
|
||||
inline const MatrixF &getWorldToObject() const { return mEvalDelegate[WorldToObject](); }
|
||||
inline const MatrixF &getCameraToWorld() const { return mEvalDelegate[CameraToWorld](); }
|
||||
inline const MatrixF &getObjectToCamera() const { return mEvalDelegate[ObjectToCamera](); }
|
||||
inline const MatrixF &getCameraToObject() const { return mEvalDelegate[CameraToObject](); }
|
||||
|
||||
// Assignment for the world/view/projection matrices
|
||||
inline void setWorld(const MatrixF &world)
|
||||
{
|
||||
mTransform[ObjectToWorld] = world;
|
||||
mEvalDelegate[WorldToObject].bind(this, &MatrixSet::MATRIX_SET_IS_INVERSE_OF_FN(WorldToObject, ObjectToWorld));
|
||||
mEvalDelegate[ObjectToScreen].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(WorldToScreen, ObjectToWorld, ObjectToScreen));
|
||||
mEvalDelegate[ObjectToCamera].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(WorldToCamera, ObjectToWorld, ObjectToCamera));
|
||||
mEvalDelegate[CameraToObject].bind(this, &MatrixSet::MATRIX_SET_IS_INVERSE_OF_FN(CameraToObject, ObjectToCamera));
|
||||
}
|
||||
|
||||
inline void setView(const MatrixF &view)
|
||||
{
|
||||
if(&view == mViewSource)
|
||||
return;
|
||||
|
||||
mViewSource = &view;
|
||||
mTransform[WorldToCamera] = view;
|
||||
mEvalDelegate[CameraToWorld].bind(this, &MatrixSet::MATRIX_SET_IS_INVERSE_OF_FN(CameraToWorld, WorldToCamera));
|
||||
mEvalDelegate[ObjectToScreen].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(WorldToScreen, ObjectToWorld, ObjectToScreen));
|
||||
mEvalDelegate[WorldToScreen].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(CameraToScreen, WorldToCamera, WorldToScreen));
|
||||
mEvalDelegate[ObjectToCamera].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(WorldToCamera, ObjectToWorld, ObjectToCamera));
|
||||
mEvalDelegate[CameraToObject].bind(this, &MatrixSet::MATRIX_SET_IS_INVERSE_OF_FN(CameraToObject, ObjectToCamera));
|
||||
}
|
||||
|
||||
inline void setProjection(const MatrixF &projection)
|
||||
{
|
||||
if(&projection == mProjectionSource)
|
||||
return;
|
||||
|
||||
mProjectionSource = &projection;
|
||||
mTransform[CameraToScreen] = projection;
|
||||
mEvalDelegate[ObjectToScreen].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(WorldToScreen, ObjectToWorld, ObjectToScreen));
|
||||
mEvalDelegate[WorldToScreen].bind(this, &MatrixSet::MATRIX_SET_MULT_ASSIGN_FN(CameraToScreen, WorldToCamera, WorldToScreen));
|
||||
}
|
||||
|
||||
void setSceneView(const MatrixF &view)
|
||||
{
|
||||
mViewSource = NULL;
|
||||
setView(view);
|
||||
mViewSource = &mTransform[WorldToCamera];
|
||||
mTransform[SceneView] = view;
|
||||
}
|
||||
|
||||
void setSceneProjection(const MatrixF &projection)
|
||||
{
|
||||
mProjectionSource = NULL;
|
||||
setProjection(projection);
|
||||
mProjectionSource = &mTransform[CameraToScreen];
|
||||
mTransform[SceneProjection] = projection;
|
||||
}
|
||||
|
||||
void restoreSceneViewProjection()
|
||||
{
|
||||
mViewSource = NULL;
|
||||
mProjectionSource = NULL;
|
||||
setView(mTransform[SceneView]);
|
||||
setProjection(mTransform[SceneProjection]);
|
||||
mViewSource = &mTransform[WorldToCamera];
|
||||
mProjectionSource = &mTransform[CameraToScreen];
|
||||
}
|
||||
}
|
||||
|
||||
dALIGN_END;
|
||||
|
||||
#endif // _MATRIXSET_H_
|
||||
48
Engine/source/math/util/matrixSetDelegateMethods.h
Normal file
48
Engine/source/math/util/matrixSetDelegateMethods.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _MATRIXSETDELEGATES_H_
|
||||
#define _MATRIXSETDELEGATES_H_
|
||||
|
||||
// Access to the direct value
|
||||
#define MATRIX_SET_GET_VALUE_FN(xfm) _transform_##xfm
|
||||
#define MATRIX_SET_GET_VALUE(xfm) inline const MatrixF &MATRIX_SET_GET_VALUE_FN(xfm)() { return mTransform[xfm]; }
|
||||
#define MATRIX_SET_BIND_VALUE(xfm) mEvalDelegate[xfm].bind(this, &MatrixSet::MATRIX_SET_GET_VALUE_FN(xfm))
|
||||
|
||||
#define MATRIX_SET_IS_INVERSE_OF_FN(inv_xfm, src_xfm) _##inv_xfm##_is_inverse_of_##src_xfm
|
||||
#define MATRIX_SET_IS_INVERSE_OF(inv_xfm, src_xfm) inline const MatrixF &MATRIX_SET_IS_INVERSE_OF_FN(inv_xfm, src_xfm)() \
|
||||
{ \
|
||||
m_matF_invert_to(mEvalDelegate[src_xfm](), mTransform[inv_xfm]); \
|
||||
MATRIX_SET_BIND_VALUE(inv_xfm); \
|
||||
return mTransform[inv_xfm]; \
|
||||
}
|
||||
|
||||
|
||||
#define MATRIX_SET_MULT_ASSIGN_FN(matA, matB, matC) _##matC##_is_##matA##_x_##matB
|
||||
#define MATRIX_SET_MULT_ASSIGN(matA, matB, matC) inline const MatrixF &MATRIX_SET_MULT_ASSIGN_FN(matA, matB, matC)() \
|
||||
{ \
|
||||
m_matF_x_matF_aligned(mEvalDelegate[matA](), mEvalDelegate[matB](), mTransform[matC]); \
|
||||
MATRIX_SET_BIND_VALUE(matC); \
|
||||
return mTransform[matC]; \
|
||||
}
|
||||
|
||||
|
||||
#endif // _MATRIXSETDELEGATES_H_
|
||||
165
Engine/source/math/util/quadTransforms.cpp
Normal file
165
Engine/source/math/util/quadTransforms.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/quadTransforms.h"
|
||||
|
||||
|
||||
BiQuadToSqr::BiQuadToSqr( const Point2F &p00,
|
||||
const Point2F &p10,
|
||||
const Point2F &p11,
|
||||
const Point2F &p01 )
|
||||
: m_kP00( p00 )
|
||||
{
|
||||
m_kB = p10 - p00 ; // width
|
||||
m_kC = p01 - p00; // height
|
||||
m_kD = p11 + p00 - p10 - p01; // diagonal dist
|
||||
|
||||
if(mFabs(m_kD.x) < POINT_EPSILON)
|
||||
m_kD.x = 0.f;
|
||||
if(mFabs(m_kD.y) < POINT_EPSILON)
|
||||
m_kD.y = 0.f;
|
||||
|
||||
m_fBC = mDotPerp( m_kB, m_kC );
|
||||
m_fBD = mDotPerp( m_kB, m_kD );
|
||||
m_fCD = mDotPerp( m_kC, m_kD );
|
||||
}
|
||||
|
||||
Point2F BiQuadToSqr::transform( const Point2F &p ) const
|
||||
{
|
||||
Point2F kA = m_kP00 - p;
|
||||
|
||||
F32 fAB = mDotPerp( kA, m_kB );
|
||||
F32 fAC = mDotPerp( kA, m_kC);
|
||||
|
||||
// 0 = ac*bc+(bc^2+ac*bd-ab*cd)*s+bc*bd*s^2 = k0 + k1*s + k2*s^2
|
||||
F32 fK0 = fAC*m_fBC;
|
||||
F32 fK1 = m_fBC*m_fBC + fAC*m_fBD - fAB*m_fCD;
|
||||
F32 fK2 = m_fBC*m_fBD;
|
||||
|
||||
if (mFabs(fK2) > POINT_EPSILON)
|
||||
{
|
||||
// s-equation is quadratic
|
||||
F32 fInv = 0.5f/fK2;
|
||||
F32 fDiscr = fK1*fK1 - 4.0f*fK0*fK2;
|
||||
F32 fRoot = mSqrt( mFabs(fDiscr) );
|
||||
|
||||
Point2F kResult0( 0, 0 );
|
||||
kResult0.x = (-fK1 - fRoot)*fInv;
|
||||
kResult0.y = fAB/(m_fBC + m_fBD*kResult0.x);
|
||||
F32 fDeviation0 = deviation(kResult0);
|
||||
if ( fDeviation0 == 0.0f )
|
||||
return kResult0;
|
||||
|
||||
Point2F kResult1( 0, 0 );
|
||||
kResult1.x = (-fK1 + fRoot)*fInv;
|
||||
kResult1.y = fAB/(m_fBC + m_fBD*kResult1.x);
|
||||
F32 fDeviation1 = deviation(kResult1);
|
||||
if ( fDeviation1 == 0.0f )
|
||||
return kResult1;
|
||||
|
||||
if (fDeviation0 <= fDeviation1)
|
||||
{
|
||||
if ( fDeviation0 < POINT_EPSILON )
|
||||
return kResult0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( fDeviation1 < POINT_EPSILON )
|
||||
return kResult1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// s-equation is linear
|
||||
Point2F kResult( 0, 0 );
|
||||
|
||||
kResult.x = -fK0/fK1;
|
||||
kResult.y = fAB/(m_fBC + m_fBD*kResult.x);
|
||||
F32 fDeviation = deviation(kResult);
|
||||
if ( fDeviation < POINT_EPSILON )
|
||||
return kResult;
|
||||
}
|
||||
|
||||
// point is outside the quadrilateral, return invalid
|
||||
return Point2F(F32_MAX,F32_MAX);
|
||||
}
|
||||
|
||||
F32 BiQuadToSqr::deviation( const Point2F &sp )
|
||||
{
|
||||
// deviation is the squared distance of the point from the unit square
|
||||
F32 fDeviation = 0.0f;
|
||||
F32 fDelta;
|
||||
|
||||
if (sp.x < 0.0f)
|
||||
{
|
||||
fDeviation += sp.x*sp.x;
|
||||
}
|
||||
else if (sp.x > 1.0f)
|
||||
{
|
||||
fDelta = sp.x - 1.0f;
|
||||
fDeviation += fDelta*fDelta;
|
||||
}
|
||||
|
||||
if (sp.y < 0.0f)
|
||||
{
|
||||
fDeviation += sp.y*sp.y;
|
||||
}
|
||||
else if (sp.y > 1.0f)
|
||||
{
|
||||
fDelta = sp.y - 1.0f;
|
||||
fDeviation += fDelta*fDelta;
|
||||
}
|
||||
|
||||
return fDeviation;
|
||||
}
|
||||
|
||||
|
||||
BiSqrToQuad3D::BiSqrToQuad3D( const Point3F& pnt00,
|
||||
const Point3F& pnt10,
|
||||
const Point3F& pnt11,
|
||||
const Point3F& pnt01)
|
||||
{
|
||||
p00 = pnt00;
|
||||
p10 = pnt10;
|
||||
p11 = pnt11;
|
||||
p01 = pnt01;
|
||||
}
|
||||
|
||||
Point3F BiSqrToQuad3D::transform( const Point2F &p ) const
|
||||
{
|
||||
//Let p00, p10, p01, and p11 be your 3-tuples that are the quad's
|
||||
//vertices. You can parameterize the quad as follows.
|
||||
|
||||
//q(s,t) = (1-s)*((1-t)*p00 + t*p01) + s*((1-t)*p10 + t*p11)
|
||||
|
||||
//for 0 <= s <= 1 and 0 <= t <= 1. Notice that q(0,0) = p00,
|
||||
//q(1,0) = p10, q(0,1) = p01, and q(1,1) = p11, so the parameter
|
||||
//"square" whose points are (s,t) will be mapped to the quad.
|
||||
|
||||
const F32 &s = p.x;
|
||||
const F32 &t = p.y;
|
||||
|
||||
Point3F result = (1.0f-s)*((1.0f-t)*p00 + t*p01) + s*((1.0f-t)*p10 + t*p11);
|
||||
return result;
|
||||
}
|
||||
|
||||
82
Engine/source/math/util/quadTransforms.h
Normal file
82
Engine/source/math/util/quadTransforms.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _QUADTOQUADTRANSFORMS_H_
|
||||
#define _QUADTOQUADTRANSFORMS_H_
|
||||
|
||||
#ifndef _MPOINT2_H_
|
||||
#include "math/mPoint2.h"
|
||||
#endif
|
||||
#ifndef _MPOINT3_H_
|
||||
#include "math/mPoint3.h"
|
||||
#endif
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "math/mMatrix.h"
|
||||
#endif
|
||||
|
||||
// NOTE: The code in these classes originate from the Wild Magic Source Code
|
||||
// library by David Eberly and is used with permission.
|
||||
|
||||
|
||||
/// This class does bilinear mapping of quadrilateral to a square.
|
||||
class BiQuadToSqr
|
||||
{
|
||||
public:
|
||||
|
||||
/// Constructs the transform class from the quadrilateral
|
||||
/// points in counter clockwise order.
|
||||
BiQuadToSqr( const Point2F &p00,
|
||||
const Point2F &p10,
|
||||
const Point2F &p11,
|
||||
const Point2F &p01 );
|
||||
|
||||
/// Transforms the point.
|
||||
Point2F transform( const Point2F &p ) const;
|
||||
|
||||
protected:
|
||||
|
||||
static F32 deviation( const Point2F &sp );
|
||||
|
||||
Point2F m_kP00, m_kB, m_kC, m_kD;
|
||||
|
||||
F32 m_fBC, m_fBD, m_fCD;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class BiSqrToQuad3D
|
||||
{
|
||||
public:
|
||||
|
||||
BiSqrToQuad3D( const Point3F &pnt00,
|
||||
const Point3F &pnt10,
|
||||
const Point3F &pnt11,
|
||||
const Point3F &pnt01 );
|
||||
|
||||
Point3F transform( const Point2F &pnt ) const;
|
||||
|
||||
protected:
|
||||
|
||||
Point3F p00, p01, p10, p11;
|
||||
};
|
||||
|
||||
#endif // _QUADTOQUADTRANSFORMS_H_
|
||||
250
Engine/source/math/util/sphereMesh.cpp
Normal file
250
Engine/source/math/util/sphereMesh.cpp
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "math/util/sphereMesh.h"
|
||||
|
||||
SphereMesh::SphereMesh(U32 baseType)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mDetails);
|
||||
|
||||
switch(baseType)
|
||||
{
|
||||
case Tetrahedron:
|
||||
mDetails.push_back(createTetrahedron());
|
||||
break;
|
||||
|
||||
case Octahedron:
|
||||
mDetails.push_back(createOctahedron());
|
||||
break;
|
||||
|
||||
case Icosahedron:
|
||||
mDetails.push_back(createIcosahedron());
|
||||
break;
|
||||
}
|
||||
calcNormals(mDetails[0]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SphereMesh::TriangleMesh * SphereMesh::createTetrahedron()
|
||||
{
|
||||
const F32 sqrt3 = 0.5773502692f;
|
||||
|
||||
static Point3F spherePnts[] = {
|
||||
Point3F( sqrt3, sqrt3, sqrt3 ),
|
||||
Point3F(-sqrt3,-sqrt3, sqrt3 ),
|
||||
Point3F(-sqrt3, sqrt3,-sqrt3 ),
|
||||
Point3F( sqrt3,-sqrt3,-sqrt3 )
|
||||
};
|
||||
|
||||
static Triangle tetrahedron[] = {
|
||||
Triangle(spherePnts[0], spherePnts[1], spherePnts[2]),
|
||||
Triangle(spherePnts[0], spherePnts[3], spherePnts[1]),
|
||||
Triangle(spherePnts[2], spherePnts[1], spherePnts[3]),
|
||||
Triangle(spherePnts[3], spherePnts[0], spherePnts[2]),
|
||||
};
|
||||
|
||||
static TriangleMesh tetrahedronMesh = {
|
||||
Tetrahedron,
|
||||
&tetrahedron[0]
|
||||
};
|
||||
|
||||
return(&tetrahedronMesh);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SphereMesh::TriangleMesh * SphereMesh::createOctahedron()
|
||||
{
|
||||
//
|
||||
static Point3F spherePnts[] = {
|
||||
Point3F( 1, 0, 0),
|
||||
Point3F(-1, 0, 0),
|
||||
Point3F( 0, 1, 0),
|
||||
Point3F( 0,-1, 0),
|
||||
Point3F( 0, 0, 1),
|
||||
Point3F( 0, 0,-1)
|
||||
};
|
||||
|
||||
//
|
||||
static Triangle octahedron[] = {
|
||||
Triangle(spherePnts[0], spherePnts[4], spherePnts[2]),
|
||||
Triangle(spherePnts[2], spherePnts[4], spherePnts[1]),
|
||||
Triangle(spherePnts[1], spherePnts[4], spherePnts[3]),
|
||||
Triangle(spherePnts[3], spherePnts[4], spherePnts[0]),
|
||||
Triangle(spherePnts[0], spherePnts[2], spherePnts[5]),
|
||||
Triangle(spherePnts[2], spherePnts[1], spherePnts[5]),
|
||||
Triangle(spherePnts[1], spherePnts[3], spherePnts[5]),
|
||||
Triangle(spherePnts[3], spherePnts[0], spherePnts[5])
|
||||
};
|
||||
|
||||
//
|
||||
static TriangleMesh octahedronMesh = {
|
||||
Octahedron,
|
||||
&octahedron[0]
|
||||
};
|
||||
|
||||
return(&octahedronMesh);
|
||||
}
|
||||
|
||||
SphereMesh::TriangleMesh * SphereMesh::createIcosahedron()
|
||||
{
|
||||
const F32 tau = 0.8506508084f;
|
||||
const F32 one = 0.5257311121f;
|
||||
|
||||
static Point3F spherePnts[] = {
|
||||
Point3F( tau, one, 0),
|
||||
Point3F(-tau, one, 0),
|
||||
Point3F(-tau,-one, 0),
|
||||
Point3F( tau,-one, 0),
|
||||
Point3F( one, 0, tau),
|
||||
Point3F( one, 0,-tau),
|
||||
Point3F(-one, 0,-tau),
|
||||
Point3F(-one, 0, tau),
|
||||
Point3F( 0, tau, one),
|
||||
Point3F( 0,-tau, one),
|
||||
Point3F( 0,-tau,-one),
|
||||
Point3F( 0, tau,-one),
|
||||
};
|
||||
|
||||
static Triangle icosahedron[] = {
|
||||
Triangle(spherePnts[4], spherePnts[8], spherePnts[7]),
|
||||
Triangle(spherePnts[4], spherePnts[7], spherePnts[9]),
|
||||
Triangle(spherePnts[5], spherePnts[6], spherePnts[11]),
|
||||
Triangle(spherePnts[5], spherePnts[10], spherePnts[6]),
|
||||
Triangle(spherePnts[0], spherePnts[4], spherePnts[3]),
|
||||
Triangle(spherePnts[0], spherePnts[3], spherePnts[5]),
|
||||
Triangle(spherePnts[2], spherePnts[7], spherePnts[1]),
|
||||
Triangle(spherePnts[2], spherePnts[1], spherePnts[6]),
|
||||
Triangle(spherePnts[8], spherePnts[0], spherePnts[11]),
|
||||
Triangle(spherePnts[8], spherePnts[11], spherePnts[1]),
|
||||
Triangle(spherePnts[9], spherePnts[10], spherePnts[3]),
|
||||
Triangle(spherePnts[9], spherePnts[2], spherePnts[10]),
|
||||
Triangle(spherePnts[8], spherePnts[4], spherePnts[0]),
|
||||
Triangle(spherePnts[11], spherePnts[0], spherePnts[5]),
|
||||
Triangle(spherePnts[4], spherePnts[9], spherePnts[3]),
|
||||
Triangle(spherePnts[5], spherePnts[3], spherePnts[10]),
|
||||
Triangle(spherePnts[7], spherePnts[8], spherePnts[1]),
|
||||
Triangle(spherePnts[6], spherePnts[1], spherePnts[11]),
|
||||
Triangle(spherePnts[7], spherePnts[2], spherePnts[9]),
|
||||
Triangle(spherePnts[6], spherePnts[10], spherePnts[2]),
|
||||
};
|
||||
|
||||
static TriangleMesh icosahedronMesh = {
|
||||
Icosahedron,
|
||||
&icosahedron[0]
|
||||
};
|
||||
|
||||
return(&icosahedronMesh);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SphereMesh::calcNormals(TriangleMesh * mesh)
|
||||
{
|
||||
for(U32 i = 0; i < mesh->numPoly; i++)
|
||||
{
|
||||
Triangle & tri = mesh->poly[i];
|
||||
mCross(tri.pnt[1] - tri.pnt[0], tri.pnt[2] - tri.pnt[0], &tri.normal);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SphereMesh::~SphereMesh()
|
||||
{
|
||||
// level 0 is static data
|
||||
for(U32 i = 1; i < mDetails.size(); i++)
|
||||
{
|
||||
delete [] mDetails[i]->poly;
|
||||
delete mDetails[i];
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const SphereMesh::TriangleMesh * SphereMesh::getMesh(U32 level)
|
||||
{
|
||||
AssertFatal(mDetails.size(), "SphereMesh::getMesh: no details!");
|
||||
|
||||
if(level > MaxLevel)
|
||||
level = MaxLevel;
|
||||
|
||||
//
|
||||
while(mDetails.size() <= level)
|
||||
mDetails.push_back(subdivideMesh(mDetails.last()));
|
||||
|
||||
return(mDetails[level]);
|
||||
}
|
||||
|
||||
SphereMesh::TriangleMesh * SphereMesh::subdivideMesh(TriangleMesh * prevMesh)
|
||||
{
|
||||
AssertFatal(prevMesh, "SphereMesh::subdivideMesh: invalid previous mesh level!");
|
||||
|
||||
//
|
||||
TriangleMesh * mesh = new TriangleMesh;
|
||||
|
||||
mesh->numPoly = prevMesh->numPoly * 4;
|
||||
mesh->poly = new Triangle [mesh->numPoly];
|
||||
|
||||
//
|
||||
for(U32 i = 0; i < prevMesh->numPoly; i++)
|
||||
{
|
||||
Triangle * pt = &prevMesh->poly[i];
|
||||
Triangle * nt = &mesh->poly[i*4];
|
||||
|
||||
Point3F a = (pt->pnt[0] + pt->pnt[2]) / 2;
|
||||
Point3F b = (pt->pnt[0] + pt->pnt[1]) / 2;
|
||||
Point3F c = (pt->pnt[1] + pt->pnt[2]) / 2;
|
||||
|
||||
// force the point onto the unit sphere surface
|
||||
a.normalize();
|
||||
b.normalize();
|
||||
c.normalize();
|
||||
|
||||
//
|
||||
nt->pnt[0] = pt->pnt[0];
|
||||
nt->pnt[1] = b;
|
||||
nt->pnt[2] = a;
|
||||
nt++;
|
||||
|
||||
//
|
||||
nt->pnt[0] = b;
|
||||
nt->pnt[1] = pt->pnt[1];
|
||||
nt->pnt[2] = c;
|
||||
nt++;
|
||||
|
||||
//
|
||||
nt->pnt[0] = a;
|
||||
nt->pnt[1] = b;
|
||||
nt->pnt[2] = c;
|
||||
nt++;
|
||||
|
||||
//
|
||||
nt->pnt[0] = a;
|
||||
nt->pnt[1] = c;
|
||||
nt->pnt[2] = pt->pnt[2];
|
||||
}
|
||||
|
||||
calcNormals(mesh);
|
||||
return(mesh);
|
||||
}
|
||||
88
Engine/source/math/util/sphereMesh.h
Normal file
88
Engine/source/math/util/sphereMesh.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _SPHEREMESH_H_
|
||||
#define _SPHEREMESH_H_
|
||||
|
||||
#ifndef _MMATH_H_
|
||||
#include "math/mMath.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class: SphereMesh
|
||||
//------------------------------------------------------------------------------
|
||||
// * ctor takes type of base polyhedron that is subdivided to create sphere
|
||||
// * getMesh(...) will subdivide the current mesh to the desired level where
|
||||
// (each level has 4 times the polys of the previous level)
|
||||
|
||||
class SphereMesh
|
||||
{
|
||||
public:
|
||||
|
||||
// regular polyhedra with triangle face polygons (num of faces)
|
||||
enum {
|
||||
Tetrahedron = 4,
|
||||
Octahedron = 8,
|
||||
Icosahedron = 20,
|
||||
|
||||
MaxLevel = 5
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
Triangle() {}
|
||||
Triangle(const Point3F &a, const Point3F &b, const Point3F &c)
|
||||
{
|
||||
pnt[0] = a;
|
||||
pnt[1] = b;
|
||||
pnt[2] = c;
|
||||
}
|
||||
|
||||
Point3F pnt[3];
|
||||
Point3F normal;
|
||||
};
|
||||
|
||||
struct TriangleMesh {
|
||||
U32 numPoly;
|
||||
Triangle * poly;
|
||||
};
|
||||
|
||||
SphereMesh(U32 baseType = Octahedron);
|
||||
~SphereMesh();
|
||||
|
||||
const TriangleMesh * getMesh(U32 level = 0);
|
||||
|
||||
private:
|
||||
|
||||
TriangleMesh * createTetrahedron();
|
||||
TriangleMesh * createOctahedron();
|
||||
TriangleMesh * createIcosahedron();
|
||||
|
||||
Vector<TriangleMesh*> mDetails;
|
||||
|
||||
void calcNormals(TriangleMesh *);
|
||||
TriangleMesh * subdivideMesh(TriangleMesh*);
|
||||
};
|
||||
|
||||
#endif
|
||||
79
Engine/source/math/util/tResponseCurve.cpp
Normal file
79
Engine/source/math/util/tResponseCurve.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "tResponseCurve.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT( SimResponseCurve );
|
||||
|
||||
ConsoleDocClass( SimResponseCurve,
|
||||
"@brief A ResponseCurve<F32> wrapped as a SimObject.\n\n"
|
||||
"Currently no applied use, not network ready, not intended "
|
||||
"for game development, for editors or internal use only.\n\n "
|
||||
"@internal");
|
||||
|
||||
SimResponseCurve::SimResponseCurve()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool SimResponseCurve::onAdd()
|
||||
{
|
||||
if ( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimResponseCurve::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void SimResponseCurve::addPoint(F32 value, F32 time)
|
||||
{
|
||||
mCurve.addPoint( value, time );
|
||||
}
|
||||
|
||||
F32 SimResponseCurve::getValue(F32 time)
|
||||
{
|
||||
return mCurve.getVal( time );
|
||||
}
|
||||
|
||||
void SimResponseCurve::clear()
|
||||
{
|
||||
mCurve.clear();
|
||||
}
|
||||
|
||||
ConsoleMethod( SimResponseCurve, addPoint, void, 4, 4, "addPoint( F32 value, F32 time )" )
|
||||
{
|
||||
object->addPoint( dAtof(argv[2]), dAtof(argv[3]) );
|
||||
}
|
||||
|
||||
ConsoleMethod( SimResponseCurve, getValue, F32, 3, 3, "getValue( F32 time )" )
|
||||
{
|
||||
return object->getValue( dAtof(argv[2]) );
|
||||
}
|
||||
|
||||
ConsoleMethod( SimResponseCurve, clear, void, 2, 2, "clear()" )
|
||||
{
|
||||
object->clear();
|
||||
}
|
||||
247
Engine/source/math/util/tResponseCurve.h
Normal file
247
Engine/source/math/util/tResponseCurve.h
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Notice:
|
||||
// Some of this code originates from an article in AI Game Programming Wisdom
|
||||
// by Dave Mark.
|
||||
|
||||
#ifndef _TRESPONSECURVE_H_
|
||||
#define _TRESPONSECURVE_H_
|
||||
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
|
||||
#ifndef _MMATHFN_H_
|
||||
#include "math/mMathFn.h"
|
||||
#endif
|
||||
|
||||
#ifndef _SIMOBJECT_H_
|
||||
#include "console/simObject.h"
|
||||
#endif
|
||||
|
||||
|
||||
// -------------------------------
|
||||
// Represents a sigmoid function
|
||||
// Note: not used by ResponseCurve
|
||||
// -------------------------------
|
||||
|
||||
class Sigmoid
|
||||
{
|
||||
public:
|
||||
Sigmoid( F32 s, F32 m) { _s = s; _m = m; }
|
||||
~Sigmoid() {};
|
||||
|
||||
inline F32 get( F32 x )
|
||||
{
|
||||
F32 pow = -2.0f * ( ( x - _m ) / _s );
|
||||
F32 y = 1.0f / mPow( 1 + M_CONST_E_F, pow );
|
||||
return y;
|
||||
}
|
||||
|
||||
F32 _s;
|
||||
F32 _m;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Represents a response curve, can query values
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template< class T >
|
||||
class ResponseCurve
|
||||
{
|
||||
public:
|
||||
|
||||
struct Sample
|
||||
{
|
||||
Sample() {}
|
||||
Sample( F32 f, const T &val ) : mF(f), mVal(val) {}
|
||||
|
||||
F32 mF;
|
||||
T mVal;
|
||||
};
|
||||
|
||||
typedef Vector< Sample > SampleList;
|
||||
SampleList mSamples;
|
||||
|
||||
const SampleList& getSamples() { return mSamples; }
|
||||
|
||||
ResponseCurve() {}
|
||||
ResponseCurve( U32 numSamples ) { mSamples.reserve(numSamples); }
|
||||
|
||||
void clear() { mSamples.clear(); }
|
||||
void addPoint( F32 f, const T &val );
|
||||
//void addPoints( U32 count, F32 f[], const T &val[] );
|
||||
T getVal( F32 f ) const;
|
||||
S32 setPoint( S32 idx, F32 f, const T &val );
|
||||
void removePoint( S32 idx );
|
||||
S32 getSampleCount() const { return mSamples.size(); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds a new value to the Response Curve, at the position f
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline void ResponseCurve<T>::addPoint( F32 f, const T &val )
|
||||
{
|
||||
typename SampleList::iterator iter = mSamples.begin();
|
||||
for ( ; iter != mSamples.end(); iter++ )
|
||||
{
|
||||
if ( iter->mF == f )
|
||||
{
|
||||
Con::warnf( "Warn: ResponseCurve<T>::AddPoint, Duplicate values are not allowed." );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( iter->mF > f )
|
||||
break;
|
||||
}
|
||||
|
||||
mSamples.insert( iter, Sample( f, val ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds the right value at position f, interpolating between the previous
|
||||
// and the following values
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline T ResponseCurve<T>::getVal( F32 f ) const
|
||||
{
|
||||
T retVal;
|
||||
|
||||
if ( mSamples.empty() )
|
||||
{
|
||||
retVal = T();
|
||||
}
|
||||
else
|
||||
{
|
||||
U32 nSamples = mSamples.size();
|
||||
if ( nSamples == 1 || f <= mSamples[0].mF )
|
||||
{
|
||||
retVal = mSamples[0].mVal;
|
||||
}
|
||||
else if ( f >= mSamples[nSamples-1].mF )
|
||||
{
|
||||
retVal = mSamples[nSamples-1].mVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
U32 i = 1;
|
||||
while ( i < (nSamples-1) && mSamples[i].mF < f )
|
||||
++i;
|
||||
|
||||
// Interpolate between m_Samples[i-1] and m_Samples[i]
|
||||
F32 fSampleMin = mSamples[i-1].mF;
|
||||
F32 fSampleMax = mSamples[i].mF;
|
||||
AssertWarn(fSampleMin != fSampleMax, "fSampleMin should not equal fSampleMax" );
|
||||
|
||||
F32 t = (f - fSampleMin) / (fSampleMax - fSampleMin);
|
||||
retVal = mSamples[i-1].mVal + ( mSamples[i].mVal - mSamples[i-1].mVal) * t;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline S32 ResponseCurve< T >::setPoint( S32 idx, F32 f, const T &val )
|
||||
{
|
||||
mSamples.erase( idx );
|
||||
|
||||
typename SampleList::iterator iter = mSamples.begin();
|
||||
for ( ; iter != mSamples.end(); iter++ )
|
||||
{
|
||||
if ( iter->mF == f )
|
||||
{
|
||||
Con::warnf( "Warn: ResponseCurve<T>::AddPoint, Duplicate values are not allowed." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( iter->mF > f )
|
||||
break;
|
||||
}
|
||||
|
||||
mSamples.insert( iter, Sample( f, val ) );
|
||||
|
||||
return (S32)( iter - mSamples.begin() );
|
||||
}
|
||||
|
||||
|
||||
class FloatCurve : public ResponseCurve<F32>
|
||||
{
|
||||
public:
|
||||
FloatCurve() {}
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------
|
||||
// A ResponseCurve<F32> wrapped as a SimObject
|
||||
// -----------------------------------------------
|
||||
|
||||
class SimResponseCurve : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
|
||||
SimResponseCurve();
|
||||
//~SimResponseCurve();
|
||||
|
||||
DECLARE_CONOBJECT( SimResponseCurve );
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
void addPoint( F32 value, F32 time );
|
||||
F32 getValue( F32 time );
|
||||
void clear();
|
||||
|
||||
ResponseCurve<F32> mCurve;
|
||||
};
|
||||
|
||||
|
||||
// A networked-datablock version of ResponseCurve
|
||||
/*
|
||||
class ResponseCurveData : public SimDataBlock
|
||||
{
|
||||
typedef SimDataBlock Parent;
|
||||
|
||||
public:
|
||||
|
||||
ResponseCurveData();
|
||||
//~ResponseCurveData();
|
||||
|
||||
DECLARE_CONOBJECT( ResponseCurveData );
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
|
||||
void addPoint( F32 value, F32 time );
|
||||
F32 getValue( F32 time );
|
||||
void clear();
|
||||
|
||||
ResponseCurve<F32> mCurve;
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue