2013-11-06 22:52:00 +01:00
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// Created by Dan Andersson 2013
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-11-12 12:33:52 +01:00
|
|
|
#include "OysterCollision3D.h"
|
2013-11-06 22:52:00 +01:00
|
|
|
#include "Utilities.h"
|
|
|
|
#include <limits>
|
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
using namespace ::Oyster::Math3D;
|
|
|
|
using namespace ::Utility::Value;
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
namespace Oyster { namespace Collision3D { namespace Utility
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
// PRIVATE HEADER ///////////////////////////////////////////////////
|
|
|
|
namespace Private
|
|
|
|
{
|
|
|
|
const Float epsilon = (const Float)1e-20;
|
|
|
|
|
|
|
|
// Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
|
2013-11-10 02:27:16 +01:00
|
|
|
inline bool EqualsZero( const Float &value )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
return Abs( value ) < epsilon;
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
|
2013-11-10 02:27:16 +01:00
|
|
|
inline bool NotEqualsZero( const Float &value )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
return Abs( value ) > epsilon;
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns true if miss/reject
|
2013-11-10 02:27:16 +01:00
|
|
|
bool BoxVsRayPerSlabCheck( const Float3 &axis, const Float &boundingOffset, const Float3 &deltaPos, const Float3 rayDirection, Float &tMin, Float &tMax )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
Float e = axis.Dot( deltaPos ),
|
|
|
|
f = axis.Dot( rayDirection );
|
|
|
|
if( EqualsZero(f) ) // if axis is not parallell with ray
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
Float t1 = e + boundingOffset,
|
|
|
|
t2 = e - boundingOffset;
|
|
|
|
t1 /= f; t2 /= f;
|
2013-11-10 02:27:16 +01:00
|
|
|
if( t1 > t2 ) ::Utility::Element::Swap( t1, t2 );
|
2013-11-20 16:58:56 +01:00
|
|
|
tMin = Max( tMin, t1 );
|
|
|
|
tMax = Min( tMax, t2 );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( tMin > tMax ) return true;
|
|
|
|
if( tMax < 0.0f ) return true;
|
|
|
|
}
|
|
|
|
else if( boundingOffset < -e ) return true;
|
|
|
|
else if( boundingOffset < e ) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
inline bool Contains( const Plane &container, const Float3 &pos )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
return EqualsZero( container.normal.Dot( pos ) + container.phasing );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
inline void Compare( Float &connectOffset, const Plane &plane, const Float3 &pos )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
connectOffset = plane.normal.Dot(pos);
|
2013-11-06 22:52:00 +01:00
|
|
|
connectOffset += plane.phasing;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
void Compare( Float &boxExtend, Float ¢erDistance, const Plane &plane, const BoxAxisAligned &box )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float3 c = (box.maxVertex + box.minVertex) * 0.5f, // box.Center
|
|
|
|
h = (box.maxVertex - box.minVertex) * 0.5f; // box.halfSize
|
2013-11-20 16:58:56 +01:00
|
|
|
boxExtend = h.x * Abs(plane.normal.x); // Box max extending towards plane
|
|
|
|
boxExtend += h.y * Abs(plane.normal.y);
|
|
|
|
boxExtend += h.z * Abs(plane.normal.z);
|
2013-11-10 02:27:16 +01:00
|
|
|
centerDistance = c.Dot(plane.normal) + plane.phasing; // distance between box center and plane
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
void Compare( Float &boxExtend, Float ¢erDistance, const Plane &plane, const Box &box )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
boxExtend = box.boundingOffset.x * Abs(plane.normal.Dot(box.xAxis)); // Box max extending towards plane
|
|
|
|
boxExtend += box.boundingOffset.y * Abs(plane.normal.Dot(box.yAxis));
|
|
|
|
boxExtend += box.boundingOffset.z * Abs(plane.normal.Dot(box.zAxis));
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
centerDistance = box.center.Dot(plane.normal) + plane.phasing; // distance between box center and plane
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float3 &boundingOffsetA, const Float3 &boundingOffsetB, const Float4x4 &rotationB, const Float3 &worldOffset )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
|
|
* Uses the Seperating Axis Theorem
|
|
|
|
* if( |t dot s| > hA dot |s * RA| + hB dot |s * RB| ) then not intersecting
|
|
|
|
* |t dot s| > hA dot |s| + hB dot |s * RB| .. as RA = I
|
|
|
|
*
|
|
|
|
* t: objectB's offset from objectA [worldOffset]
|
|
|
|
* s: current comparison axis
|
|
|
|
* hA: boundingReach vector of objectA. Only absolute values is assumed. [boundingOffsetA]
|
|
|
|
* hB: boundingReach vector of objectB. Only absolute values is assumed. [boundingOffsetB]
|
|
|
|
* RA: rotation matrix of objectA. Is identity matrix here, thus omitted.
|
|
|
|
* RB: rotation matrix of objectB. Is transformed into objectA's view at this point. [rotationB]
|
|
|
|
*
|
|
|
|
* Note: s * RB = (RB^T * s)^T = (RB^-1 * s)^T .... vector == vector^T
|
|
|
|
*****************************************************************/
|
|
|
|
|
|
|
|
Float4x4 absRotationB = Abs(rotationB);
|
|
|
|
Float3 absWorldOffset = Abs(worldOffset); // |t|: [absWorldOffset]
|
|
|
|
|
|
|
|
// s = { 1, 0, 0 } [ RA.v[0] ]
|
|
|
|
if( absWorldOffset.x > boundingOffsetA.x + boundingOffsetB.Dot(Float3(absRotationB.v[0].x, absRotationB.v[1].x, absRotationB.v[2].x)) )
|
|
|
|
{ // |t dot s| > hA dot |s| + hB dot |s * RB| -->> t.x > hA.x + hB dot |{RB.v[0].x, RB.v[1].x, RB.v[2].x}|
|
|
|
|
return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
// s = { 0, 1, 0 } [ RA.v[1] ]
|
|
|
|
if( absWorldOffset.y > boundingOffsetA.y + boundingOffsetB.Dot(Float3(absRotationB.v[0].y, absRotationB.v[1].y, absRotationB.v[2].y)) )
|
|
|
|
{ // t.y > hA.y + hB dot |{RB.v[0].y, RB.v[1].y, RB.v[2].y}|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s = { 0, 0, 1 } [ RA.v[2] ]
|
|
|
|
if( absWorldOffset.z > boundingOffsetA.z + boundingOffsetB.Dot(Float3(absRotationB.v[0].z, absRotationB.v[1].z, absRotationB.v[2].z)) )
|
|
|
|
{ // t.z > hA.z + hB dot |{RB.v[0].z, RB.v[1].z, RB.v[2].z}|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s = RB.v[0].xyz
|
|
|
|
if( Abs(worldOffset.Dot(rotationB.v[0].xyz)) > boundingOffsetA.Dot(absRotationB.v[0].xyz) + boundingOffsetB.x )
|
|
|
|
{ // |t dot s| > hA dot |s| + hB dot |s * RB| -->> |t dot s| > hA dot |s| + hB dot |{1, 0, 0}| -->> |t dot s| > hA dot |s| + hB.x
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s = RB.v[1].xyz
|
|
|
|
if( Abs(worldOffset.Dot(rotationB.v[1].xyz)) > boundingOffsetA.Dot(absRotationB.v[1].xyz) + boundingOffsetB.y )
|
|
|
|
{ // |t dot s| > hA dot |s| + hB.y
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s = RB.v[2].xyz
|
|
|
|
if( Abs(worldOffset.Dot(rotationB.v[2].xyz)) > boundingOffsetA.Dot(absRotationB.v[2].xyz) + boundingOffsetB.z )
|
|
|
|
{ // |t dot s| > hA dot |s| + hB.z
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s = ( 1,0,0 ) x rotationB.v[0].xyz:
|
|
|
|
Float d = boundingOffsetA.y * absRotationB.v[0].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[0].y;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[2].x;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[1].x;
|
|
|
|
if( Abs(worldOffset.z*rotationB.v[0].y - worldOffset.y*rotationB.v[0].z) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 1,0,0 ) x rotationB.v[1].xyz:
|
|
|
|
d = boundingOffsetA.y * absRotationB.v[1].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[1].y;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[2].x;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[0].x;
|
|
|
|
if( Abs(worldOffset.z*rotationB.v[1].y - worldOffset.y*rotationB.v[1].z) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 1,0,0 ) x rotationB.v[2].xyz:
|
|
|
|
d = boundingOffsetA.y * absRotationB.v[2].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[2].y;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[1].x;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[0].x;
|
|
|
|
if( Abs(worldOffset.z*rotationB.v[2].y - worldOffset.y*rotationB.v[2].z) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 0,1,0 ) x rotationB.v[0].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[0].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[0].x;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[2].y;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[1].y;
|
|
|
|
if( Abs(worldOffset.x*rotationB.v[0].z - worldOffset.z*rotationB.v[0].x) > d ) return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
// s = ( 0,1,0 ) x rotationB.v[1].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[1].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[1].x;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[2].y;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[0].y;
|
|
|
|
if( Abs(worldOffset.x*rotationB.v[1].z - worldOffset.z*rotationB.v[1].x) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 0,1,0 ) x rotationB.v[2].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[2].z;
|
|
|
|
d += boundingOffsetA.z * absRotationB.v[2].x;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[1].y;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[0].y;
|
|
|
|
if( Abs(worldOffset.x*rotationB.v[2].z - worldOffset.z*rotationB.v[2].x) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 0,0,1 ) x rotationB.v[0].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[0].y;
|
|
|
|
d += boundingOffsetA.y * absRotationB.v[0].x;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[2].z;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[1].z;
|
|
|
|
if( Abs(worldOffset.y*rotationB.v[0].x - worldOffset.x*rotationB.v[0].y) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 0,0,1 ) x rotationB.v[1].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[1].y;
|
|
|
|
d += boundingOffsetA.y * absRotationB.v[1].x;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[2].z;
|
|
|
|
d += boundingOffsetB.z * absRotationB.v[0].z;
|
|
|
|
if( Abs(worldOffset.y*rotationB.v[1].x - worldOffset.x*rotationB.v[1].y) > d ) return false;
|
|
|
|
|
|
|
|
// s = ( 0,0,1 ) x rotationB.v[2].xyz:
|
|
|
|
d = boundingOffsetA.x * absRotationB.v[2].y;
|
|
|
|
d += boundingOffsetA.y * absRotationB.v[2].x;
|
|
|
|
d += boundingOffsetB.x * absRotationB.v[1].z;
|
|
|
|
d += boundingOffsetB.y * absRotationB.v[0].z;
|
|
|
|
if( Abs(worldOffset.y*rotationB.v[2].x - worldOffset.x*rotationB.v[2].y) > d ) return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-12-16 13:33:33 +01:00
|
|
|
|
|
|
|
bool SeperatingAxisTest_AxisAlignedVsTransformedBox( const Float3 &boundingOffsetA, const Float3 &boundingOffsetB, const Float4x4 &rotationB, const Float3 &worldOffset, Float3 &worldPointOfContact )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
|
|
* Uses the Seperating Axis Theorem
|
|
|
|
* if( |t dot s| > hA dot |s * RA| + hB dot |s * RB| ) then not intersecting
|
|
|
|
* |t dot s| > hA dot |s| + hB dot |s * RB| .. as RA = I
|
|
|
|
*
|
|
|
|
* t: objectB's offset from objectA [worldOffset]
|
|
|
|
* s: current comparison axis
|
|
|
|
* hA: boundingReach vector of objectA. Only absolute values is assumed. [boundingOffsetA]
|
|
|
|
* hB: boundingReach vector of objectB. Only absolute values is assumed. [boundingOffsetB]
|
|
|
|
* RA: rotation matrix of objectA. Is identity matrix here, thus omitted.
|
|
|
|
* RB: rotation matrix of objectB. Is transformed into objectA's view at this point. [rotationB]
|
|
|
|
*
|
|
|
|
* Note: s * RB = (RB^T * s)^T = (RB^-1 * s)^T .... vector == vector^T
|
|
|
|
*****************************************************************/
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
|
|
* Distance Alghorithm based on .. something Dan came up with
|
|
|
|
* pi = si * ( |t dot si| * (hA dot |si|) / (hA dot |si| + hB dot |si * RB|) )
|
|
|
|
* p = point of contact
|
|
|
|
* = ( p1 + p2 + ... + p13 + p14 ) / 5
|
|
|
|
*****************************************************************/
|
|
|
|
|
|
|
|
Float4 t = Float4( worldOffset, 0.0f ),
|
|
|
|
s = Float4::standard_unit_x,
|
|
|
|
hA = Float4( boundingOffsetA, 0.0f ),
|
|
|
|
hB = Float4( boundingOffsetB, 0.0f );
|
|
|
|
Float centerSeperation = Abs( t.Dot(s) ),
|
|
|
|
eA = hA.Dot( Abs(s) ),
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Float4 sumPoints = s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4::standard_unit_y;
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4::standard_unit_z;
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = rotationB.v[0];
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = rotationB.v[1];
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = rotationB.v[2];
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_x.Cross(rotationB.v[0].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_x.Cross(rotationB.v[1].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_x.Cross(rotationB.v[2].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_y.Cross(rotationB.v[0].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_y.Cross(rotationB.v[1].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_y.Cross(rotationB.v[2].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_z.Cross(rotationB.v[0].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_z.Cross(rotationB.v[1].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
s = Float4( Float3::standard_unit_z.Cross(rotationB.v[2].xyz), 0.0f );
|
|
|
|
centerSeperation = Abs( t.Dot(s) );
|
|
|
|
eA = hA.Dot( Abs(s) );
|
|
|
|
edgeSeperation = eA + hB.Dot( Abs(s * rotationB) );
|
|
|
|
if( centerSeperation > edgeSeperation )
|
|
|
|
{ // no intersection
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sumPoints += s.GetNormalized() * ( centerSeperation * eA / edgeSeperation );
|
|
|
|
|
|
|
|
worldPointOfContact = ((1.0f/5.0f) * sumPoints).xyz;
|
|
|
|
return true;
|
|
|
|
}
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// PUBLIC BODY //////////////////////////////////////////////////////
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
void Compare( Float &connectDistance, Float &connectOffsetSquared, const Ray &ray, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
Float3 dP = point.center - ray.origin;
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
connectDistance = dP.Dot( ray.direction );
|
|
|
|
connectDistance /= ray.direction.Dot( ray.direction );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
dP -= ( connectDistance * ray.direction );
|
2013-11-10 02:27:16 +01:00
|
|
|
connectOffsetSquared = dP.Dot( dP );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
void Compare( Float &connectDistanceA, Float &connectDistanceB, Float &connectOffsetSquared, const Ray &rayA, const Ray &rayB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float3 dP = rayB.origin - rayA.origin;
|
2013-11-10 02:27:16 +01:00
|
|
|
connectDistanceA = rayA.direction.Dot( dP );
|
|
|
|
connectDistanceA /= rayA.direction.Dot( rayA.direction );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
dP *= -1.0f;
|
2013-11-10 02:27:16 +01:00
|
|
|
connectDistanceB = rayB.direction.Dot( dP );
|
|
|
|
connectDistanceB /= rayB.direction.Dot( rayB.direction );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
dP = rayA.direction * connectDistanceA;
|
|
|
|
dP += rayA.origin;
|
|
|
|
dP -= rayB.direction * connectDistanceB;
|
|
|
|
dP -= rayB.origin;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
connectOffsetSquared = dP.Dot( dP );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
void Compare( Float &connectOffset, const Plane &plane, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, plane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Point &pointA, const Point &pointB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Fredrick Johansson
|
2013-11-10 02:27:16 +01:00
|
|
|
if (pointA.center.x != pointB.center.x) return false;
|
|
|
|
if (pointA.center.y != pointB.center.y) return false;
|
|
|
|
if (pointA.center.z != pointB.center.z) return false;
|
|
|
|
return true; // Passed all tests, is in same position
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Point &pointA, const Point &pointB, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Ray &ray, const Point &point, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffsetSquared;
|
2013-11-10 02:27:16 +01:00
|
|
|
Compare( connectDistance, connectOffsetSquared, ray, point );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Private::EqualsZero(connectOffsetSquared) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
connectOffsetSquared = 0.0f;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
connectDistance = 0.0f;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Ray &rayA, const Ray &rayB, Float &connectDistanceA, Float &connectDistanceB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffsetSquared;
|
2013-11-10 02:27:16 +01:00
|
|
|
Compare( connectDistanceA, connectDistanceB, connectOffsetSquared, rayA, rayB );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Private::EqualsZero(connectOffsetSquared) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
connectOffsetSquared = 0.0f;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
connectDistanceA = connectDistanceB = 0.0f;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Ray &ray, const Point &point, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Ray &rayA, const Ray &rayB, ::Oyster::Math::Float &connectDistanceA, ::Oyster::Math::Float &connectDistanceB, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 13:33:33 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Sphere &sphere, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
Float3 dP = point.center - sphere.center;
|
|
|
|
if( dP.Dot(dP) > (sphere.radius * sphere.radius) )
|
2013-11-06 22:52:00 +01:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Sphere &sphere, const Ray &ray, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{// by Dan Andersson
|
|
|
|
Float3 dP = sphere.center - ray.origin;
|
2013-11-10 02:27:16 +01:00
|
|
|
Float s = dP.Dot( ray.direction ),
|
|
|
|
dSquared = dP.Dot( dP ),
|
2013-11-06 22:52:00 +01:00
|
|
|
rSquared = sphere.radius * sphere.radius;
|
|
|
|
|
|
|
|
if( dSquared <= rSquared ) { connectDistance = 0.0f; return true; }
|
|
|
|
else if( s < 0.0f ) { connectDistance = 0.0f; return false; }
|
|
|
|
|
|
|
|
Float mSquared = dSquared - (s*s);
|
|
|
|
if( mSquared > rSquared ) { connectDistance = 0.0f; return false; }
|
|
|
|
|
|
|
|
Float q = ::std::sqrt( rSquared - mSquared );
|
|
|
|
if( dSquared > rSquared ) connectDistance = s - q;
|
|
|
|
else connectDistance = s + q;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Sphere &sphereA, const Sphere &sphereB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Fredrick Johansson
|
|
|
|
Float3 C = sphereA.center;
|
|
|
|
C -= sphereB.center;
|
|
|
|
Float r = (sphereA.radius + sphereB.radius);
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if (r*r >= C.Dot(C))
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
return true; // Intersect detected!
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Sphere &sphere, const Point &point, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Sphere &sphere, const Ray &ray, ::Oyster::Math::Float &connectDistance, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
bool Intersect( const Sphere &sphereA, const Sphere &sphereB, ::Oyster::Math::Float3& worldPointOfContact )
|
2013-12-16 09:38:04 +01:00
|
|
|
{
|
2013-12-16 10:28:49 +01:00
|
|
|
//Float3 C = sphereA.center;
|
|
|
|
//C -= sphereB.center;
|
|
|
|
//Float r = (sphereA.radius + sphereB.radius);
|
2013-12-16 09:38:04 +01:00
|
|
|
|
2013-12-16 10:28:49 +01:00
|
|
|
//if (r*r >= C.Dot(C))
|
|
|
|
//{
|
|
|
|
// Float distance;
|
|
|
|
|
|
|
|
// Intersect(sphereA, Ray(sphereB.center, C.Normalize()), distance);
|
|
|
|
|
|
|
|
// worldPointOfContact = sphereB.center+C.Normalize()*distance;
|
|
|
|
|
|
|
|
// return true; // Intersect detected!
|
|
|
|
//}
|
2013-12-16 09:38:04 +01:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Plane &plane, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffset;
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, plane, point.center );
|
|
|
|
return Private::EqualsZero(connectOffset);
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Plane &plane, const Ray &ray, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
Float c = plane.normal.Dot(ray.direction);
|
|
|
|
if( Private::EqualsZero(c) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // ray is parallell with the plane. (ray direction orthogonal with the planar normal)
|
|
|
|
connectDistance = 0.0f;
|
2013-11-10 02:27:16 +01:00
|
|
|
return Contains( plane, ray.origin );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
connectDistance = -plane.phasing;
|
2013-11-10 02:27:16 +01:00
|
|
|
connectDistance -= plane.normal.Dot( ray.origin );
|
2013-11-06 22:52:00 +01:00
|
|
|
connectDistance /= c;
|
|
|
|
|
|
|
|
if( connectDistance > 0.0f )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
connectDistance = 0.0f;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Plane &plane, const Sphere &sphere )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffset;
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, plane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
return (connectOffset <= sphere.radius);
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Plane &planeA, const Plane &planeB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
if( planeA.normal == planeB.normal ) // they are parallell
|
|
|
|
return (planeA.phasing == planeB.phasing);
|
|
|
|
else if( planeA.normal == -planeB.normal ) // they are still parallell
|
|
|
|
return (planeA.phasing == -planeB.phasing);
|
|
|
|
return true; // none parallell planes ALWAYS intersects somewhere
|
|
|
|
}
|
|
|
|
|
2013-12-16 09:38:04 +01:00
|
|
|
bool Intersect( const Plane &plane, const Point &point, const ::Oyster::Math::Float3& worldPointOfContact )
|
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Intersect( const Plane &plane, const Ray &ray, ::Oyster::Math::Float &connectDistance, const ::Oyster::Math::Float3& worldPointOfContact )
|
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Intersect( const Plane &plane, const Sphere &sphere, const ::Oyster::Math::Float3& worldPointOfContact )
|
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Intersect( const Plane &planeA, const Plane &planeB, const ::Oyster::Math::Float3& worldPointOfContact )
|
|
|
|
{
|
2013-12-16 10:31:26 +01:00
|
|
|
//! @todo TODO: implement Stub
|
2013-12-16 09:38:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
if( point.center.x < box.minVertex.x ) return false;
|
|
|
|
if( point.center.x > box.maxVertex.x ) return false;
|
|
|
|
if( point.center.y < box.minVertex.y ) return false;
|
|
|
|
if( point.center.y > box.maxVertex.y ) return false;
|
|
|
|
if( point.center.z < box.minVertex.z ) return false;
|
|
|
|
if( point.center.z > box.maxVertex.z ) return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Point &point, Float3 &worldPointOfContact )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
if( Intersect(box, point) )
|
|
|
|
{
|
|
|
|
worldPointOfContact = point.center;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Ray &ray, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float tMin = ::std::numeric_limits<Float>::max(),
|
|
|
|
tMax = -tMin; // initiating to extremevalues
|
|
|
|
|
|
|
|
Float3 boundingOffset = ((box.maxVertex - box.minVertex) * 0.5f),
|
|
|
|
dP = ((box.maxVertex + box.minVertex) * 0.5f) - ray.origin;
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_x, boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
|
|
|
if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_y, boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
|
|
|
if( Private::BoxVsRayPerSlabCheck( Float3::standard_unit_z, boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
if( tMin > 0.0f ) connectDistance = tMin;
|
|
|
|
else connectDistance = tMax;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Ray &ray, Float &connectDistance, Float3 &worldPointOfContact )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
if( Intersect(box, ray, connectDistance) )
|
|
|
|
{
|
|
|
|
worldPointOfContact = ray.origin + ray.direction * connectDistance;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Sphere &sphere )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-12-04 13:52:07 +01:00
|
|
|
Float4 e = Max( Float4(box.minVertex - sphere.center, 0.0f), Float4::null );
|
|
|
|
e += Max( Float4(sphere.center - box.maxVertex, 0.0f), Float4::null );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( e.Dot(e) > (sphere.radius * sphere.radius) ) return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Sphere &sphere, Float3 &worldPointOfContact )
|
|
|
|
{
|
|
|
|
//! @todo TODO: implement stub
|
|
|
|
return Intersect( box, sphere );
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Plane &plane )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float e, d;
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, plane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
if( d + e < 0.0f ) return false; // is above
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &box, const Plane &plane, Float3 &worldPointOfContact )
|
|
|
|
{
|
|
|
|
//! @todo TODO: implement stub
|
|
|
|
return Intersect( box, plane );
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
// bool Intersect( const BoxAxisAligned &box, const Triangle &triangle )
|
|
|
|
// { return false; /* TODO: */ }
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const BoxAxisAligned &boxA, const BoxAxisAligned &boxB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
if( boxA.maxVertex.x < boxB.minVertex.x ) return false;
|
|
|
|
if( boxA.minVertex.x > boxB.maxVertex.x ) return false;
|
|
|
|
if( boxA.maxVertex.y < boxB.minVertex.y ) return false;
|
|
|
|
if( boxA.minVertex.y > boxB.maxVertex.y ) return false;
|
|
|
|
if( boxA.maxVertex.z < boxB.minVertex.z ) return false;
|
|
|
|
if( boxA.minVertex.z > boxB.maxVertex.z ) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &box, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
Float3 dPos = point.center - box.center;
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
Float coordinate = dPos.Dot( box.xAxis );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( coordinate > box.boundingOffset.x ) return false;
|
|
|
|
if( coordinate < -box.boundingOffset.x ) return false;
|
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
coordinate = dPos.Dot( box.yAxis );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( coordinate > box.boundingOffset.y ) return false;
|
|
|
|
if( coordinate < -box.boundingOffset.y ) return false;
|
|
|
|
|
2013-11-20 16:58:56 +01:00
|
|
|
coordinate = dPos.Dot( box.zAxis );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( coordinate > box.boundingOffset.z ) return false;
|
|
|
|
if( coordinate < -box.boundingOffset.z ) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const Box &box, const Point &point, Float3 &worldPointOfContact )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
if( Intersect(box, point) )
|
|
|
|
{
|
|
|
|
worldPointOfContact = point.center;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &box, const Ray &ray, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float tMin = ::std::numeric_limits<Float>::max(),
|
|
|
|
tMax = -tMin; // initiating to extremevalues
|
|
|
|
|
|
|
|
Float3 dP = box.center - ray.origin;
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Private::BoxVsRayPerSlabCheck( box.xAxis, box.boundingOffset.x, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
|
|
|
if( Private::BoxVsRayPerSlabCheck( box.yAxis, box.boundingOffset.y, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
|
|
|
if( Private::BoxVsRayPerSlabCheck( box.zAxis, box.boundingOffset.z, dP, ray.direction, tMin, tMax ) ) { connectDistance = 0.0f; return false; }
|
2013-11-06 22:52:00 +01:00
|
|
|
|
|
|
|
if( tMin > 0.0f ) connectDistance = tMin;
|
|
|
|
else connectDistance = tMax;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const Box &box, const Ray &ray, Float &connectDistance, Float3 &worldPointOfContact )
|
|
|
|
{ // by Dan Andersson
|
|
|
|
if( Intersect(box, ray, connectDistance) )
|
|
|
|
{
|
|
|
|
worldPointOfContact = ray.origin + ray.direction * connectDistance;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &box, const Sphere &sphere )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-12-04 14:12:06 +01:00
|
|
|
// center: sphere's center in the box's view space
|
|
|
|
Float4 center = TransformVector( InverseRotationMatrix(box.rotation), Float4(sphere.center - box.center, 0.0f) );
|
2013-12-04 13:52:07 +01:00
|
|
|
|
2013-12-04 14:12:06 +01:00
|
|
|
Float4 e = Max( Float4(-box.boundingOffset, 0.0f) - center, Float4::null );
|
|
|
|
e += Max( center - Float4(box.boundingOffset, 0.0f), Float4::null );
|
2013-12-04 13:52:07 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( e.Dot(e) > (sphere.radius * sphere.radius) ) return false;
|
2013-11-06 22:52:00 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const Box &box, const Sphere &sphere, Float3 &worldPointOfContact )
|
|
|
|
{
|
|
|
|
//! @todo TODO: implement stub
|
|
|
|
return Intersect( box, sphere );
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &box, const Plane &plane )
|
2013-11-06 22:52:00 +01:00
|
|
|
{// by Dan Andersson
|
|
|
|
Float e, d;
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, plane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
if( d + e < 0.0f ) return false; // is above
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-16 10:31:26 +01:00
|
|
|
bool Intersect( const Box &box, const Plane &plane, Float3 &worldPointOfContact )
|
|
|
|
{
|
|
|
|
//! @todo TODO: implement stub
|
|
|
|
return Intersect( box, plane );
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &boxA, const BoxAxisAligned &boxB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
Float3 alignedOffsetBoundaries = (boxB.maxVertex - boxB.minVertex) * 0.5f,
|
|
|
|
offset = boxA.center - Average( boxB.minVertex, boxB.maxVertex );
|
|
|
|
return Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( alignedOffsetBoundaries, boxA.boundingOffset, boxA.rotation, offset );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Box &boxA, const Box &boxB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-20 16:58:56 +01:00
|
|
|
Float4x4 orientationA = OrientationMatrix(boxA.rotation, boxA.center),
|
|
|
|
orientationB = OrientationMatrix(boxB.rotation, boxB.center),
|
|
|
|
invOrientationA = InverseOrientationMatrix( orientationA );
|
|
|
|
|
|
|
|
orientationB = TransformMatrix( invOrientationA, orientationB );
|
|
|
|
|
|
|
|
return Private::SeperatingAxisTest_AxisAlignedVsTransformedBox( boxA.boundingOffset, boxB.boundingOffset, ExtractRotationMatrix(orientationB), orientationB.v[3].xyz );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffset;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.leftPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.rightPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.bottomPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.topPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.nearPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.farPlane, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < 0.0f ) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const Ray &ray, Float &connectDistance )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
bool intersected = false;
|
|
|
|
Float distance = 0.0f;
|
|
|
|
connectDistance = ::std::numeric_limits<Float>::max();
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.leftPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.rightPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.bottomPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.topPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.nearPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Intersect(frustrum.farPlane, ray, distance) )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
intersected = true;
|
2013-11-20 16:58:56 +01:00
|
|
|
connectDistance = Min( connectDistance, distance );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if( intersected ) return true;
|
|
|
|
|
|
|
|
connectDistance = 0.0f;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const Sphere &sphere )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float connectOffset;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.leftPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.rightPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.bottomPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.topPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.nearPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( connectOffset, frustrum.farPlane, sphere.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( connectOffset < -sphere.radius ) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const Plane &plane )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
2013-11-10 02:27:16 +01:00
|
|
|
return false; // TODO:
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
// bool Intersect( const Frustrum &frustrum, const Triangle &triangle, ? );
|
2013-11-06 22:52:00 +01:00
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const BoxAxisAligned &box )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float e, d;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.leftPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.rightPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.bottomPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.topPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.nearPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.farPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrum, const Box &box )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
Float e, d;
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.leftPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.rightPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.bottomPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.topPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.nearPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
Private::Compare( e, d, frustrum.farPlane, box );
|
2013-11-06 22:52:00 +01:00
|
|
|
if( d - e > 0.0f ) return false; // is beneath
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Intersect( const Frustrum &frustrumA, const Frustrum &frustrumB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
2013-11-10 02:27:16 +01:00
|
|
|
return false; // TODO:
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Contains( const Ray &container, const Ray &ray )
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
2013-11-10 02:27:16 +01:00
|
|
|
return false; /*TODO: */
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Contains( const Sphere &sphereA, const Sphere &sphereB )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Fredrick Johansson
|
|
|
|
// Check if SphereB is larger than sphereA
|
|
|
|
if (sphereA.radius < sphereB.radius)
|
|
|
|
{
|
|
|
|
return false; // Is impossible, yes
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calc distance from center to center
|
|
|
|
Float3 d = sphereB.center - sphereA.center;
|
|
|
|
Float deltaR = sphereA.radius - sphereB.radius;
|
|
|
|
|
|
|
|
// Check if contained
|
2013-11-10 02:27:16 +01:00
|
|
|
if (d.Dot(d) <= (deltaR*deltaR))
|
2013-11-06 22:52:00 +01:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not contained
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Contains( const Plane &container, const Point &point )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
return Private::Contains( container, point.center );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Contains( const Plane &container, const Ray &ray )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
2013-11-10 02:27:16 +01:00
|
|
|
if( Private::NotEqualsZero(container.normal.Dot(ray.direction)) ) return false;
|
|
|
|
return Contains( container, ray.origin );
|
2013-11-06 22:52:00 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 02:27:16 +01:00
|
|
|
bool Contains( const Plane &container, const Plane &plane )
|
2013-11-06 22:52:00 +01:00
|
|
|
{ // by Dan Andersson
|
|
|
|
if( container.phasing == plane.phasing )
|
|
|
|
return container.normal == plane.normal;
|
|
|
|
if( container.phasing == -plane.phasing )
|
|
|
|
return container.normal == -plane.normal;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} } }
|