DragonNest/Common/EternityEngine/EtCollisionMng.cpp

187 lines
5.9 KiB
C++
Raw Permalink Normal View History

#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;
}