242 lines
5.3 KiB
C++
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++;
|
|
}
|
|
}
|