// 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 #include #include 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::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::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(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(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); }