2024-12-21 10:04:04 +08:00
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
|
#include "EtCollisionMng.h"
|
|
|
|
|
|
#include "EtFindCollision.h"
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined( USE_BOOST_MEMPOOL )
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
CEtCollisionMng::CEtCollisionMng(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CEtCollisionMng::~CEtCollisionMng(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CEtCollisionMng::Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_CollisionKdTree.Clear();
|
|
|
|
|
|
SAFE_DELETE_AVEC( m_vecAllocPrimitive );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CEtCollisionMng::AddCollisionMeshToKdTree( SCollisionPrimitive &Primitive, EtMatrix &WorldMat, const EtVector3 &vScale )
|
|
|
|
|
|
{
|
|
|
|
|
|
if( m_CollisionKdTree.IsBuild() )
|
|
|
|
|
|
{
|
|
|
|
|
|
m_CollisionKdTree.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SKdTreeCollisionPrimitive KdTreePrimitive;
|
|
|
|
|
|
float fScale = max( max( vScale.x, vScale.y ), vScale.z );
|
|
|
|
|
|
|
|
|
|
|
|
switch( Primitive.Type )
|
|
|
|
|
|
{
|
|
|
|
|
|
case CT_TRIANGLE_LIST:
|
|
|
|
|
|
{
|
|
|
|
|
|
SCollisionTriangleList *pCollisionTriangle;
|
|
|
|
|
|
SCollisionTriangle *pTriangle;
|
|
|
|
|
|
int i, nTriangleCount;
|
|
|
|
|
|
|
|
|
|
|
|
pCollisionTriangle = ( SCollisionTriangleList * )&Primitive;
|
|
|
|
|
|
nTriangleCount = ( int )pCollisionTriangle->vecTriangle.size();
|
|
|
|
|
|
pTriangle = new SCollisionTriangle[ nTriangleCount ];
|
|
|
|
|
|
m_vecAllocPrimitive.push_back( pTriangle );
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < nTriangleCount; i++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
EtVector3 vPoint[ 3 ];
|
|
|
|
|
|
|
|
|
|
|
|
KdTreePrimitive.pPrimitive = pTriangle + i;
|
|
|
|
|
|
vPoint[ 0 ] = pCollisionTriangle->vecTriangle[ i ].vOrigin;
|
|
|
|
|
|
vPoint[ 1 ] = pCollisionTriangle->vecTriangle[ i ].vOrigin + pCollisionTriangle->vecTriangle[ i ].vEdge1;
|
|
|
|
|
|
vPoint[ 2 ] = pCollisionTriangle->vecTriangle[ i ].vOrigin + pCollisionTriangle->vecTriangle[ i ].vEdge2;
|
|
|
|
|
|
EtVec3TransformCoordArray( vPoint, sizeof( EtVector3 ), vPoint, sizeof( EtVector3 ), &WorldMat, 3 );
|
|
|
|
|
|
pTriangle[ i ].vOrigin = vPoint[ 0 ];
|
|
|
|
|
|
pTriangle[ i ].vEdge1 = vPoint[ 1 ] - vPoint[ 0 ];
|
|
|
|
|
|
pTriangle[ i ].vEdge2 = vPoint[ 2 ] - vPoint[ 0 ];
|
|
|
|
|
|
|
|
|
|
|
|
m_CollisionKdTree.AddPrimitive( KdTreePrimitive );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CT_BOX:
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
SCollisionBox *pBox, *pOriginalBox;
|
|
|
|
|
|
|
|
|
|
|
|
pOriginalBox = ( SCollisionBox * )&Primitive;
|
|
|
|
|
|
pBox = new SCollisionBox();
|
|
|
|
|
|
KdTreePrimitive.pPrimitive = pBox;
|
|
|
|
|
|
m_vecAllocPrimitive.push_back( pBox );
|
|
|
|
|
|
|
|
|
|
|
|
EtVec3TransformCoord( &pBox->vCenter, &pOriginalBox->vCenter, &WorldMat );
|
|
|
|
|
|
|
|
|
|
|
|
EtMatrix WorldNormalMat = WorldMat;
|
|
|
|
|
|
EtVector3 vLength;
|
|
|
|
|
|
vLength.x = EtVec3Length((EtVector3*)&WorldNormalMat._11);
|
|
|
|
|
|
vLength.y = EtVec3Length((EtVector3*)&WorldNormalMat._21);
|
|
|
|
|
|
vLength.z = EtVec3Length((EtVector3*)&WorldNormalMat._31);
|
|
|
|
|
|
|
|
|
|
|
|
*(EtVector3*)(&WorldNormalMat._11) /= vLength.x;
|
|
|
|
|
|
*(EtVector3*)(&WorldNormalMat._21) /= vLength.y;
|
|
|
|
|
|
*(EtVector3*)(&WorldNormalMat._31) /= vLength.z;
|
|
|
|
|
|
|
|
|
|
|
|
// Non-Uniform Scale Matrix <20><> <20><>ǥ<EFBFBD>踦 <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>ڿ<EFBFBD> Normalize<7A><65> <20><><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ϹǷ<CFB9>, <20≯<EFBFBD> Orthogonal Matrix <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < 3; i++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
EtVec3TransformNormal( pBox->vAxis + i, pOriginalBox->vAxis + i, &WorldNormalMat );
|
|
|
|
|
|
pBox->fExtent[ i ] = pOriginalBox->fExtent[ i ] * ((FLOAT*)&vLength.x)[ i ];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*EtMatrix MatIdent;
|
|
|
|
|
|
EtMatrixIdentity(&MatIdent);
|
|
|
|
|
|
*(EtVector3*)&MatIdent._11 = pBox->vAxis[0];
|
|
|
|
|
|
*(EtVector3*)&MatIdent._21 = pBox->vAxis[1];
|
|
|
|
|
|
*(EtVector3*)&MatIdent._31 = pBox->vAxis[2];
|
|
|
|
|
|
float fDet = fabsf(EtMatrixDeterminant(&MatIdent) - 1.0f);
|
|
|
|
|
|
ASSERT( fDet < 0.0001f );*/
|
|
|
|
|
|
|
|
|
|
|
|
m_CollisionKdTree.AddPrimitive( KdTreePrimitive );
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CT_SPHERE:
|
|
|
|
|
|
SCollisionSphere *pSphere, *pOriginalSphere;
|
|
|
|
|
|
|
|
|
|
|
|
pOriginalSphere = ( SCollisionSphere * )&Primitive;
|
|
|
|
|
|
pSphere = new SCollisionSphere();
|
|
|
|
|
|
KdTreePrimitive.pPrimitive = pSphere;
|
|
|
|
|
|
m_vecAllocPrimitive.push_back( pSphere );
|
|
|
|
|
|
|
|
|
|
|
|
EtVec3TransformCoord( &pSphere->vCenter, &pOriginalSphere->vCenter, &WorldMat );
|
|
|
|
|
|
pSphere->fRadius = pOriginalSphere->fRadius * fScale;
|
|
|
|
|
|
|
|
|
|
|
|
m_CollisionKdTree.AddPrimitive( KdTreePrimitive );
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CT_CAPSULE:
|
|
|
|
|
|
SCollisionCapsule *pCapsule, *pOriginalCapsule;
|
|
|
|
|
|
|
|
|
|
|
|
pOriginalCapsule = ( SCollisionCapsule * )&Primitive;
|
|
|
|
|
|
pCapsule = new SCollisionCapsule();
|
|
|
|
|
|
KdTreePrimitive.pPrimitive = pCapsule;
|
|
|
|
|
|
m_vecAllocPrimitive.push_back( pCapsule );
|
|
|
|
|
|
|
|
|
|
|
|
EtVec3TransformCoord( &pCapsule->Segment.vOrigin, &pOriginalCapsule->Segment.vOrigin, &WorldMat );
|
|
|
|
|
|
EtVector3 vOriginFar = pOriginalCapsule->Segment.vOrigin + pOriginalCapsule->Segment.vDirection;
|
|
|
|
|
|
EtVec3TransformCoord( &vOriginFar, &vOriginFar, &WorldMat );
|
|
|
|
|
|
pCapsule->Segment.vDirection = vOriginFar - pCapsule->Segment.vOrigin;
|
|
|
|
|
|
|
|
|
|
|
|
pCapsule->fRadius = pOriginalCapsule->fRadius * fScale;
|
|
|
|
|
|
if( fScale != 1.0f )
|
|
|
|
|
|
{
|
|
|
|
|
|
pCapsule->Segment.vOrigin = pCapsule->Segment.vOrigin - ( fScale - 1.0f ) * 0.5f * pCapsule->Segment.vDirection;
|
|
|
|
|
|
pCapsule->Segment.vDirection += pCapsule->Segment.vDirection * ( fScale - 1.0f ) * 0.5f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_CollisionKdTree.AddPrimitive( KdTreePrimitive );
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CEtCollisionMng::BuildCollisionTree()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_CollisionKdTree.BuildTree();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CEtCollisionMng::FindCollision( std::vector< SCollisionPrimitive * > &vecPrimitive, SAABox &BoundingBox, EtVector3 &vMove, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime)
|
|
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
bool bCollision;
|
|
|
|
|
|
static std::vector< SKdTreeCollisionPrimitive * > vecResult;
|
|
|
|
|
|
SCollisionResponse Response;
|
|
|
|
|
|
|
|
|
|
|
|
bCollision = false;
|
|
|
|
|
|
vecResult.clear();
|
|
|
|
|
|
m_CollisionKdTree.Pick( BoundingBox, vecResult );
|
|
|
|
|
|
if( !vecResult.empty() )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::vector< SKdTreeCollisionPrimitive * >::iterator it;
|
|
|
|
|
|
Response.vMove = vMove;
|
|
|
|
|
|
for( i = 0; i < ( int )vecPrimitive.size(); i++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
for( it = vecResult.begin() ; it != vecResult.end(); it++ )
|
|
|
|
|
|
{
|
|
|
|
|
|
Response.vExtraNormal.x = FLT_MAX;
|
|
|
|
|
|
if( CEtCollisionFinder::GetInstance().FindCollision( *vecPrimitive[ i ], *( ( *it )->pPrimitive), Response, bCalcContactTime ) )
|
|
|
|
|
|
{
|
|
|
|
|
|
Response.pCollisionPrimitive = ( *it )->pPrimitive;
|
|
|
|
|
|
vecResponse.push_back( Response );
|
|
|
|
|
|
if( Response.vExtraNormal.x != FLT_MAX )
|
|
|
|
|
|
{
|
|
|
|
|
|
Response.vNormal = Response.vExtraNormal;
|
|
|
|
|
|
vecResponse.push_back( Response );
|
|
|
|
|
|
}
|
|
|
|
|
|
bCollision = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return bCollision;
|
|
|
|
|
|
}
|