DragonNest/Common/EternityEngine/EtObject.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

1209 lines
No EOL
26 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtObject.h"
#include "EtConvexVolume.h"
#include "EtFindCollision.h"
#include "EtLoader.h"
#include "EtCustomParam.h"
#include "EtGenerateCollisionMesh.h"
#include "EtOptionController.h"
#include "EtCollisionMng.h"
#include "EtWater.h"
#include "EtEngine.h"
#include "EtFrustum.h"
#include "EtSkyBoxRTT.h"
#if !defined( USE_BOOST_MEMPOOL )
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
#endif
using namespace EternityEngine;
DECL_SMART_PTR_STATIC( CEtObject, 3000 )
CEtOctree< CEtObject * > *CEtObject::s_pDynamicOctree = NULL;
float CEtOctreeNode< CEtObject * >::s_fMinRadius = 1000.0f;
bool CEtObject::m_bSkipDrawCollision = false;
CEtObject::CEtObject(void)
: CSmartPtrBase< CEtObject >()
{
SetChild( false );
ShowObject( true );
EnableObject( true );
EnableCull( true );
EnableShadowCast( false );
m_bShadowReceive = false;
m_bLightMapInfluence = false;
EnableLightMapCast( false );
EnableWaterCast( false );
ShowBoundingBox( false );
ShowCollisionPrimitive( false );
EtMatrixIdentity( &m_WorldMat );
m_WorldMat._41 = m_WorldMat._42 = m_WorldMat._43 = FLT_MAX;
m_PrevWorldMat._11 = FLT_MAX;
EtMatrixIdentity( &m_LinkOffsetMat );
m_nLinkBoneIndex = -1;
m_nSaveMatIndex = -1;
m_bValidSaveMatIndex = false;
m_pSkinInstance = NULL;
m_fObjectAlpha = 1.0f;
m_pCurOctreeNode = NULL;
m_BoundingBox.Min = EtVector3( 0.f, 0.f, 0.f );
m_BoundingBox.Max = EtVector3( 0.f, 0.f, 0.f );
m_OriginalBoundingBox.Min = EtVector3( 0.f, 0.f, 0.f );
m_OriginalBoundingBox.Max = EtVector3( 0.f, 0.f, 0.f );
m_RenderType = RT_SCREEN;
m_bAniObject = false;
m_LinkType = LT_BONE;
m_nFrustumMask = 0;
}
CEtObject::~CEtObject(void)
{
if( m_hParent )
{
m_hParent->RemoveChild( GetMySmartPtr() );
}
if( m_pCurOctreeNode )
{
s_pDynamicOctree->Remove( this, m_pCurOctreeNode );
}
SAFE_DELETE( m_pSkinInstance );
Clear();
}
void CEtObject::Clear()
{
SAFE_RELEASE_SPTR( m_hSkin );
}
void CEtObject::InitializeClass()
{
s_pDynamicOctree = new CEtOctree< CEtObject * >;
}
void CEtObject::FinalizeClass()
{
SAFE_DELETE( s_pDynamicOctree );
}
int CEtObject::Initialize( EtSkinHandle hSkin )
{
Clear();
m_hSkin = hSkin;
m_pSkinInstance = new CEtSkinInstance();
if( !m_hSkin->AddCallback( this ) )
{
CommonInitialize();
}
return ET_OK;
}
void CEtObject::CommonInitialize()
{ CreateSkinInstance();
if( m_hSkin->GetMeshHandle() )
CEtCollisionEntity::Initialize( *m_hSkin->GetMeshHandle()->GetCollisionPrimitive(), *m_hSkin->GetMeshHandle()->GetCollisionPrimitiveParentIndex() );
UpdateCollisionPrimitive( m_WorldMat );
GetMeshBoundingBox( m_OriginalBoundingBox );
GetMeshBoundingSphere( m_OriginalBoundingSphere );
}
void CEtObject::CreateSkinInstance()
{
if( m_hSkin )
{
if( m_pSkinInstance == NULL )
{
m_pSkinInstance = new CEtSkinInstance();
}
m_pSkinInstance->CopySkinInfo( m_hSkin );
if( m_pSkinInstance->IsSkyBox() )
{
CEtSkyBoxRTT::GetInstance().AddObject( m_MySmartPtr );
CEtSkyBoxRTT::GetInstance().SetRenderFrameCount( -1 );
}
}
}
RenderType CEtObject::SetRenderType( RenderType Type )
{
RenderType Ret = m_RenderType;
m_RenderType = Type;
return Ret;
}
void CEtObject::SetParent( EtObjectHandle hObject, const char *pLinkBoneName, EtMatrix *pOffsetMat )
{
EtMeshHandle hMesh = hObject->GetMesh();
int nLinkBoneIndex = -1;
if( hMesh )
{
nLinkBoneIndex = hMesh->FindDummy( pLinkBoneName );
if( nLinkBoneIndex != -1 )
{
SetParent( hObject, nLinkBoneIndex, pOffsetMat, LT_MESH_DUMMY );
return;
}
nLinkBoneIndex = hMesh->FindBone( pLinkBoneName );
if( nLinkBoneIndex != -1 )
{
SetParent( hObject, nLinkBoneIndex, pOffsetMat, LT_BONE );
return;
}
}
}
void CEtObject::SetParent( EtObjectHandle hObject, int nBoneIndex, EtMatrix *pOffsetMat, LinkType Type )
{
if ( hObject == GetMySmartPtr() )
{
ASSERT( false && "hObject == GetMySmartPtr()" );
return;
}
// <20>Լ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD> <20><><EFBFBD><EFBFBD>!!!
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
if( m_hParent )
{
m_hParent->RemoveChild( GetMySmartPtr() );
}
if( hObject )
{
m_hParent = hObject;
m_nLinkBoneIndex = nBoneIndex;
m_LinkType = Type;
if( pOffsetMat )
{
m_LinkOffsetMat = *pOffsetMat;
}
m_hParent->AddChild( GetMySmartPtr() );
EnableShadowCast( m_hParent->IsShadowCast() );
EnableShadowReceive( m_hParent->IsShadowReceive() );
EnableLightMapInfluence( m_hParent->IsLightMapInfluence() );
SetObjectAlpha( m_hParent->GetObjectAlpha() );
SetChild( true );
int nItemIndex, nParentItemIndex;
nItemIndex = GetMyItemIndex();
nParentItemIndex = m_hParent->GetMyItemIndex();
if( nItemIndex < nParentItemIndex )
{
SwapItemIndex( nItemIndex, nParentItemIndex );
}
}
else
{
m_hParent.Identity();
m_nLinkBoneIndex = -1;
EtMatrixIdentity( &m_LinkOffsetMat );
SetChild( false );
}
}
void CEtObject::AddChild( EtObjectHandle hObject )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
m_vecChild.push_back( hObject );
if( m_hSkin->IsReady() )
{
RecalcBoundingBox();
RecalcBoundingSphere();
}
}
void CEtObject::RemoveChild( EtObjectHandle hObject )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i;
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
if( m_vecChild[ i ] == hObject )
{
m_vecChild.erase( m_vecChild.begin() + i );
RecalcBoundingBox();
RecalcBoundingSphere();
return;
}
}
ASSERT( 0 && "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> child<6C><64> <20><><EFBFBD><EFBFBD>" );
}
bool CEtObject::IsShow()
{
if( !m_hSkin ) return false;
return m_bShow && m_hSkin->IsReady();
}
void CEtObject::EnableLightMapInfluence( bool bEnable )
{
m_bLightMapInfluence = bEnable;
CalcLightMapInfluence();
}
void CEtObject::ShowSubmesh( int nSubmeshIndex, bool bShow )
{
if( m_pSkinInstance )
{
m_pSkinInstance->GetSkinRenderInfo( nSubmeshIndex )->bShowSubmesh = bShow;
}
}
bool CEtObject::IsShowSubmesh( int nSubmeshIndex )
{
if( m_pSkinInstance )
{
return m_pSkinInstance->GetSkinRenderInfo( nSubmeshIndex )->bShowSubmesh;
}
return true;
}
void CEtObject::SetFrustumMask( int nMask )
{
m_nFrustumMask = nMask;
}
void CEtObject::AddFrustumMask( int nMask )
{
m_nFrustumMask |= nMask;
int i, nCount;
nCount = ( int )m_vecChild.size();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hObject = m_vecChild[ i ];
hObject->AddFrustumMask( nMask );
}
}
void CEtObject::EnableShadowCast( bool bEnable )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
m_bShadowCast = bEnable;
int i, nCount;
nCount = ( int )m_vecChild.size();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hObject = m_vecChild[ i ];
hObject->EnableShadowCast( bEnable );
}
}
void CEtObject::EnableShadowReceive( bool bEnable )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
m_bShadowReceive = bEnable;
int i, nCount;
nCount = ( int )m_vecChild.size();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hObject = m_vecChild[ i ];
hObject->EnableShadowReceive( bEnable );
}
}
void CEtObject::SetObjectAlpha( float fAlpha )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
m_fObjectAlpha = fAlpha;
int i, nCount;
nCount = ( int )m_vecChild.size();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hObject = m_vecChild[ i ];
hObject->SetObjectAlpha( fAlpha );
}
}
void CEtObject::Update( EtMatrix *pWorldMat )
{
SSphere Sphere;
if( m_PrevWorldMat._11 == FLT_MAX )
{
m_PrevWorldMat = *pWorldMat;
m_bUpdateNeeded = true;
}
else
{
m_PrevWorldMat = m_WorldMat;
if( memcmp ( &m_PrevWorldMat, pWorldMat , sizeof(EtMatrix) ) != 0 ) {
m_bUpdateNeeded = true;
}
}
m_WorldMat = *pWorldMat;
UpdateBoundingPrimitive();
CalcLightInfluence();
CalcLightMapInfluence();
if( ( m_hSkin ) && ( !IsChild() ) )
{
UpdateCollisionPrimitive( m_WorldMat, m_bUpdateNeeded );
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 = s_pDynamicOctree->Update( this, Sphere, m_pCurOctreeNode );
}
else
{
m_pCurOctreeNode = s_pDynamicOctree->Insert( this, Sphere );
}
}
}
m_bUpdateNeeded = false;
}
void CEtObject::CalcParentBoneMat()
{
EtMatrix LinkMat, *pBoneMat;
EtMatrixMultiply( &LinkMat, m_hParent->GetWorldMat(), &m_LinkOffsetMat );
if( m_nLinkBoneIndex != -1 )
{
if( m_LinkType == LT_BONE )
{
pBoneMat = m_hParent->GetBoneTransMat( m_nLinkBoneIndex );
}
else
{
pBoneMat = m_hParent->GetDummyTransMat( m_nLinkBoneIndex );
}
if( pBoneMat )
{
EtMatrixMultiply( &LinkMat, pBoneMat, &LinkMat );
}
}
Update( &LinkMat );
}
void CEtObject::InitRender( int nSaveMatIndex )
{
if( !IsShow() )
{
return;
}
if( m_hParent )
{
CalcParentBoneMat();
}
int i;
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
m_vecChild[ i ]->InitRender( nSaveMatIndex );
}
}
void CEtObject::Render()
{
if( !IsShow() )
{
return;
}
if( IsShowBoundingBox() )
{
DrawBoundingBox();
}
if( m_pSkinInstance )
{
m_pSkinInstance->Render( m_WorldMat, m_PrevWorldMat, m_fObjectAlpha, m_vecInfluenceLight, m_bShadowReceive, m_nSaveMatIndex );
}
}
void CEtObject::RenderImmediate( bool bRenderChild )
{
if( !IsShow() )
{
return;
}
if( m_pSkinInstance )
{
m_pSkinInstance->RenderImmediate( m_WorldMat, m_WorldMat, m_fObjectAlpha, m_vecInfluenceLight, m_bShadowReceive, false, m_nSaveMatIndex );
}
if( bRenderChild )
{
int i;
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
if( m_vecChild[ i ] )
{
m_vecChild[ i ]->RenderImmediate( bRenderChild );
}
}
}
}
void CEtObject::RenderAlphaImmediate( bool bRenderChild )
{
if( !IsShow() )
{
return;
}
if( m_pSkinInstance )
{
m_pSkinInstance->RenderImmediate( m_WorldMat, m_WorldMat, m_fObjectAlpha, m_vecInfluenceLight, m_bShadowReceive, true, m_nSaveMatIndex );
}
if( bRenderChild )
{
int i;
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
if( m_vecChild[ i ] )
{
m_vecChild[ i ]->RenderAlphaImmediate( bRenderChild );
}
}
}
}
void CEtObject::RenderShadow()
{
if( !IsShow() )
{
return;
}
if( m_pSkinInstance )
{
m_pSkinInstance->RenderShadow( m_WorldMat, m_nSaveMatIndex );
}
}
void CEtObject::RenderWater( int index )
{
if( !IsShow() )
{
return;
}
if( m_pSkinInstance )
{
if( !m_hParent )
{
InitRender();
m_pSkinInstance->RenderWater( index, m_WorldMat, m_PrevWorldMat, m_fObjectAlpha, m_vecInfluenceLight, m_bShadowReceive, m_nSaveMatIndex );
}
}
}
void CEtObject::SetSaveMatIndex( int nIndex )
{
m_nSaveMatIndex = nIndex;
int i;
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
m_vecChild[ i ]->SetSaveMatIndex( nIndex );
}
}
void CEtObject::GetMeshBoundingBox( SAABox &AABox )
{
if( m_hSkin )
{
EtMeshHandle hMesh = m_hSkin->GetMeshHandle();
if( hMesh )
{
hMesh->GetBoundingBox( AABox );
}
return;
}
AABox.Min = EtVector3( -1.0f, -1.0f, -1.0f );
AABox.Max = EtVector3( 1.0f, 1.0f, 1.0f );
}
void CEtObject::GetMeshBoundingSphere( SSphere &Sphere )
{
if( m_hSkin )
{
EtMeshHandle hMesh = m_hSkin->GetMeshHandle();
if( hMesh )
{
hMesh->GetBoundingSphere( Sphere );
}
return;
}
Sphere.Center = EtVector3( 0.0f, 0.0f, 0.0f );
Sphere.fRadius = 1.0f;
}
void CEtObject::RecalcBoundingBox()
{
SAABox BoundingBox;
GetMeshBoundingBox( m_OriginalBoundingBox );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ϵ尡 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>־ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD>߱<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>..
/* for( int i = 0; i < ( int )m_vecChild.size(); i++ )
{
m_vecChild[ i ]->GetMeshBoundingBox( BoundingBox );
m_OriginalBoundingBox.AddPoint( BoundingBox.Max );
m_OriginalBoundingBox.AddPoint( BoundingBox.Min );
}*/
}
void CEtObject::RecalcBoundingSphere()
{
int i;
EtVector3 vDirection, vOriginalEnd, vChildEnd;
SSphere BoundingSphere;
GetMeshBoundingSphere( m_OriginalBoundingSphere );
for( i = 0; i < ( int )m_vecChild.size(); i++ )
{
m_vecChild[ i ]->GetMeshBoundingSphere( BoundingSphere );
if( m_OriginalBoundingSphere.IsInside( BoundingSphere ) )
{
continue;
}
vDirection = BoundingSphere.Center - m_OriginalBoundingSphere.Center;
EtVec3Normalize( &vDirection, &vDirection );
vOriginalEnd = m_OriginalBoundingSphere.Center - vDirection * m_OriginalBoundingSphere.fRadius;
vChildEnd = BoundingSphere.Center + vDirection * BoundingSphere.fRadius;
m_OriginalBoundingSphere.Center = ( vOriginalEnd + vChildEnd ) * 0.5f;
m_OriginalBoundingSphere.fRadius = EtVec3Length( &( vOriginalEnd - vChildEnd ) ) * 0.5f;
}
}
void CEtObject::DrawBoundingBox( DWORD dwColor )
{
int i;
static short s_LineIndices[] =
{
0, 1, 1, 3, 3, 2, 2, 0,
4, 5, 5, 7, 7, 6, 6, 4,
0, 4, 1, 5, 3, 7, 2, 6,
};
SOBB OBBox;
OBBox.Init( m_OriginalBoundingBox, m_WorldMat );
for( i = 0; i < sizeof( s_LineIndices ) / sizeof( short ) / 2; i++ )
{
DrawLine3D( OBBox.Vertices[ s_LineIndices[ i * 2 ] ], OBBox.Vertices[ s_LineIndices[ i * 2 + 1 ] ], dwColor );
}
}
void CEtObject::UpdateBoundingPrimitive()
{
if( !m_hSkin )
{
return;
}
if( !m_bUpdateNeeded ) { // Static Object <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ź<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD>.
return;
}
if( !m_OriginalBoundingBox.IsValid() ) {
return;
}
m_BoundingBox.Reset();
SOBB OBBox;
OBBox.Init( m_OriginalBoundingBox, m_WorldMat );
for( int i = 0; i < 8; i++) {
m_BoundingBox.AddPoint( OBBox.Vertices[i] );
}
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, bool bUpdate )
{
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 );
}
else {
CEtCollisionEntity::UpdateCollisionPrimitive( i, *pBoneMat, bUpdate );
}
}
}
bool CEtObject::FindDynamicCollision( EtMatrix &WorldMat, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime, bool bUpdaetPrimitive)
{
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( bUpdaetPrimitive )
{
UpdateCollisionPrimitive( WorldMat );
m_bUpdateNeeded = true;
}
return _FindDynamicCollision( BoundingBox, vMove, vecResponse, bCalcContactTime );
}
bool CEtObject::_FindDynamicCollision( SAABox &BoundingBox, EtVector3 &vMove, DNVector(SCollisionResponse) &vecResponse, bool bCalcContactTime)
{
static DNVector(CEtObject *) vecPickObject;
bool bRet = false;
vecPickObject.clear();
s_pDynamicOctree->Pick( BoundingBox, vecPickObject );
if( !vecPickObject.empty() )
{
int i;
for( i = 0; i < ( int )vecPickObject.size(); i++ )
{
std::vector< SCollisionPrimitive * > *pTargetPrimitive;
if( !vecPickObject[ i ]->IsEnableCollision() )
{
continue;
}
if( ( vecPickObject[ i ]->GetCollisionGroup() & GetTargetCollisionGroup() ) == 0 )
{
continue;
}
pTargetPrimitive = 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 bUpdaetPrimitive)
{
if( !IsEnableCollision() )
{
return false;
}
SAABox BoundingBox;
EtVector3 vMove;
bool bResult;
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( bUpdaetPrimitive )
{
UpdateCollisionPrimitive( WorldMat );
m_bUpdateNeeded = true;
}
bResult = CEtCollisionMng::GetInstance().FindCollision( m_vecPrimitive, BoundingBox, vMove, vecResponse, bCalcContactTime );
if( _FindDynamicCollision( BoundingBox, vMove, vecResponse, bCalcContactTime ) )
{
bResult = true;
}
return bResult;
}
bool CEtObject::FindCollision( EtObjectHandle hObject, std::vector< SCollisionResponse > &vecResponse, bool bCalcContactTime )
{
int i, j;
SCollisionResponse Response;
bool bResult = false;
std::vector< SCollisionPrimitive * > &vecTragetPrimitive = *hObject->GetCollisionPrimitive();
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;
}
}
}
return bResult;
}
int CEtObject::AddCustomParam( const char *pParamName )
{
if( m_pSkinInstance )
{
return m_pSkinInstance->AddCustomParam( pParamName );
}
return -1;
}
bool CEtObject::SetCustomParam( int nParamIndex, void *pValue, int nSubMeshIndex )
{
if( m_pSkinInstance )
{
return m_pSkinInstance->SetCustomParam( nParamIndex, pValue, nSubMeshIndex );
}
return false;
}
void CEtObject::RestoreCustomParam( int nParamIndex, int nSubMeshIndex )
{
if( m_pSkinInstance )
{
m_pSkinInstance->RestoreCustomParam( nParamIndex, nSubMeshIndex );
}
}
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::ClearFrustumMask()
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
GetItem( i )->SetFrustumMask( 0 );
}
}
void CEtObject::MaskFrustumObjectList( CEtConvexVolume *pFrustum, int nFrustumMask )
{
int i, j, nCount;
int nWaterCount = GetEtWater()->GetWaterCount();
std::vector<CEtConvexVolume> ReflectFrustumList;
ReflectFrustumList.resize( nWaterCount );
for( i = 0; i < nWaterCount; i++) {
ReflectFrustumList[i].Initialize( GetEtWater()->GetViewProjMat( i ) );
}
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtVector3 Origin, Extent;
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
CEtObject *pObject = hHandle.GetPointer();
if( !pObject->IsEnable() )
{
continue;
}
if( pObject->IsChild() )
{
continue;
}
if( !pObject->IsShow() )
{
continue;
}
pObject->GetExtent( Origin, Extent );
if( ( !pObject->IsEnableCull() ) || pFrustum->TesToBox( Origin, Extent ) )
{
pObject->AddFrustumMask( nFrustumMask );
}
if( pObject->IsWaterCast() )
{
for( j = 0; j < nWaterCount; j++)
{
if( GetEtWater()->GetWaterIgnoreBake( j ) )
continue;
if( ( !pObject->IsEnableCull() ) || ( ReflectFrustumList[j].TesToBox( Origin, Extent ) ) )
{
pObject->RenderWater( j );
}
}
}
}
}
void CEtObject::InitRenderObjectList()
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
if( hHandle->IsChild() )
{
continue;
}
if( hHandle->GetFrustumMask() )
{
hHandle->InitRender();
}
}
}
void CEtObject::RenderObjectList( int nMask )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
if( hHandle->GetRenderType() != CT_SCREEN )
{
continue;
}
if( hHandle->GetFrustumMask() & nMask )
{
hHandle->Render();
}
}
}
void CEtObject::RenderShadowObjectList( int nMask, float fShadowRange )
{
int i, nCount;
CEtConvexVolume Frustum;
EtMatrix ProjMat;
EtCameraHandle hCamera;
hCamera = CEtCamera::GetActiveCamera();
EtMatrixPerspectiveFovLH( &ProjMat, hCamera->GetFOV(), hCamera->GetAspectRatio(), hCamera->GetCameraNear(), fShadowRange );
EtMatrixMultiply( &ProjMat, hCamera->GetViewMat(), &ProjMat );
Frustum.Initialize( ProjMat );
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
if( hHandle->GetRenderType() != CT_SCREEN )
{
continue;
}
if( ( hHandle->GetFrustumMask() & nMask ) && ( hHandle->IsShadowCast() ) && ( hHandle->GetObjectAlpha() > 0.5f ) )
{
EtVector3 Origin, Extent;
hHandle->GetExtent( Origin, Extent );
if( ( !hHandle->IsEnableCull() ) || Frustum.TesToBox( Origin, Extent ) )
{
hHandle->RenderShadow();
}
}
}
}
void CEtObject::DrawCollisionList( int nMask )
{
if( m_bSkipDrawCollision ) { // <20>׷<EFBFBD><D7B7><EFBFBD><EFBFBD>°<EFBFBD><C2B0><EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
return;
}
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
bool bDraw = false;
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
if( hHandle->GetRenderType() != CT_SCREEN )
{
continue;
}
if( hHandle->IsShowCollisionPrimitive() ) bDraw = true;
if( hHandle->GetFrustumMask() & nMask )
{
hHandle->DrawCollisionPrimitive();
}
}
if( !bDraw ) {
m_bSkipDrawCollision = true;
}
}
void CEtObject::CalcLightInfluence()
{
if( !m_bUpdateNeeded ) {
return;
}
m_vecInfluenceLight.clear();
CEtLight::CalcLightInfluence( m_BoundingSphere, m_vecInfluenceLight, m_MySmartPtr );
struct CompareFunc {
EtVector3 m_vOffset;
CompareFunc( EtVector3 &vOffset ) : m_vOffset(vOffset) {}
bool operator () ( CEtLight *pLight1, CEtLight *pLight2 ) const
{
float fLength1 = EtVec3LengthSq( &EtVector3( pLight1->GetLightInfo()->Position - m_vOffset ) );
float fLength2 = EtVec3LengthSq( &EtVector3( pLight2->GetLightInfo()->Position - m_vOffset ) );
return fLength1 < fLength2;
}
};
std::sort( m_vecInfluenceLight.begin(), m_vecInfluenceLight.end(), CompareFunc( m_BoundingSphere.Center ) );
int nMaxLightCount = MAX_POINT_LIGHT_COUNT + MAX_SPOT_LIGHT_COUNT - 1;
if( ( int )m_vecInfluenceLight.size() > nMaxLightCount )
{
m_vecInfluenceLight.erase( m_vecInfluenceLight.begin() + nMaxLightCount, m_vecInfluenceLight.end() );
}
}
void CEtObject::CalcLightInfluenceList( bool bForce )
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
if( bForce ) hHandle->SetUpdateNeeded( true );
hHandle->CalcLightInfluence();
}
}
void CEtObject::CalcLightMapInfluence()
{
if( m_pSkinInstance )
{
if( m_bLightMapInfluence )
{
if( m_bUpdateNeeded ) {
float fInfluence = CEtTerrainArea::CalcLightMapInfluence( m_WorldMat._41, m_WorldMat._43 );
m_pSkinInstance->SetDirLightAttenuation( fInfluence );
}
}
else
{
m_pSkinInstance->SetDirLightAttenuation( 1.0f );
}
}
}
void CEtObject::RecalcLightMapInfluence()
{
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
int i, nCount;
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
hHandle->SetUpdateNeeded( true );
hHandle->CalcLightMapInfluence();
}
}
void CEtObject::SetWorldSize( EtVector3 &WorldCenter, float fRadius )
{
CEtLight::SetWorldSize( WorldCenter, fRadius );
s_pDynamicOctree->Initialize( WorldCenter, fRadius );
int i, nItemCount;
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nItemCount = GetItemCount();
for( i = 0; i < nItemCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( !hHandle )
{
continue;
}
hHandle->m_pCurOctreeNode = NULL;
}
}
EtObjectHandle CEtObject::Pick( int nX, int nY, int nCameraIndex )
{
CEtObject *pPickObject;
EtVector3 Position, Direction;
CEtCamera::GetItem( nCameraIndex )->CalcPositionAndDir( nX, nY, Position, Direction );
pPickObject = NULL;
s_pDynamicOctree->Pick( Position, Direction, pPickObject );
if( pPickObject )
{
return pPickObject->GetMySmartPtr();
}
else
{
EtObjectHandle Identity;
return Identity;
}
}
void CEtObject::OnLoadComplete( CBackgroundLoader *pLoader )
{
CommonInitialize();
RecalcBoundingBox();
RecalcBoundingSphere();
Update( &m_WorldMat );
CBackgroundLoaderCallback::OnLoadComplete( pLoader );
}
void CEtObject::AddCollisionMeshToKdTree()
{
if( ( !m_hSkin ) || ( ( m_nCollisionGroup & COLLISION_TYPE_STATIC ) == 0 ) )
{
return;
}
int i;
EtMeshHandle hMesh;
hMesh = m_hSkin->GetMeshHandle();
if( hMesh )
{
for( i = 0; i < hMesh->GetCollisionPrimitiveCount(); i++ )
{
CEtCollisionMng::GetInstance().AddCollisionMeshToKdTree( *( *hMesh->GetCollisionPrimitive() )[ i ], m_WorldMat, m_vScale );
}
}
}
void CEtObject::BuildKdTree()
{
int i, nCount;
CEtCollisionMng::GetInstance().Clear();
ScopeLock<CSyncLock> Lock( s_SmartPtrLock );
nCount = GetItemCount();
for( i = 0; i < nCount; i++ )
{
EtObjectHandle hHandle;
hHandle = GetItem( i );
if( hHandle )
{
if( !hHandle->IsEnableCollision() ) {
continue;
}
hHandle->UpdateCollisionPrimitive( *hHandle->GetWorldMat() );
hHandle->AddCollisionMeshToKdTree();
}
}
CEtCollisionMng::GetInstance().BuildCollisionTree();
}