DragonNest/Common/EternityEngineSrv/EtCollisionEntity.cpp

492 lines
11 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
#include "StdAfx.h"
#include "EtTestCollision.h"
#include "EtFindCollision.h"
#include "EtCollisionEntity.h"
CEtCollisionEntity::CEtCollisionEntity(void)
{
m_pvecOriginalPrimitive = NULL;
m_vScale = EtVector3( 1.0f, 1.0f, 1.0f );
m_nCollisionGroup = 0;
m_nTargetCollisionGroup = -1;
m_bDraw = false;
m_bEnableCollision = false;
SetCollisionGroup( COLLISION_GROUP_STATIC( 1 ) );
SetTargetCollisionGroup( 0 );
}
CEtCollisionEntity::~CEtCollisionEntity(void)
{
SAFE_DELETE_PVEC( m_vecPrimitive );
}
void CEtCollisionEntity::Initialize( std::vector< SCollisionPrimitive * > &vecPrimitive, std::vector< int > &vecPrimitiveBoneIndex )
{
int i;
SCollisionPrimitive *pBasePrimitive;
SAFE_DELETE_PVEC( m_vecPrimitive );
m_vecPrimitiveParentIndex.clear();
m_vecPrimitiveEnable.clear();
m_vecPrimitiveParentIndex.insert( m_vecPrimitiveParentIndex.end(), vecPrimitiveBoneIndex.begin(), vecPrimitiveBoneIndex.end() );
m_vecPrimitiveEnable.resize( vecPrimitive.size() );
m_pvecOriginalPrimitive = &vecPrimitive;
for( i = 0; i < ( int )m_pvecOriginalPrimitive->size(); i++ )
{
switch( ( *m_pvecOriginalPrimitive )[ i ]->Type )
{
case CT_SPHERE:
pBasePrimitive = new SCollisionSphere();
break;
case CT_BOX:
pBasePrimitive = new SCollisionBox();
break;
case CT_CAPSULE:
pBasePrimitive = new SCollisionCapsule();
break;
case CT_TRIANGLE_LIST:
pBasePrimitive = new SCollisionTriangleList();
break;
default:
pBasePrimitive = NULL;
continue;
}
m_vecPrimitive.push_back( pBasePrimitive );
m_vecPrimitiveEnable[ i ] = true;
}
m_bEnableCollision = true;
ShowCollisionPrimitive( true );
}
void CEtCollisionEntity::UpdateCollisionPrimitive( int nIndex, EtMatrix &WorldMat )
{
if( nIndex >= ( int )m_vecPrimitive.size() )
{
ASSERT( 0 && "Invalid Collision Primitive Index!!!" );
return;
}
if( !m_vecPrimitiveEnable[ nIndex ] )
{
return;
}
::UpdateCollisionPrimitive( *m_vecPrimitive[ nIndex ], *( *m_pvecOriginalPrimitive )[ nIndex ], WorldMat, m_vScale );
}
void CEtCollisionEntity::UpdateCollisionPrimitive( EtMatrix &WorldMat )
{
if( !m_pvecOriginalPrimitive )
{
ASSERT( 0 && "Not Found Original CollisionMesh!!!" );
return;
}
int i;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
UpdateCollisionPrimitive( i, WorldMat );
}
}
SCollisionPrimitive *CEtCollisionEntity::FindCollisionPrimitive( int nBoneIndex )
{
int i;
for( i = 0; i < ( int )m_vecPrimitiveParentIndex.size(); i++ )
{
if( m_vecPrimitiveParentIndex[ i ] == nBoneIndex )
{
return m_vecPrimitive[ i ];
}
}
return NULL;
}
void CEtCollisionEntity::DrawCollisionPrimitive()
{
}
bool CEtCollisionEntity::TestCollision( SCollisionPrimitive &Primitive )
{
int i;
SCollisionResponse Response;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
if( CEtCollisionFinder::GetInstance().FindCollision( *m_vecPrimitive[ i ], Primitive, Response, false ) )
{
return true;
}
}
return false;
}
bool CEtCollisionEntity::FindCollision( SCollisionPrimitive &TragetPrimitive, EtVector3 &vMove, SCollisionResponse &Response, bool bCalcContactTime )
{
int i;
Response.vMove = vMove;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
if( CEtCollisionFinder::GetInstance().FindCollision( *m_vecPrimitive[ i ], TragetPrimitive, Response, bCalcContactTime ) )
{
return true;
}
}
return false;
}
bool CEtCollisionEntity::FindCollision( std::vector< SCollisionPrimitive * > &vecTragetPrimitive, EtVector3 &vMove, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime )
{
int i, j;
SCollisionResponse Response;
bool bResult = false;
Response.vMove = vMove;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
for( j = 0; j < ( int )vecTragetPrimitive.size(); j++ )
{
if( CEtCollisionFinder::GetInstance().FindCollision( *m_vecPrimitive[ i ], *vecTragetPrimitive[ j ], Response, bCalcContactTime ) )
{
Response.pCollisionPrimitive = vecTragetPrimitive[ j ];
vecResponse.push_back( Response );
if( Response.vExtraNormal.x != FLT_MAX )
{
Response.vNormal = Response.vExtraNormal;
vecResponse.push_back( Response );
}
bResult = true;
}
}
}
return bResult;
}
bool CEtCollisionEntity::TestSegmentCollision( SSegment &Segment )
{
if( !IsEnableCollision() )
{
return false;
}
int i;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
switch( m_vecPrimitive[ i ]->Type )
{
case CT_BOX:
if( TestSegmentToBox( Segment, *( ( SCollisionBox * )m_vecPrimitive[ i ] ) ) )
{
return true;
}
break;
case CT_SPHERE:
if( TestSegmentToSphere( Segment, *( ( SCollisionSphere * )m_vecPrimitive[ i ] ) ) )
{
return true;
}
break;
case CT_CAPSULE:
if( TestSegmentToCapsule( Segment, *( ( SCollisionCapsule * )m_vecPrimitive[ i ] ) ) )
{
return true;
}
break;
}
}
return false;
}
bool CEtCollisionEntity::FindSegmentCollision( SSegment &Segment, SCollisionResponse &Response, DNVector(SCollisionResponse) *pvResponse )
{
if( !IsEnableCollision() )
{
return false;
}
int i;
bool bResult;
float fContactTime;
bResult = false;
Response.fContactTime = FLT_MAX;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;;
}
switch( m_vecPrimitive[ i ]->Type )
{
case CT_BOX:
if( FindSegmentToBox( Segment, *( ( SCollisionBox * )m_vecPrimitive[ i ] ), fContactTime ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fContactTime;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fContactTime < Response.fContactTime )
{
Response.fContactTime = fContactTime;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
case CT_SPHERE:
if( FindSegmentToSphere( Segment, *( ( SCollisionSphere * )m_vecPrimitive[ i ] ), fContactTime ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fContactTime;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fContactTime < Response.fContactTime )
{
Response.fContactTime = fContactTime;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
case CT_CAPSULE:
if( FindSegmentToCapsule( Segment, *( ( SCollisionCapsule * )m_vecPrimitive[ i ] ), fContactTime ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fContactTime;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fContactTime < Response.fContactTime )
{
Response.fContactTime = fContactTime;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
}
}
return bResult;
}
bool CEtCollisionEntity::FindCapsuleCollision( SCollisionCapsule &Capsule, SCollisionResponse &Response, DNVector(SCollisionResponse) *pvResponse )
{
if( !IsEnableCollision() )
{
return false;
}
int i;
float fParam1, fParam2;
bool bResult;
bResult = false;
Response.fContactTime = FLT_MAX;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
switch( m_vecPrimitive[ i ]->Type )
{
case CT_BOX:
float fBoxParam0, fBoxParam1, fBoxParam2;
if( TestBoxToCapsule( *( ( SCollisionBox * )m_vecPrimitive[ i ] ), Capsule, fParam1, fBoxParam0, fBoxParam1, fBoxParam2 ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fParam1;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fParam1 < Response.fContactTime )
{
Response.fContactTime = fParam1;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
case CT_SPHERE:
if( TestSphereToCapsule( *( ( SCollisionSphere * )m_vecPrimitive[ i ] ), Capsule, fParam1 ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fParam1;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fParam1 < Response.fContactTime )
{
Response.fContactTime = fParam1;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
case CT_CAPSULE:
if( TestCapsuleToCapsule( Capsule, *( ( SCollisionCapsule * )m_vecPrimitive[ i ] ), fParam1, fParam2 ) )
{
if( pvResponse )
{
SCollisionResponse sResponse;
sResponse.fContactTime = fParam1;
sResponse.pCollisionPrimitive = m_vecPrimitive[i];
pvResponse->push_back( sResponse );
}
if( fParam1 < Response.fContactTime )
{
Response.fContactTime = fParam1;
Response.pCollisionPrimitive = m_vecPrimitive[ i ];
}
bResult = true;
}
break;
}
}
return bResult;
}
bool CEtCollisionEntity::FindCollisionPrimitiveCenterInRange( EtVector3 vPosition, float fMinRangeRadius, float fRangeRadius )
{
if( !IsEnableCollision() )
{
return false;
}
float fMinRadiusSQ = fMinRangeRadius * fMinRangeRadius;
float fRadiusSQ = fRangeRadius * fRangeRadius;
for( int i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( !m_vecPrimitiveEnable[ i ] )
{
continue;
}
// <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ԵǾ<D4B5><C7BE>ִ<EFBFBD> <20>ֵ<EFBFBD><D6B5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ƴ<EFBFBD><C6B3>´<EFBFBD>.
EtVector3 vCenter( 0.0f, 0.0f, 0.0f );
switch( m_vecPrimitive[ i ]->Type )
{
case CT_BOX:
{
SCollisionBox* pCollisionBox = static_cast<SCollisionBox*>(m_vecPrimitive[ i ]);
vCenter = pCollisionBox->vCenter;
}
break;
case CT_SPHERE:
{
SCollisionSphere* pCollisionSphere = static_cast<SCollisionSphere*>( m_vecPrimitive[ i ] );
vCenter = pCollisionSphere->vCenter;
}
break;
case CT_CAPSULE:
{
SCollisionCapsule* pCollisionCapsule = static_cast<SCollisionCapsule*>( m_vecPrimitive[ i ] );
SAABox AABB;
pCollisionCapsule->GetBoundingBox( AABB );
vCenter = AABB.GetCenter();
}
break;
}
float fDistanceSQ = EtVec3LengthSq( &EtVector3(vCenter - vPosition) );
if( fDistanceSQ >= fMinRadiusSQ && fDistanceSQ <= fRadiusSQ )
return true;
}
return false;
}
int CEtCollisionEntity::GetParentBoneIndex( SCollisionPrimitive *pPrimitive )
{
int i;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( m_vecPrimitive[ i ] == pPrimitive )
{
return m_vecPrimitiveParentIndex[ i ];
}
}
return -1;
}
void CEtCollisionEntity::EnableCollision( SCollisionPrimitive *pPrimitive, bool bEnable )
{
int i;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( m_vecPrimitive[ i ] == pPrimitive )
{
m_vecPrimitiveEnable[ i ] = bEnable;
}
}
}
bool CEtCollisionEntity::IsEnableCollision( SCollisionPrimitive *pPrimitive )
{
int i;
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
{
if( m_vecPrimitive[ i ] == pPrimitive )
{
return m_vecPrimitiveEnable[ i ] ? true : false;
}
}
return false;
}