346 lines
7.3 KiB
C++
346 lines
7.3 KiB
C++
#include "StdAfx.h"
|
|
#include <algorithm>
|
|
#include "../eterBase/Timer.h"
|
|
|
|
#include "GrpLightManager.h"
|
|
#include "StateManager.h"
|
|
|
|
float CLightBase::ms_fCurTime = 0.0f;
|
|
|
|
CLightManager::CLightManager()
|
|
{
|
|
m_v3CenterPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
|
|
m_dwLimitLightCount = LIGHT_LIMIT_DEFAULT;
|
|
}
|
|
|
|
CLightManager::~CLightManager()
|
|
{
|
|
}
|
|
|
|
void CLightManager::Destroy()
|
|
{
|
|
m_LightPool.Destroy();
|
|
}
|
|
|
|
void CLightManager::Initialize()
|
|
{
|
|
SetSkipIndex(1);
|
|
|
|
m_NonUsingLightIDDeque.clear();
|
|
|
|
m_LightMap.clear();
|
|
m_LightPool.FreeAll();
|
|
}
|
|
|
|
void CLightManager::RegisterLight(ELightType /*LightType*/, TLightID * poutLightID, D3DLIGHT8 & LightData)
|
|
{
|
|
CLight * pLight = m_LightPool.Alloc();
|
|
TLightID ID = NewLightID();
|
|
pLight->SetParameter(ID, LightData);
|
|
m_LightMap[ID] = pLight;
|
|
*poutLightID = ID;
|
|
}
|
|
|
|
void CLightManager::DeleteLight(TLightID LightID)
|
|
{
|
|
TLightMap::iterator itor = m_LightMap.find(LightID);
|
|
|
|
if (m_LightMap.end() == itor)
|
|
{
|
|
assert(!"CLightManager::DeleteLight - Failed to find light ID!");
|
|
return;
|
|
}
|
|
|
|
CLight * pLight = itor->second;
|
|
|
|
pLight->Clear();
|
|
m_LightPool.Free(pLight);
|
|
|
|
m_LightMap.erase(itor);
|
|
|
|
ReleaseLightID(LightID);
|
|
}
|
|
|
|
CLight * CLightManager::GetLight(TLightID LightID)
|
|
{
|
|
TLightMap::iterator itor = m_LightMap.find(LightID);
|
|
|
|
if (m_LightMap.end() == itor)
|
|
{
|
|
assert(!"CLightManager::SetLightData - Failed to find light ID!");
|
|
return NULL;
|
|
}
|
|
|
|
return itor->second;
|
|
}
|
|
|
|
void CLightManager::SetCenterPosition(const D3DXVECTOR3 & c_rv3Position)
|
|
{
|
|
m_v3CenterPosition = c_rv3Position;
|
|
}
|
|
|
|
void CLightManager::SetLimitLightCount(DWORD dwLightCount)
|
|
{
|
|
m_dwLimitLightCount = dwLightCount;
|
|
}
|
|
|
|
void CLightManager::SetSkipIndex(DWORD dwSkipIndex)
|
|
{
|
|
m_dwSkipIndex = dwSkipIndex;
|
|
}
|
|
|
|
struct LightComp
|
|
{
|
|
bool operator () (const CLight * l, const CLight * r) const
|
|
{
|
|
return l->GetDistance() < r->GetDistance();
|
|
}
|
|
};
|
|
|
|
// NOTE : FlushLight후 렌더링
|
|
// 그 후 반드시 RestoreLight를 해줘야만 한다.
|
|
void CLightManager::FlushLight()
|
|
{
|
|
Update();
|
|
|
|
m_LightSortVector.clear();
|
|
|
|
// NOTE: Dynamic과 Static을 분리 시키고 CenterPosition이 바뀔때마다 Static만
|
|
// 다시 Flush 하는 식으로 최적화 할 수 있다. - [levites]
|
|
|
|
// light들의 거리를 추출해 정렬한다.
|
|
TLightMap::iterator itor = m_LightMap.begin();
|
|
|
|
for (; itor != m_LightMap.end(); ++itor)
|
|
{
|
|
CLight * pLight = itor->second;
|
|
|
|
D3DXVECTOR3 v3LightPos(pLight->GetPosition());
|
|
D3DXVECTOR3 v3Distance(v3LightPos - m_v3CenterPosition);
|
|
pLight->SetDistance(D3DXVec3Length(&v3Distance));
|
|
m_LightSortVector.push_back(pLight);
|
|
}
|
|
|
|
// quick sort lights
|
|
std::sort(m_LightSortVector.begin(), m_LightSortVector.end(), LightComp());
|
|
|
|
// NOTE - 거리로 정렬된 라이트를 Limit 갯수 만큼 제한해서 켜준다.
|
|
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, TRUE);
|
|
|
|
for (DWORD k = 0; k < min(m_dwLimitLightCount, m_LightSortVector.size()); ++k)
|
|
{
|
|
m_LightSortVector[k]->Update();
|
|
m_LightSortVector[k]->SetDeviceLight(TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
void CLightManager::RestoreLight()
|
|
{
|
|
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
|
|
|
|
for (DWORD k = 0; k < min(m_dwLimitLightCount, m_LightSortVector.size()); ++k)
|
|
m_LightSortVector[k]->SetDeviceLight(FALSE);
|
|
}
|
|
|
|
TLightID CLightManager::NewLightID()
|
|
{
|
|
if (!m_NonUsingLightIDDeque.empty())
|
|
{
|
|
TLightID id = m_NonUsingLightIDDeque.back();
|
|
m_NonUsingLightIDDeque.pop_back();
|
|
return (id);
|
|
}
|
|
|
|
return m_dwSkipIndex + m_LightMap.size();
|
|
}
|
|
|
|
void CLightManager::ReleaseLightID(TLightID LightID)
|
|
{
|
|
m_NonUsingLightIDDeque.push_back(LightID);
|
|
}
|
|
|
|
void CLightManager::Update()
|
|
{
|
|
//static DWORD s_dwStartTime = ELTimer_GetMSec();
|
|
//ms_fCurTime = float(ELTimer_GetMSec() - s_dwStartTime) / 1000.0f;
|
|
ms_fCurTime = CTimer::Instance().GetCurrentSecond();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CLight::CLight()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
CLight::~CLight()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CLight::Initialize()
|
|
{
|
|
m_LightID = 0;
|
|
m_isEdited = TRUE;
|
|
m_fDistance = 0.0f;
|
|
|
|
memset(&m_d3dLight, 0, sizeof(m_d3dLight));
|
|
|
|
m_d3dLight.Type = D3DLIGHT_POINT;
|
|
m_d3dLight.Attenuation0 = 0.0f;
|
|
m_d3dLight.Attenuation1 = 1.0f;
|
|
m_d3dLight.Attenuation2 = 0.0f;
|
|
}
|
|
|
|
void CLight::Clear()
|
|
{
|
|
if (m_LightID)
|
|
SetDeviceLight(FALSE);
|
|
Initialize();
|
|
}
|
|
|
|
void CLight::SetDeviceLight(BOOL bActive)
|
|
{
|
|
if (bActive && m_isEdited)
|
|
{
|
|
if (ms_lpd3dDevice)
|
|
ms_lpd3dDevice->SetLight(m_LightID, &m_d3dLight);
|
|
}
|
|
if (ms_lpd3dDevice)
|
|
{
|
|
ms_lpd3dDevice->LightEnable(m_LightID, bActive);
|
|
}
|
|
}
|
|
|
|
void CLight::SetParameter(TLightID id, const D3DLIGHT8 & c_rLight)
|
|
{
|
|
m_LightID = id;
|
|
m_d3dLight = c_rLight;
|
|
}
|
|
|
|
void CLight::SetDiffuseColor(float fr, float fg, float fb, float fa)
|
|
{
|
|
if (m_d3dLight.Diffuse.r == fr
|
|
&& m_d3dLight.Diffuse.g == fg
|
|
&& m_d3dLight.Diffuse.b == fb
|
|
&& m_d3dLight.Diffuse.a == fa
|
|
)
|
|
return;
|
|
m_d3dLight.Diffuse.r = fr;
|
|
m_d3dLight.Diffuse.g = fg;
|
|
m_d3dLight.Diffuse.b = fb;
|
|
m_d3dLight.Diffuse.a = fa;
|
|
m_isEdited = TRUE;
|
|
}
|
|
|
|
void CLight::SetAmbientColor(float fr, float fg, float fb, float fa)
|
|
{
|
|
if (m_d3dLight.Ambient.r == fr
|
|
&& m_d3dLight.Ambient.g == fg
|
|
&& m_d3dLight.Ambient.b == fb
|
|
&& m_d3dLight.Ambient.a == fa
|
|
)
|
|
return;
|
|
m_d3dLight.Ambient.r = fr;
|
|
m_d3dLight.Ambient.g = fg;
|
|
m_d3dLight.Ambient.b = fb;
|
|
m_d3dLight.Ambient.a = fa;
|
|
m_isEdited = TRUE;
|
|
}
|
|
|
|
void CLight::SetRange(float fRange)
|
|
{
|
|
if (m_d3dLight.Range == fRange)
|
|
return;
|
|
|
|
m_d3dLight.Range = fRange;
|
|
m_isEdited = TRUE;
|
|
}
|
|
|
|
const D3DVECTOR & CLight::GetPosition() const
|
|
{
|
|
return m_d3dLight.Position;
|
|
}
|
|
|
|
void CLight::SetPosition(float fx, float fy, float fz)
|
|
{
|
|
if (m_d3dLight.Position.x == fx && m_d3dLight.Position.y == fy && m_d3dLight.Position.z == fz)
|
|
return;
|
|
|
|
m_d3dLight.Position.x = fx;
|
|
m_d3dLight.Position.y = fy;
|
|
m_d3dLight.Position.z = fz;
|
|
m_isEdited = TRUE;
|
|
}
|
|
|
|
void CLight::SetDistance(float fDistance)
|
|
{
|
|
m_fDistance = fDistance;
|
|
}
|
|
|
|
void CLight::BlendDiffuseColor(const D3DXCOLOR & c_rColor, float fBlendTime, float fDelayTime)
|
|
{
|
|
D3DXCOLOR Color(m_d3dLight.Diffuse);
|
|
m_DiffuseColorTransitor.SetTransition(Color, c_rColor, ms_fCurTime + fDelayTime, fBlendTime);
|
|
}
|
|
|
|
void CLight::BlendAmbientColor(const D3DXCOLOR & c_rColor, float fBlendTime, float fDelayTime)
|
|
{
|
|
D3DXCOLOR Color(m_d3dLight.Ambient);
|
|
m_AmbientColorTransitor.SetTransition(Color, c_rColor, ms_fCurTime + fDelayTime, fBlendTime);
|
|
}
|
|
|
|
void CLight::BlendRange(float fRange, float fBlendTime, float fDelayTime)
|
|
{
|
|
m_RangeTransitor.SetTransition(m_d3dLight.Range, fRange, ms_fCurTime + fDelayTime, fBlendTime);
|
|
}
|
|
|
|
void CLight::Update()
|
|
{
|
|
if (m_AmbientColorTransitor.isActiveTime(ms_fCurTime))
|
|
{
|
|
if (!m_AmbientColorTransitor.isActive())
|
|
{
|
|
m_AmbientColorTransitor.SetActive();
|
|
m_AmbientColorTransitor.SetSourceValue(m_d3dLight.Ambient);
|
|
}
|
|
else
|
|
{
|
|
D3DXCOLOR Color;
|
|
|
|
m_AmbientColorTransitor.GetValue(ms_fCurTime, &Color);
|
|
SetAmbientColor(Color.r, Color.g, Color.b, Color.a);
|
|
}
|
|
}
|
|
|
|
if (m_DiffuseColorTransitor.isActiveTime(ms_fCurTime))
|
|
{
|
|
if (!m_DiffuseColorTransitor.isActive())
|
|
{
|
|
m_DiffuseColorTransitor.SetActive();
|
|
m_DiffuseColorTransitor.SetSourceValue(m_d3dLight.Diffuse);
|
|
}
|
|
else
|
|
{
|
|
D3DXCOLOR Color;
|
|
m_DiffuseColorTransitor.GetValue(ms_fCurTime, &Color);
|
|
SetDiffuseColor(Color.r, Color.g, Color.b, Color.a);
|
|
}
|
|
}
|
|
|
|
if (m_RangeTransitor.isActiveTime(ms_fCurTime))
|
|
{
|
|
if (!m_RangeTransitor.isActive())
|
|
{
|
|
m_RangeTransitor.SetActive();
|
|
m_RangeTransitor.SetSourceValue(m_d3dLight.Range);
|
|
}
|
|
else
|
|
{
|
|
float fRange;
|
|
m_RangeTransitor.GetValue(ms_fCurTime, &fRange);
|
|
SetRange(fRange);
|
|
}
|
|
}
|
|
}
|