Source

gltut / Tut 12 Dynamic Range / Lights.cpp

Full commit

#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <math.h>
#include "Lights.h"
#include <glm/glm.hpp>

static float g_fLightHeight = 10.5f;
static float g_fLightRadius = 70.0f;

glm::vec4 CalcLightPosition(const Framework::Timer &timer, float alphaOffset)
{
	const float fLoopDuration = 5.0f;
	const float fScale = 3.14159f * 2.0f;

	float timeThroughLoop = timer.GetAlpha() + alphaOffset;

	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);

	ret.x = cosf(timeThroughLoop * fScale) * g_fLightRadius;
	ret.z = sinf(timeThroughLoop * fScale) * g_fLightRadius;

	return ret;
}

const float g_fLightAttenuation = 1.0f / (15.0f * 15.0f);

float distance(const glm::vec3 &lhs, const glm::vec3 &rhs)
{
	return glm::length(rhs - lhs);
}

LightManager::LightManager()
	: m_keyLightTimer(Framework::Timer::TT_LOOP, 5.0f)
	, m_ambientInterpolator(true)
{
	std::vector<glm::vec4> ambientValues;
	ambientValues.reserve(4);
	
	ambientValues.push_back(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f));

	m_ambientInterpolator.SetValues(ambientValues);

	m_lightTimers.reserve(NUMBER_OF_LIGHTS - 1);
	m_lightPos.reserve(NUMBER_OF_LIGHTS - 1);
	m_lightPos.push_back(LightInterpolator(true));
	m_lightPos.push_back(LightInterpolator(true));
	m_lightPos.push_back(LightInterpolator(true));

	std::vector<glm::vec3> posValues;
	posValues.reserve(20);

	posValues.push_back(glm::vec3(-50.0f, 30.0f, 70.0f));
	posValues.push_back(glm::vec3(-70.0f, 30.0f, 50.0f));
	posValues.push_back(glm::vec3(-70.0f, 30.0f, -50.0f));
	posValues.push_back(glm::vec3(-50.0f, 30.0f, -70.0f));
	posValues.push_back(glm::vec3(50.0f, 30.0f, -70.0f));
	posValues.push_back(glm::vec3(70.0f, 30.0f, -50.0f));
	posValues.push_back(glm::vec3(70.0f, 30.0f, 50.0f));
	posValues.push_back(glm::vec3(50.0f, 30.0f, 70.0f));
	m_lightPos[0].SetValues(posValues);
	m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f));

	posValues.clear();
	posValues.push_back(glm::vec3(80.0f, 30.0f, -70.0f));
	posValues.push_back(glm::vec3(70.0f, 25.0f, 70.0f));
	m_lightPos[1].SetValues(posValues);
	m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f));

	posValues.clear();
	posValues.push_back(glm::vec3(-70.0f, 25.0f, -75.0f));
	posValues.push_back(glm::vec3(-70.0f, 5.0f, 0.0f));
	posValues.push_back(glm::vec3(-70.0f, 25.0f, 70.0f));
	posValues.push_back(glm::vec3(0.0f, 50.0f, 0.0f));
	m_lightPos[2].SetValues(posValues);
	m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f));
}

struct UpdateTimer
{
	void operator()(Framework::Timer &timer) {timer.Update();}
	void operator()(std::pair<const std::string, Framework::Timer> &timeData)
	{timeData.second.Update();}
};

struct PauseTimer
{
	void operator()(Framework::Timer &timer) {timer.TogglePause();}
	void operator()(std::pair<const std::string, Framework::Timer> &timeData)
	{timeData.second.TogglePause();}
};

struct RewindTimer
{
	RewindTimer(float _secRewind) : secRewind(_secRewind) {}

	void operator()(Framework::Timer &timer) {timer.Rewind(secRewind);}
	void operator()(std::pair<const std::string, Framework::Timer> &timeData)
	{timeData.second.Rewind(secRewind);}

	float secRewind;
};

void LightManager::UpdateTime()
{
	m_keyLightTimer.Update();
	std::for_each(m_lightTimers.begin(), m_lightTimers.end(), UpdateTimer());
	std::for_each(m_extraTimers.begin(), m_extraTimers.end(), UpdateTimer());
}

bool LightManager::TogglePause()
{
	std::for_each(m_lightTimers.begin(), m_lightTimers.end(), PauseTimer());
	std::for_each(m_extraTimers.begin(), m_extraTimers.end(), PauseTimer());

	return m_keyLightTimer.TogglePause();
}

void LightManager::RewindTime( float secRewind )
{
	m_keyLightTimer.Rewind(secRewind);
	std::for_each(m_lightTimers.begin(), m_lightTimers.end(), RewindTimer(secRewind));
	std::for_each(m_extraTimers.begin(), m_extraTimers.end(), RewindTimer(secRewind));
}

LightBlock LightManager::GetLightPositions( const glm::mat4 &worldToCameraMat ) const
{
	LightBlock lightData;

	lightData.ambientIntensity = m_ambientInterpolator.Interpolate(m_keyLightTimer.GetAlpha());
	lightData.lightAttenuation = g_fLightAttenuation;

	lightData.lights[0].cameraSpaceLightPos =
		worldToCameraMat * glm::vec4(0.0f, 0.981f, 0.196f, 0.0f);

	lightData.lights[0].lightIntensity = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f);

	for(int light = 1; light < NUMBER_OF_LIGHTS; light++)
	{
		int lightIx = light - 1;
		glm::vec4 worldLightPos = glm::vec4(m_lightPos[lightIx].Interpolate(m_lightTimers[lightIx].GetAlpha()), 1.0f);
		glm::vec4 lightPosCameraSpace = worldToCameraMat * worldLightPos;

		lightData.lights[light].cameraSpaceLightPos = lightPosCameraSpace;
		lightData.lights[light].lightIntensity = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
	}

	return lightData;
}

int LightManager::GetNumberOfPointLights() const
{
	return m_lightPos.size();
}

glm::vec3 LightManager::GetWorldLightPosition( int lightIx ) const
{
	return m_lightPos[lightIx].Interpolate(m_lightTimers[lightIx].GetAlpha());
}

void LightManager::CreateTimer( const std::string &timerName,
							   Framework::Timer::Type eType, float fDuration )
{
	m_extraTimers[timerName] = Framework::Timer(eType, fDuration);
}

float LightManager::GetTimerValue( const std::string &timerName ) const
{
	ExtraTimerMap::const_iterator loc = m_extraTimers.find(timerName);

	if(loc == m_extraTimers.end())
		return -1.0f;

	return loc->second.GetAlpha();
}