| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 | //-----------------------------------------------------------------------------// 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/mMatrix.h"#include "math/mSphere.h"const Box3F Box3F::Invalid( F32_MAX, F32_MAX, F32_MAX, -F32_MAX, -F32_MAX, -F32_MAX );const Box3F Box3F::Max( -F32_MAX, -F32_MAX, -F32_MAX, F32_MAX, F32_MAX, F32_MAX );const Box3F Box3F::Zero( 0, 0, 0, 0, 0, 0 );//-----------------------------------------------------------------------------bool Box3F::isOverlapped( const SphereF& sphere ) const{   // Algorithm: Real-Time Rendering, Ed. 1, p323, 10.10.1 Sphere/Box Intersection   F32 d = 0;   for( U32 i = 0; i < 3; ++ i )      if( sphere.center[ i ] < minExtents[ i ] )         d = d + mSquared( sphere.center[ i ] - minExtents[ i ] );      else if( sphere.center[ i ] > maxExtents[ i ] )         d = d + mSquared( sphere.center[ i ] - maxExtents[ i ] );   return !( d > mSquared( sphere.radius ) );}//-----------------------------------------------------------------------------bool Box3F::collideLine(const Point3F& start, const Point3F& end, F32* t, Point3F* n) const{   // Collide against bounding box. Need at least this for the editor.   F32 st,et;   F32 fst = 0;   F32 fet = 1;   const F32* bmin = &minExtents.x;   const F32* bmax = &maxExtents.x;   const F32* si   = &start.x;   const F32* ei   = &end.x;   static const Point3F na[3] = { Point3F(1.0f, 0.0f, 0.0f), Point3F(0.0f, 1.0f, 0.0f), Point3F(0.0f, 0.0f, 1.0f) };   Point3F finalNormal(0.0f, 0.0f, 0.0f);   for (S32 i = 0; i < 3; i++) {	  bool	n_neg = false;      if (si[i] < ei[i]) {         if (si[i] > bmax[i] || ei[i] < bmin[i])            return false;         F32 di = ei[i] - si[i];         st = (si[i] < bmin[i]) ? (bmin[i] - si[i]) / di : 0.0f;         et = (ei[i] > bmax[i]) ? (bmax[i] - si[i]) / di : 1.0f;		 n_neg = true;      }      else {         if (ei[i] > bmax[i] || si[i] < bmin[i])            return false;         F32 di = ei[i] - si[i];         st = (si[i] > bmax[i]) ? (bmax[i] - si[i]) / di : 0.0f;         et = (ei[i] < bmin[i]) ? (bmin[i] - si[i]) / di : 1.0f;      }      if (st > fst) {         fst = st;		 finalNormal = na[i];		 if ( n_neg )			finalNormal.neg();      }      if (et < fet)         fet = et;      if (fet < fst)         return false;   }   *t = fst;   *n = finalNormal;   return true;}//-----------------------------------------------------------------------------bool Box3F::collideLine(const Point3F& start, const Point3F& end) const{   F32 t;   Point3F normal;   return collideLine(start, end, &t, &normal);}//-----------------------------------------------------------------------------bool Box3F::collideOrientedBox(const Point3F & bRadii, const MatrixF & toA) const{   Point3F p;   toA.getColumn(3,&p);   Point3F aCenter = minExtents + maxExtents;   aCenter *= 0.5f;   p -= aCenter; // this essentially puts origin of toA target space on the center of the current box   Point3F aRadii = maxExtents - minExtents;   aRadii *= 0.5f;	F32 absXX,absXY,absXZ;	F32 absYX,absYY,absYZ;	F32 absZX,absZY,absZZ;   const F32 * f = toA;   absXX = mFabs(f[0]);   absYX = mFabs(f[1]);   absZX = mFabs(f[2]);	if (aRadii.x + bRadii.x * absXX + bRadii.y * absYX + bRadii.z * absZX - mFabs(p.x)<0.0f)		return false;   absXY = mFabs(f[4]);   absYY = mFabs(f[5]);   absZY = mFabs(f[6]);	if (aRadii.y + bRadii.x * absXY +	bRadii.y * absYY +	bRadii.z * absZY - mFabs(p.y)<0.0f)		return false;	   absXZ = mFabs(f[8]);   absYZ = mFabs(f[9]);   absZZ = mFabs(f[10]);	if (aRadii.z + bRadii.x * absXZ + bRadii.y * absYZ +	bRadii.z * absZZ - mFabs(p.z)<0.0f)		return false;	if (aRadii.x*absXX + aRadii.y*absXY + aRadii.z*absXZ + bRadii.x - mFabs(p.x*f[0] + p.y*f[4] + p.z*f[8])<0.0f)		return false;	if (aRadii.x*absYX + aRadii.y*absYY + aRadii.z*absYZ + bRadii.y - mFabs(p.x*f[1] + p.y*f[5] + p.z*f[9])<0.0f)		return false;				if (aRadii.x*absZX + aRadii.y*absZY + aRadii.z*absZZ + bRadii.z - mFabs(p.x*f[2] + p.y*f[6] + p.z*f[10])<0.0f)		return false;				if (mFabs(p.z*f[4] - p.y*f[8]) >				aRadii.y * absXZ + aRadii.z * absXY +				bRadii.y * absZX + bRadii.z * absYX)		return false;		if (mFabs(p.z*f[5] - p.y*f[9]) >				aRadii.y * absYZ + aRadii.z * absYY +				bRadii.x * absZX + bRadii.z * absXX)		return false;		if (mFabs(p.z*f[6] - p.y*f[10]) >				aRadii.y * absZZ + aRadii.z * absZY +				bRadii.x * absYX + bRadii.y * absXX)		return false;		if (mFabs(p.x*f[8] - p.z*f[0]) >				aRadii.x * absXZ + aRadii.z * absXX +				bRadii.y * absZY + bRadii.z * absYY)		return false;		if (mFabs(p.x*f[9] - p.z*f[1]) >				aRadii.x * absYZ + aRadii.z * absYX +				bRadii.x * absZY + bRadii.z * absXY)		return false;		if (mFabs(p.x*f[10] - p.z*f[2]) >				aRadii.x * absZZ + aRadii.z * absZX +				bRadii.x * absYY + bRadii.y * absXY)		return false;		if (mFabs(p.y*f[0] - p.x*f[4]) >				aRadii.x * absXY + aRadii.y * absXX +				bRadii.y * absZZ + bRadii.z * absYZ)		return false;		if (mFabs(p.y*f[1] - p.x*f[5]) >				aRadii.x * absYY + aRadii.y * absYX +				bRadii.x * absZZ + bRadii.z * absXZ)		return false;		if (mFabs(p.y*f[2] - p.x*f[6]) >				aRadii.x * absZY + aRadii.y * absZX +				bRadii.x * absYZ + bRadii.y * absXZ)		return false;		return true;}//-----------------------------------------------------------------------------Box3F Box3F::aroundPoints( const Point3F* points, U32 numPoints ){   AssertFatal( points != NULL, "Box3F::aroundPoints - Receive a NULL pointer" );   AssertFatal( numPoints >= 1, "Box3F::aroundPoints - Must have at least one point" );   Box3F box;      Point3F minPoint = points[ 0 ];   Point3F maxPoint = points[ 0 ];   for( U32 i = 1; i < numPoints; ++ i )      for( U32 n = 0; n < 3; ++ n )      {         minPoint[ n ] = getMin( minPoint[ n ], points[ i ][ n ] );         maxPoint[ n ] = getMax( maxPoint[ n ], points[ i ][ n ] );      }   return Box3F( minPoint, maxPoint );}//-----------------------------------------------------------------------------Point3F Box3F::computeVertex( U32 corner ) const{   AssertFatal( corner < NUM_POINTS, "Box3F::computeVertex - Index out of range" );      switch( corner )   {      case NearBottomLeft:    return Point3F( minExtents.x, minExtents.y, minExtents.z );      case NearTopLeft:       return Point3F( minExtents.x, minExtents.y, maxExtents.z );      case NearTopRight:      return Point3F( maxExtents.x, minExtents.y, maxExtents.z );      case NearBottomRight:   return Point3F( maxExtents.x, minExtents.y, minExtents.z );      case FarBottomLeft:     return Point3F( minExtents.x, maxExtents.y, minExtents.z );      case FarTopLeft:        return Point3F( minExtents.x, maxExtents.y, maxExtents.z );      case FarTopRight:       return Point3F( maxExtents.x, maxExtents.y, maxExtents.z );      case FarBottomRight:    return Point3F( maxExtents.x, maxExtents.y, minExtents.z );   }   // Not reached.   return Point3F( 0.f, 0.f, 0.f );}//-----------------------------------------------------------------------------F32 Box3F::getGreatestDiagonalLength() const{   F32 maxDiagonalsLen = ( computeVertex( FarTopRight ) - computeVertex( NearBottomLeft ) ).len();   maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarTopLeft ) - computeVertex( NearBottomRight ) ).len() );   maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarBottomLeft ) - computeVertex( NearTopRight ) ).len() );   maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarBottomRight ) - computeVertex( NearTopLeft ) ).len() );   return maxDiagonalsLen;}//-----------------------------------------------------------------------------SphereF Box3F::getBoundingSphere() const{   return SphereF( getCenter(), getGreatestDiagonalLength() / 2.f );}
 |