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

242 lines
5.3 KiB
C++

#include "StdAfx.h"
#include "EtLight.h"
#include "EtOptionController.h"
#if !defined( USE_BOOST_MEMPOOL )
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
#endif
DECL_SMART_PTR_STATIC( CEtLight, 5 )
EtColor CEtLight::s_GlobalAmbient = EtColor( 1.0f, 1.0f, 1.0f, 1.0f );
std::vector< CEtLight * > CEtLight::s_vecDirectionalLight;
std::vector< CEtLight * > CEtLight::s_vecPointLight;
std::vector< CEtLight * > CEtLight::s_vecSpotLight;
std::vector< CEtLight * > CEtLight::s_vecInfluencePointLight;
std::vector< CEtLight * > CEtLight::s_vecInfluenceSpotLight;
float CEtLight::s_fDirLightAttenuation = 1.0f;
CEtOctree< CEtLight * > *CEtLight::s_pLightOctree = NULL;
float CEtOctreeNode< CEtLight * >::s_fMinRadius = 1000.0f;
CEtLight::CEtLight(void)
{
m_bEnable = true;
m_pCurOctreeNode = NULL;
}
CEtLight::~CEtLight(void)
{
std::vector< CEtLight * > *pvecLight;
std::vector< CEtLight * >::iterator Iter;
if( m_pCurOctreeNode )
{
s_pLightOctree->Remove( this, m_pCurOctreeNode );
}
switch( m_LightInfo.Type )
{
case LT_DIRECTIONAL:
pvecLight = &s_vecDirectionalLight;
break;
case LT_POINT:
pvecLight = &s_vecPointLight;
break;
case LT_SPOT:
pvecLight = &s_vecSpotLight;
break;
}
Iter = std::find( pvecLight->begin(), pvecLight->end(), this );
if( Iter != pvecLight->end() )
{
pvecLight->erase( Iter );
}
SAFE_RELEASE_SPTR( m_hPointLightDecal );
}
void CEtLight::InitializeClass()
{
s_pLightOctree = new CEtOctree< CEtLight * >;
}
void CEtLight::FinalizeClass()
{
SAFE_DELETE( s_pLightOctree );
}
void CEtLight::Initialize( SLightInfo *pSLightInfo, EtObjectHandle hCastLightObject )
{
m_LightInfo = *pSLightInfo;
m_hLightCastObject = hCastLightObject;
switch( m_LightInfo.Type )
{
case LT_DIRECTIONAL:
s_vecDirectionalLight.push_back( this );
break;
case LT_POINT:
{
SSphere BoundingSphere;
if( !m_hLightCastObject )
{
AddDecal();
}
s_vecPointLight.push_back( this );
BoundingSphere.Center = m_LightInfo.Position;
BoundingSphere.fRadius = m_LightInfo.fRange;
m_pCurOctreeNode = s_pLightOctree->Insert( this, BoundingSphere );
if( hCastLightObject )
{
hCastLightObject->CalcLightInfluence();
}
else
{
CEtObject::CalcLightInfluenceList();
}
}
break;
case LT_SPOT:
{
SSphere BoundingSphere;
s_vecSpotLight.push_back( this );
BoundingSphere.Center = m_LightInfo.Position;
BoundingSphere.fRadius = m_LightInfo.fRange;
m_pCurOctreeNode = s_pLightOctree->Insert( this, BoundingSphere );
if( hCastLightObject )
{
hCastLightObject->CalcLightInfluence();
}
else
{
CEtObject::CalcLightInfluenceList();
}
}
break;
}
}
void CEtLight::SetLightInfo( SLightInfo *pSLightInfo )
{
if( m_LightInfo.Type != pSLightInfo->Type )
{
return;
}
m_LightInfo = *pSLightInfo;
if( ( m_LightInfo.Type == LT_POINT ) && ( !m_hLightCastObject ) )
{
SAFE_RELEASE_SPTR( m_hPointLightDecal );
AddDecal();
}
}
void CEtLight::GetBoundingSphere( SSphere &Sphere, bool bActorSize/* = false*/ )
{
Sphere.Center = m_LightInfo.Position;
Sphere.fRadius = m_LightInfo.fRange;
}
void CEtLight::AddDecal()
{
EtTerrainHandle hTerrainArea;
float fLightHeight, fRadius;
m_LightInfo.Diffuse.a = 1.0f;
hTerrainArea = CEtTerrainArea::GetTerrainArea( m_LightInfo.Position.x, m_LightInfo.Position.z );
if( !hTerrainArea )
{
return;
}
fLightHeight = m_LightInfo.Position.y - hTerrainArea->GetLandHeight( m_LightInfo.Position.x, m_LightInfo.Position.z, NULL );
if( fLightHeight < 0.0f )
{
return;
}
fRadius = m_LightInfo.fRange * m_LightInfo.fRange - fLightHeight * fLightHeight;
if( fRadius < 0.0f )
{
return;
}
CEtPointLightDecal *pDecal;
pDecal = new CEtPointLightDecal();
pDecal->Initialize( m_LightInfo, sqrtf( fRadius ), FLT_MAX );
m_hPointLightDecal = pDecal->GetMySmartPtr();
}
SLightInfo *CEtLight::GetShadowCastDirLightInfo()
{
//ASSERT( !s_vecDirectionalLight.empty() );
if( s_vecDirectionalLight.empty() )
{
return NULL;
}
int i;
for( i = 0; i < ( int )s_vecDirectionalLight.size(); i++ )
{
if( ( s_vecDirectionalLight[ i ]->m_LightInfo.bCastShadow ) && ( s_vecDirectionalLight[ i ]->IsEnable() ) )
{
return s_vecDirectionalLight[ i ]->GetLightInfo();
}
}
return s_vecDirectionalLight[ 0 ]->GetLightInfo();
}
void CEtLight::SetWorldSize( EtVector3 &WorldCenter, float fRadius )
{
s_pLightOctree->Initialize( WorldCenter, fRadius );
}
void CEtLight::CalcLightInfluence( SSphere &Sphere, DNVector(CEtLight *) &vecInfluenceLight, EtObjectHandle CalcLightObject )
{
s_pLightOctree->Pick( Sphere, vecInfluenceLight );
DNVector( CEtLight * )::iterator it;
for( it = vecInfluenceLight.begin(); it != vecInfluenceLight.end(); )
{
if( ( *it )->m_hLightCastObject )
{
if( ( *it )->m_hLightCastObject != CalcLightObject )
{
it = vecInfluenceLight.erase( it );
continue;
}
}
++it;
}
}
void CEtLight::SetInfluenceLight( CEtLight **ppLight )
{
int nIndex;
s_vecInfluencePointLight.clear();
s_vecInfluenceSpotLight.clear();
if( ppLight == NULL ) return;
nIndex = 0;
while( ppLight[ nIndex ] )
{
switch( ppLight[ nIndex ]->m_LightInfo.Type )
{
case LT_POINT:
s_vecInfluencePointLight.push_back( ppLight[ nIndex ] );
break;
case LT_SPOT:
s_vecInfluenceSpotLight.push_back( ppLight[ nIndex ] );
break;
}
nIndex++;
}
}