161 lines
3.6 KiB
C++
161 lines
3.6 KiB
C++
// Copyright (C) 2015 Jérôme Leclercq
|
|
// This file is part of the "Nazara Engine - Graphics module"
|
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
|
|
#include <Nazara/Graphics/LightManager.hpp>
|
|
#include <Nazara/Graphics/Light.hpp>
|
|
#include <Nazara/Graphics/Debug.hpp>
|
|
|
|
NzLightManager::NzLightManager() :
|
|
m_lightCount(0)
|
|
{
|
|
}
|
|
|
|
NzLightManager::NzLightManager(const NzLight** lights, unsigned int lightCount)
|
|
{
|
|
SetLights(lights, lightCount);
|
|
}
|
|
|
|
void NzLightManager::AddLights(const NzLight** lights, unsigned int lightCount)
|
|
{
|
|
m_lights.push_back(std::make_pair(lights, lightCount));
|
|
m_lightCount += lightCount;
|
|
}
|
|
|
|
void NzLightManager::Clear()
|
|
{
|
|
m_lights.clear();
|
|
m_lightCount = 0;
|
|
}
|
|
|
|
unsigned int NzLightManager::ComputeClosestLights(const NzVector3f& position, float squaredRadius, unsigned int maxResults)
|
|
{
|
|
m_results.resize(maxResults);
|
|
for (Light& light : m_results)
|
|
{
|
|
light.light = nullptr;
|
|
light.score = std::numeric_limits<unsigned int>::max(); // Nous jouons au Golf
|
|
}
|
|
|
|
for (auto it = m_lights.begin(); it != m_lights.end(); ++it)
|
|
{
|
|
const NzLight** lights = it->first;
|
|
unsigned int lightCount = it->second;
|
|
|
|
for (unsigned int j = 0; j < lightCount; ++j)
|
|
{
|
|
const NzLight* light = *lights++;
|
|
|
|
unsigned int score = std::numeric_limits<unsigned int>::max();
|
|
switch (light->GetLightType())
|
|
{
|
|
case nzLightType_Directional:
|
|
score = 0; // Lumière choisie d'office
|
|
break;
|
|
|
|
case nzLightType_Point:
|
|
{
|
|
float lightRadius = light->GetRadius();
|
|
|
|
float squaredDistance = position.SquaredDistance(light->GetPosition());
|
|
if (squaredDistance - squaredRadius <= lightRadius*lightRadius)
|
|
score = static_cast<unsigned int>(squaredDistance*1000.f);
|
|
|
|
break;
|
|
}
|
|
|
|
case nzLightType_Spot:
|
|
{
|
|
float lightRadius = light->GetRadius();
|
|
|
|
///TODO: Attribuer bonus/malus selon l'angle du spot ?
|
|
float squaredDistance = position.SquaredDistance(light->GetPosition());
|
|
if (squaredDistance - squaredRadius <= lightRadius*lightRadius)
|
|
score = static_cast<unsigned int>(squaredDistance*1000.f);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (score < m_results[0].score)
|
|
{
|
|
unsigned int k;
|
|
for (k = 1; k < maxResults; ++k)
|
|
{
|
|
if (score > m_results[k].score)
|
|
break;
|
|
}
|
|
|
|
k--; // Position de la nouvelle lumière
|
|
|
|
// Décalage
|
|
std::memcpy(&m_results[0], &m_results[1], k*sizeof(Light));
|
|
|
|
m_results[k].light = light;
|
|
m_results[k].score = score;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int i;
|
|
for (i = 0; i < maxResults; ++i)
|
|
{
|
|
if (m_results[i].light)
|
|
break;
|
|
}
|
|
|
|
return maxResults-i;
|
|
}
|
|
|
|
const NzLight* NzLightManager::GetLight(unsigned int index) const
|
|
{
|
|
#if NAZARA_GRAPHICS_SAFE
|
|
if (index >= m_lightCount)
|
|
{
|
|
NazaraError("Light index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_lightCount) + ')');
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
for (unsigned int i = 0; i < m_lights.size(); ++i)
|
|
{
|
|
unsigned int lightCount = m_lights[i].second;
|
|
if (index > lightCount)
|
|
index -= lightCount;
|
|
else
|
|
{
|
|
const NzLight** lights = m_lights[i].first;
|
|
return lights[i];
|
|
}
|
|
}
|
|
|
|
#if NAZARA_GRAPHICS_SAFE
|
|
NazaraInternalError("Light not found");
|
|
#else
|
|
NazaraError("Light not found");
|
|
#endif
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
unsigned int NzLightManager::GetLightCount() const
|
|
{
|
|
return m_lightCount;
|
|
}
|
|
|
|
const NzLight* NzLightManager::GetResult(unsigned int i) const
|
|
{
|
|
return m_results[m_results.size()-i-1].light;
|
|
}
|
|
|
|
bool NzLightManager::IsEmpty() const
|
|
{
|
|
return m_lightCount == 0;
|
|
}
|
|
|
|
void NzLightManager::SetLights(const NzLight** lights, unsigned int lightCount)
|
|
{
|
|
Clear();
|
|
AddLights(lights, lightCount);
|
|
}
|