mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 20:54:46 +00:00
223 lines
7.3 KiB
C++
223 lines
7.3 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/mPlane.h"
|
||
|
|
|
||
|
|
#include "math/mathUtils.h"
|
||
|
|
#include "math/mBox.h"
|
||
|
|
#include "math/mOrientedBox.h"
|
||
|
|
#include "math/mSphere.h"
|
||
|
|
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool PlaneF::intersect( const PlaneF& plane, Point3F& outLinePt, VectorF& outLineDir ) const
|
||
|
|
{
|
||
|
|
// Compute direction of intersection line.
|
||
|
|
outLineDir = mCross( *this, plane );
|
||
|
|
|
||
|
|
// If d is zero, the planes are parallel (and separated)
|
||
|
|
// or coincident, so they're not considered intersecting
|
||
|
|
F32 denom = mDot( outLineDir, outLineDir );
|
||
|
|
if ( denom < 0.00001f )
|
||
|
|
return false;
|
||
|
|
|
||
|
|
// Compute point on intersection line
|
||
|
|
outLinePt = - mCross( d * plane - plane.d * *this,
|
||
|
|
outLineDir ) / denom;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool PlaneF::isParallelTo( const PlaneF& plane, F32 epsilon ) const
|
||
|
|
{
|
||
|
|
F32 val = 1.0f - mFabs( mDot( *this, plane ) );
|
||
|
|
return ( val > - epsilon ) && ( val < epsilon );
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool PlaneF::isPerpendicularTo( const PlaneF& plane, F32 epsilon ) const
|
||
|
|
{
|
||
|
|
F32 val = mDot( *this, plane );
|
||
|
|
return ( val > - epsilon) && ( val < epsilon );
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
bool PlaneF::clipSegment( const Point3F& start, const Point3F& end, Point3F& outNewEnd ) const
|
||
|
|
{
|
||
|
|
// Intersect ray with plane.
|
||
|
|
|
||
|
|
F32 dist = intersect( start, end );
|
||
|
|
if( dist == PARALLEL_PLANE || dist < 0.f || dist > 1.f )
|
||
|
|
return false;
|
||
|
|
|
||
|
|
// Compute distance to point on segment.
|
||
|
|
|
||
|
|
Point3F dir = end - start;
|
||
|
|
dir *= dist;
|
||
|
|
|
||
|
|
// Compute new end point.
|
||
|
|
|
||
|
|
outNewEnd = start + dir;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
U32 PlaneF::clipPolygon( const Point3F* inVertices, U32 inNumVertices, Point3F* outVertices ) const
|
||
|
|
{
|
||
|
|
// Find the first vertex that lies on the front of the plane.
|
||
|
|
|
||
|
|
S32 start = -1;
|
||
|
|
for( U32 i = 0; i < inNumVertices; i ++ )
|
||
|
|
{
|
||
|
|
Side side = whichSide( inVertices[ i ] );
|
||
|
|
if( side == PlaneF::Front )
|
||
|
|
{
|
||
|
|
start = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// If nothing was in front of the plane, we're done.
|
||
|
|
|
||
|
|
if( start == -1 )
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
Point3F finalPoints[ 128 ];
|
||
|
|
U32 numFinalPoints = 0;
|
||
|
|
|
||
|
|
U32 baseStart = start;
|
||
|
|
U32 end = ( start + 1 ) % inNumVertices;
|
||
|
|
|
||
|
|
dMemcpy( outVertices, inVertices, inNumVertices * sizeof( Point3F ) );
|
||
|
|
|
||
|
|
while( end != baseStart )
|
||
|
|
{
|
||
|
|
const Point3F& rStartPoint = outVertices[ start ];
|
||
|
|
const Point3F& rEndPoint = outVertices[ end ];
|
||
|
|
|
||
|
|
PlaneF::Side fSide = whichSide( rStartPoint );
|
||
|
|
PlaneF::Side eSide = whichSide( rEndPoint );
|
||
|
|
|
||
|
|
S32 code = fSide * 3 + eSide;
|
||
|
|
switch( code )
|
||
|
|
{
|
||
|
|
case 4: // f f
|
||
|
|
case 3: // f o
|
||
|
|
case 1: // o f
|
||
|
|
case 0: // o o
|
||
|
|
// No Clipping required
|
||
|
|
finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
|
||
|
|
start = end;
|
||
|
|
end = ( end + 1 ) % inNumVertices;
|
||
|
|
break;
|
||
|
|
|
||
|
|
|
||
|
|
case 2: // f b
|
||
|
|
{
|
||
|
|
// In this case, we emit the front point, Insert the intersection,
|
||
|
|
// and advancing to point to first point that is in front or on...
|
||
|
|
//
|
||
|
|
finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
|
||
|
|
|
||
|
|
Point3F vector = rEndPoint - rStartPoint;
|
||
|
|
F32 t = - ( distToPlane( rStartPoint ) / mDot( *this, vector ) );
|
||
|
|
|
||
|
|
Point3F intersection = rStartPoint + ( vector * t );
|
||
|
|
finalPoints[ numFinalPoints ++ ] = intersection;
|
||
|
|
|
||
|
|
U32 endSeek = ( end + 1 ) % inNumVertices;
|
||
|
|
while( whichSide( outVertices[ endSeek ] ) == PlaneF::Back )
|
||
|
|
endSeek = ( endSeek + 1 ) % inNumVertices;
|
||
|
|
|
||
|
|
end = endSeek;
|
||
|
|
start = ( end + ( inNumVertices - 1 ) ) % inNumVertices;
|
||
|
|
|
||
|
|
const Point3F& rNewStartPoint = outVertices[ start ];
|
||
|
|
const Point3F& rNewEndPoint = outVertices[ end ];
|
||
|
|
|
||
|
|
vector = rNewEndPoint - rNewStartPoint;
|
||
|
|
t = - ( distToPlane( rNewStartPoint ) / mDot( *this, vector ) );
|
||
|
|
|
||
|
|
intersection = rNewStartPoint + ( vector * t );
|
||
|
|
outVertices[ start ] = intersection;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case -1: // o b
|
||
|
|
{
|
||
|
|
// In this case, we emit the front point, and advance to point to first
|
||
|
|
// point that is in front or on...
|
||
|
|
//
|
||
|
|
finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
|
||
|
|
|
||
|
|
U32 endSeek = ( end + 1 ) % inNumVertices;
|
||
|
|
while( whichSide( outVertices[ endSeek ] ) == PlaneF::Back)
|
||
|
|
endSeek = ( endSeek + 1 ) % inNumVertices;
|
||
|
|
|
||
|
|
end = endSeek;
|
||
|
|
start = (end + ( inNumVertices - 1 ) ) % inNumVertices;
|
||
|
|
|
||
|
|
const Point3F& rNewStartPoint = outVertices[ start ];
|
||
|
|
const Point3F& rNewEndPoint = outVertices[ end ];
|
||
|
|
|
||
|
|
Point3F vector = rNewEndPoint - rNewStartPoint;
|
||
|
|
F32 t = - ( distToPlane( rNewStartPoint ) / mDot( *this, vector ) );
|
||
|
|
|
||
|
|
Point3F intersection = rNewStartPoint + ( vector * t );
|
||
|
|
outVertices[ start ] = intersection;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case -2: // b f
|
||
|
|
case -3: // b o
|
||
|
|
case -4: // b b
|
||
|
|
// In the algorithm used here, this should never happen...
|
||
|
|
AssertISV(false, "SGUtil::clipToPlane: error in polygon clipper");
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
AssertFatal(false, "SGUtil::clipToPlane: bad outcode");
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Emit the last point.
|
||
|
|
finalPoints[ numFinalPoints ++ ] = outVertices[ start ];
|
||
|
|
AssertFatal( numFinalPoints >= 3, avar("Error, this shouldn't happen! Invalid winding in clipToPlane: %d", numFinalPoints ) );
|
||
|
|
|
||
|
|
// Copy the new rWinding, and we're set!
|
||
|
|
//
|
||
|
|
dMemcpy( outVertices, finalPoints, numFinalPoints * sizeof( Point3F ) );
|
||
|
|
AssertISV( numFinalPoints <= 128, "MaxWindingPoints exceeded in scenegraph. Fatal error.");
|
||
|
|
|
||
|
|
return numFinalPoints;
|
||
|
|
}
|