336 lines
7.9 KiB
C++
336 lines
7.9 KiB
C++
|
|
#include "StdAfx.h"
|
|||
|
|
#include "EtObject.h"
|
|||
|
|
#include "EtFindCollision.h"
|
|||
|
|
#include "EtLoader.h"
|
|||
|
|
#include "PerfCheck.h"
|
|||
|
|
#include "EtCollisionMng.h"
|
|||
|
|
|
|||
|
|
using namespace EternityEngine;
|
|||
|
|
|
|||
|
|
DECL_MULTISMART_PTR_STATIC( CEtObject, MAX_SESSION_COUNT, 1000 )
|
|||
|
|
|
|||
|
|
STATIC_DECL_INIT( CEtObject, CEtOctree< CEtObject * >, s_DynamicOctree );
|
|||
|
|
|
|||
|
|
float CEtOctreeNode< CEtObject * >::s_fMinRadius = 1000.0f;
|
|||
|
|
|
|||
|
|
CEtObject::CEtObject( CMultiRoom *pRoom )
|
|||
|
|
: CMultiSmartPtrBase< CEtObject, MAX_SESSION_COUNT >(pRoom)
|
|||
|
|
{
|
|||
|
|
EtMatrixIdentity( &m_WorldMat );
|
|||
|
|
m_pCurOctreeNode = NULL;
|
|||
|
|
m_BoundingBox.Reset();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CEtObject::~CEtObject(void)
|
|||
|
|
{
|
|||
|
|
if( m_pCurOctreeNode )
|
|||
|
|
{
|
|||
|
|
STATIC_INSTANCE(s_DynamicOctree).Remove( this, m_pCurOctreeNode );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::Clear()
|
|||
|
|
{
|
|||
|
|
SAFE_RELEASE_SPTR( m_hSkin );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int CEtObject::Initialize( EtSkinHandle hSkin )
|
|||
|
|
{
|
|||
|
|
Clear();
|
|||
|
|
m_hSkin = hSkin;
|
|||
|
|
CommonInitialize();
|
|||
|
|
|
|||
|
|
return ET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::CommonInitialize()
|
|||
|
|
{
|
|||
|
|
if( !m_hSkin || !m_hSkin->GetMeshHandle() )
|
|||
|
|
{
|
|||
|
|
_ASSERT(0);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
CEtCollisionEntity::Initialize( *m_hSkin->GetMeshHandle()->GetCollisionPrimitive(), *m_hSkin->GetMeshHandle()->GetCollisionPrimitiveParentIndex() );
|
|||
|
|
UpdateCollisionPrimitive( m_WorldMat );
|
|||
|
|
GetMeshBoundingBox( m_OriginalBoundingBox );
|
|||
|
|
GetMeshBoundingSphere( m_OriginalBoundingSphere );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::Update( EtMatrix *pWorldMat )
|
|||
|
|
{
|
|||
|
|
SSphere Sphere;
|
|||
|
|
|
|||
|
|
m_WorldMat = *pWorldMat;
|
|||
|
|
UpdateBoundingPrimitive();
|
|||
|
|
if( m_hSkin )
|
|||
|
|
{
|
|||
|
|
UpdateCollisionPrimitive( m_WorldMat );
|
|||
|
|
GetBoundingSphere( Sphere );
|
|||
|
|
if( GetCollisionGroup() >= COLLISION_GROUP_DYNAMIC( 2 ) ) // <20><><EFBFBD>̳<EFBFBD><CCB3><EFBFBD> <20>ø<EFBFBD><C3B8><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> <20>ֵ鸸 <20><>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20>־ üũ <20><><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD> KdTree<65><65> <20><><EFBFBD><EFBFBD>.
|
|||
|
|
{
|
|||
|
|
if( m_pCurOctreeNode )
|
|||
|
|
{
|
|||
|
|
m_pCurOctreeNode = STATIC_INSTANCE(s_DynamicOctree).Update( this, Sphere, m_pCurOctreeNode );
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
m_pCurOctreeNode = STATIC_INSTANCE(s_DynamicOctree).Insert( this, Sphere );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::GetMeshBoundingBox( SAABox &AABox )
|
|||
|
|
{
|
|||
|
|
EtMeshHandle hMesh;
|
|||
|
|
|
|||
|
|
hMesh = m_hSkin->GetMeshHandle();
|
|||
|
|
if( hMesh )
|
|||
|
|
{
|
|||
|
|
hMesh->GetBoundingBox( AABox );
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AABox.Min = EtVector3( -1.0f, -1.0f, -1.0f );
|
|||
|
|
AABox.Max = EtVector3( 1.0f, 1.0f, 1.0f );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::GetMeshBoundingSphere( SSphere &Sphere )
|
|||
|
|
{
|
|||
|
|
EtMeshHandle hMesh;
|
|||
|
|
|
|||
|
|
hMesh = m_hSkin->GetMeshHandle();
|
|||
|
|
if( hMesh )
|
|||
|
|
{
|
|||
|
|
hMesh->GetBoundingSphere( Sphere );
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Sphere.Center = EtVector3( 0.0f, 0.0f, 0.0f );
|
|||
|
|
Sphere.fRadius = 1.0f;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::RecalcBoundingBox()
|
|||
|
|
{
|
|||
|
|
GetMeshBoundingBox( m_OriginalBoundingBox );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::RecalcBoundingSphere()
|
|||
|
|
{
|
|||
|
|
EtVector3 vDirection, vOriginalEnd, vChildEnd;
|
|||
|
|
SSphere BoundingSphere;
|
|||
|
|
|
|||
|
|
GetMeshBoundingSphere( m_OriginalBoundingSphere );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::UpdateBoundingPrimitive()
|
|||
|
|
{
|
|||
|
|
if( !m_hSkin )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int i;
|
|||
|
|
EtMatrix OutputMat;
|
|||
|
|
|
|||
|
|
EtMatrixScaling( &OutputMat, m_vScale.x, m_vScale.y, m_vScale.z );
|
|||
|
|
EtMatrixMultiply( &OutputMat, &OutputMat, &m_WorldMat );
|
|||
|
|
m_BoundingBox.Reset();
|
|||
|
|
for( i = 0; i < 8; i ++ )
|
|||
|
|
{
|
|||
|
|
EtVector3 vPoint;
|
|||
|
|
|
|||
|
|
m_OriginalBoundingBox.GetVertex( i, vPoint );
|
|||
|
|
EtVec3TransformCoord( &vPoint, &vPoint, &OutputMat );
|
|||
|
|
m_BoundingBox.AddPoint( vPoint );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_BoundingSphere = m_OriginalBoundingSphere;
|
|||
|
|
EtVec3TransformCoord( &m_BoundingSphere.Center, &m_OriginalBoundingSphere.Center, &m_WorldMat );
|
|||
|
|
m_BoundingSphere.fRadius *= max( max( m_vScale.x, m_vScale.y ), m_vScale.z );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::UpdateCollisionPrimitive( EtMatrix &WorldMat )
|
|||
|
|
{
|
|||
|
|
if( !IsEnableCollision() )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int i;
|
|||
|
|
EtMatrix *pBoneMat, AniMat;
|
|||
|
|
|
|||
|
|
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
|
|||
|
|
{
|
|||
|
|
pBoneMat = &WorldMat;
|
|||
|
|
if( m_vecPrimitiveParentIndex[ i ] != -1 )
|
|||
|
|
{
|
|||
|
|
pBoneMat = GetBoneMat( m_vecPrimitiveParentIndex[ i ] );
|
|||
|
|
if( pBoneMat )
|
|||
|
|
{
|
|||
|
|
pBoneMat = EtMatrixMultiply( &AniMat, pBoneMat, &WorldMat );
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pBoneMat = &WorldMat;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
CEtCollisionEntity::UpdateCollisionPrimitive( i, *pBoneMat );
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool CEtObject::FindDynamicCollision( EtMatrix &WorldMat, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime, bool bUpdatePrimitive )
|
|||
|
|
{
|
|||
|
|
SAABox BoundingBox;
|
|||
|
|
EtVector3 vMove;
|
|||
|
|
|
|||
|
|
vMove.x = WorldMat._41 - m_WorldMat._41;
|
|||
|
|
vMove.y = WorldMat._42 - m_WorldMat._42;
|
|||
|
|
vMove.z = WorldMat._43 - m_WorldMat._43;
|
|||
|
|
GetBoundingBox( BoundingBox );
|
|||
|
|
BoundingBox.Max += vMove;
|
|||
|
|
BoundingBox.Min += vMove;
|
|||
|
|
if( bUpdatePrimitive )
|
|||
|
|
{
|
|||
|
|
UpdateCollisionPrimitive( WorldMat );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return _FindDynamicCollision( BoundingBox, vMove, vecResponse, bCalcContactTime );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool CEtObject::_FindDynamicCollision( SAABox &BoundingBox, EtVector3 &vMove, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime )
|
|||
|
|
{
|
|||
|
|
STATIC_DECL( DNVector(CEtObject*) vecPickObject );
|
|||
|
|
|
|||
|
|
bool bRet = false;
|
|||
|
|
STATIC_INSTANCE( vecPickObject ).clear();
|
|||
|
|
STATIC_INSTANCE( s_DynamicOctree ).Pick( BoundingBox, STATIC_INSTANCE( vecPickObject ) );
|
|||
|
|
if( !STATIC_INSTANCE( vecPickObject ).empty() )
|
|||
|
|
{
|
|||
|
|
int i;
|
|||
|
|
|
|||
|
|
for( i = 0; i < ( int )STATIC_INSTANCE( vecPickObject ).size(); i++ )
|
|||
|
|
{
|
|||
|
|
std::vector< SCollisionPrimitive * > *pTargetPrimitive;
|
|||
|
|
|
|||
|
|
if( !STATIC_INSTANCE( vecPickObject )[ i ]->IsEnableCollision() )
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
if( ( STATIC_INSTANCE( vecPickObject )[ i ]->GetCollisionGroup() & GetTargetCollisionGroup() ) == 0 )
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
pTargetPrimitive = STATIC_INSTANCE( vecPickObject )[ i ]->GetCollisionPrimitive();
|
|||
|
|
if( !pTargetPrimitive )
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
if( CEtCollisionEntity::FindCollision( *pTargetPrimitive, vMove, vecResponse, bCalcContactTime ) )
|
|||
|
|
{
|
|||
|
|
bRet = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return bRet;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool CEtObject::FindCollision( EtMatrix &WorldMat, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime, bool bUpdaePrimitive )
|
|||
|
|
{
|
|||
|
|
if( !IsEnableCollision() )
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SAABox BoundingBox;
|
|||
|
|
EtVector3 vMove;
|
|||
|
|
bool bResult;
|
|||
|
|
PROFILE_TIME_TEST_BLOCK_START( "FindCollision1" );
|
|||
|
|
|
|||
|
|
vMove.x = WorldMat._41 - m_WorldMat._41;
|
|||
|
|
vMove.y = WorldMat._42 - m_WorldMat._42;
|
|||
|
|
vMove.z = WorldMat._43 - m_WorldMat._43;
|
|||
|
|
GetBoundingBox( BoundingBox );
|
|||
|
|
BoundingBox.Max += vMove;
|
|||
|
|
BoundingBox.Min += vMove;
|
|||
|
|
|
|||
|
|
if( bUpdaePrimitive )
|
|||
|
|
{
|
|||
|
|
UpdateCollisionPrimitive( WorldMat );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bResult = CEtCollisionMng::GetInstance(GetRoom()).FindCollision( m_vecPrimitive, BoundingBox, vMove, vecResponse, bCalcContactTime );
|
|||
|
|
|
|||
|
|
if( _FindDynamicCollision( BoundingBox, vMove, vecResponse, bCalcContactTime ) )
|
|||
|
|
{
|
|||
|
|
bResult = true;
|
|||
|
|
}
|
|||
|
|
PROFILE_TIME_TEST_BLOCK_END();
|
|||
|
|
|
|||
|
|
return bResult;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool CEtObject::FindCollision( EtObjectHandle hObject, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime )
|
|||
|
|
{
|
|||
|
|
int i, j;
|
|||
|
|
SCollisionResponse Response;
|
|||
|
|
bool bResult = false;
|
|||
|
|
std::vector< SCollisionPrimitive * > &vecTragetPrimitive = *hObject->GetCollisionPrimitive();
|
|||
|
|
|
|||
|
|
PROFILE_TIME_TEST_BLOCK_START( "FindCollision2" );
|
|||
|
|
for( i = 0; i < ( int )m_vecPrimitive.size(); i++ )
|
|||
|
|
{
|
|||
|
|
if( !m_vecPrimitiveEnable[ i ] )
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
for( j = 0; j < ( int )vecTragetPrimitive.size(); j++ )
|
|||
|
|
{
|
|||
|
|
if( !hObject->IsEnableCollision( vecTragetPrimitive[ j ] ) )
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
PROFILE_TIME_TEST_BLOCK_END();
|
|||
|
|
|
|||
|
|
return bResult;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::GetExtent( EtVector3 &Origin, EtVector3 &Extent )
|
|||
|
|
{
|
|||
|
|
Origin = ( m_BoundingBox.Max + m_BoundingBox.Min ) / 2;
|
|||
|
|
Extent = ( m_BoundingBox.Max - m_BoundingBox.Min ) / 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtObject::SetWorldSize( CMultiRoom *pRoom, EtVector3 &WorldCenter, float fRadius )
|
|||
|
|
{
|
|||
|
|
STATIC_INSTANCE_(s_DynamicOctree).Initialize( WorldCenter, fRadius );
|
|||
|
|
STATIC_INSTANCE_(s_DynamicOctree).UseLock( false );
|
|||
|
|
|
|||
|
|
int i, nItemCount;
|
|||
|
|
|
|||
|
|
nItemCount = GetItemCount(pRoom);
|
|||
|
|
for( i = 0; i < nItemCount; i++ )
|
|||
|
|
{
|
|||
|
|
EtObjectHandle hObject = GetItem( pRoom, i );
|
|||
|
|
if( hObject ) hObject->m_pCurOctreeNode = NULL;
|
|||
|
|
}
|
|||
|
|
}
|