<commit_before>/*
The MIT License (MIT)

Copyright (c) 2015 Dennis Wandschura

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "Engine.h"
#include <vxEngineLib/Timer.h>
#include <vxEngineLib/EngineConfig.h>
#include <vxEngineLib/Locator.h>
#include "developer.h"
#include "EngineGlobals.h"
#include "CpuProfiler.h"
#include <vxEngineLib/MessageTypes.h>
#include <vxEngineLib/debugPrint.h>
#include <vxResourceAspect/FileEntry.h>
#include <vxEngineLib/Logfile.h>

Engine* g_pEngine{ nullptr };

namespace EngineCpp
{
	void callbackKeyPressed(u16 key)
	{
		g_pEngine->keyPressed(key);
	}

	void callbackKeyReleased(u16 key)
	{
		g_pEngine->keyReleased(key);
	}

	void schedulerThread(vx::TaskManager* scheduler)
	{
		std::atomic_uint running;
		running.store(1);

		scheduler->initializeThread(&running);

		while (running.load() != 0)
		{
			scheduler->swapBuffer();

			scheduler->update();
		}
	}
}

Engine::Engine()
	:m_msgManager(),
	m_actionManager(),
	m_taskManager(),
	m_systemAspect(),
	m_physicsAspect(),
	m_actorAspect(),
	m_renderAspect(nullptr),
	m_entityAspect(),
	m_bRun(0),
	m_resourceAspect(),
#if _VX_MEM_PROFILE
	m_allocManager(),
#endif
	m_allocator(),
	m_shutdown(0),
	m_scene(),
	m_renderAspectDll(nullptr),
	m_audioAspectDll(nullptr),
	m_destroyFn(nullptr)
{
	g_pEngine = this;
}

Engine::~Engine()
{
	if (m_shutdown == 0)
	{
		// something bad happened
		assert(false);
	}
}

void Engine::update()
{
	//printf("physx simulate\n");
	m_physicsAspect.update(g_dt);

	// process events
	m_msgManager.update();

	m_actionManager.update();

	m_resourceAspect.update();

	//printf("task manager begin\n");
	//m_taskManager.update();
	//m_taskManager.wait();
	//printf("task manager end\n");

	// update aspects in order
	//printf("physx fetch\n");
	m_physicsAspect.fetch();

	m_systemAspect.update(g_dt);

	m_entityAspect.update(g_dt, &m_actionManager);

	//CpuProfiler::popMarker();

	//CpuProfiler::pushMarker("physx");
	//CpuProfiler::popMarker();
}

void Engine::mainLoop(Logfile* logfile)
{
	auto frequency = Timer::getFrequency();
	const f64 invFrequency = 1.0 / frequency;

	LARGE_INTEGER last;
	QueryPerformanceCounter(&last);

	m_renderAspect->initializeProfiler(logfile);

	f32 accum = 0.0f;
	while (m_bRun != 0)
	{
		LARGE_INTEGER current;
		QueryPerformanceCounter(&current);

		auto frameTicks = (current.QuadPart - last.QuadPart) * 1000;
		f32 frameTime = static_cast<f32>(frameTicks * invFrequency) * 0.001f;
		frameTime = fminf(frameTime, g_dt);

		accum += frameTime;

		m_renderAspect->update();
		m_renderAspect->submitCommands();

		while (accum >= g_dt)
		{
			update();

			m_renderAspect->updateProfiler(g_dt);

			accum -= g_dt;
		}

		m_renderAspect->endFrame();

		last = current;
	}
}

bool Engine::initializeImpl(const std::string &dataDir)
{
	m_memory = Memory(200 MBYTE, 64);

	m_allocator = vx::StackAllocator(m_memory.get(), static_cast<u32>(m_memory.size()));

#if _VX_MEM_PROFILE
	m_allocManager.registerAllocator(&m_allocator, "mainAllocator");
#endif

	m_msgManager.initialize(&m_allocator, 255);
	Locator::provide(&m_msgManager);

	bool flipTextures = (g_engineConfig.m_rendererSettings.m_renderMode == Graphics::RendererSettings::Mode_GL);
	if (!m_resourceAspect.initialize(&m_allocator, dataDir, nullptr, &m_taskManager, &m_msgManager, flipTextures, false))
		return false;

	return true;
}

bool Engine::createRenderAspectGL(const RenderAspectDescription &desc)
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectGL_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectGL.dll");
#endif

	if (handle == nullptr)
		return false;

	auto proc = (CreateRenderAspectFunction)GetProcAddress(handle, "createRenderAspect");
	auto procDestroy = (DestroyRenderAspectFunction)GetProcAddress(handle, "destroyRenderAspect");
	if (proc == nullptr || procDestroy == nullptr)
		return false;

	RenderAspectInitializeError error;
	auto renderAspect = proc(desc, &error);
	if (renderAspect == nullptr)
		return false;

	m_renderAspect = renderAspect;
	m_renderAspectDll = handle;
	m_destroyFn = procDestroy;

	return true;
}

bool Engine::createRenderAspectDX12(const RenderAspectDescription &desc)
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectDX12_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectDX12.dll");
#endif
	if (handle == nullptr)
		return false;

	auto proc = (CreateRenderAspectFunction)GetProcAddress(handle, "createRenderAspect");
	auto procDestroy = (DestroyRenderAspectFunction)GetProcAddress(handle, "destroyRenderAspect");
	if (proc == nullptr || procDestroy == nullptr)
		return false;

	auto renderAspect = proc(desc, nullptr);
	if (renderAspect == nullptr)
		return false;

	m_renderAspect = renderAspect;
	m_renderAspectDll = handle;
	m_destroyFn = procDestroy;

	return true;
}

bool Engine::createAudioAspect()
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxAudioAspect_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxAudioAspect.dll");
#endif
	if (handle == nullptr)
		return false;

	auto proc = (CreateAudioAspectFunctionType)GetProcAddress(handle, "createAudioAspect");
	if (proc == nullptr)
		return false;

	auto audioAspect = proc();
	if (audioAspect == nullptr)
		return false;

	m_audioAspect = audioAspect;
	m_audioAspectDll = handle;

	if (!m_audioAspect->initialize())
		return false;

	return true;
}

bool Engine::initialize(Logfile* logfile)
{
	const std::string dataDir("../data/");

#if _VX_MEM_PROFILE
	vx::Allocator::setProfiler(&m_allocManager);
#endif

	if (!g_engineConfig.loadFromFile("settings.txt"))
	{
		logfile->append("could not load 'settings.txt'\n");
		//printf("could not load 'settings.txt'\n");
		return false;
	}

	g_engineConfig.m_editor = false;

	if (!initializeImpl(dataDir))
		return false;

	m_taskManager.initialize(2, 10, 30.0f, &m_allocator);

#if _VX_MEM_PROFILE
	//m_taskManager.initialize(1, &m_allocator, 1024, &m_allocManager);
#else
	//m_taskManager.initialize(1, &m_allocator, 1024, nullptr);
#endif

	if (!m_systemAspect.initialize(g_engineConfig, EngineCpp::callbackKeyPressed, EngineCpp::callbackKeyReleased, nullptr))
		return false;

	RenderAspectDescription renderAspectDesc =
	{
		dataDir,
		(void*)&m_systemAspect.getWindow(),
		nullptr,
		&m_allocator,
		&g_engineConfig,
		logfile,
		&m_resourceAspect,
		&m_msgManager,
		&m_taskManager
	};

	auto renderMode = g_engineConfig.m_rendererSettings.m_renderMode;
	if (renderMode == Graphics::RendererSettings::Mode_GL)
	{
		if (!createRenderAspectGL(renderAspectDesc))
		{
			logfile->append("error opengl renderer\n");
			return false;
		}
	}
	else if (renderMode == Graphics::RendererSettings::Mode_DX12)
	{
		if (!createRenderAspectDX12(renderAspectDesc))
		{
			logfile->append("error dx12 renderer\n");
			return false;
		}
	}

	//m_renderAspect->makeCurrent(false);

	if (!m_physicsAspect.initialize(&m_taskManager))
		return false;

#if _VX_MEM_PROFILE
	if (!m_entityAspect.initialize(&m_allocator, &m_taskManager, &m_allocManager))
		return false;
#else
	if (!m_entityAspect.initialize(&m_allocator, &m_taskManager, nullptr))
		return false;
#endif

	if (!createAudioAspect())
		return false;

#if _VX_MEM_PROFILE
	m_actorAspect.initialize(&m_allocator, &m_allocManager);
#else
	m_actorAspect.initialize(&m_allocator, nullptr);
#endif

	Locator::provide(&m_physicsAspect);
	Locator::provide(m_renderAspect);
	Locator::provide(&m_resourceAspect);

	// register aspects that receive events
	m_msgManager.registerListener(m_renderAspect, 3, (u8)vx::MessageType::File_Event);
	m_msgManager.registerListener(&m_physicsAspect, 2, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event);
	m_msgManager.registerListener(&m_entityAspect, 1, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event);
	m_msgManager.registerListener(&m_actorAspect, 2, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event | (u8)vx::MessageType::AI_Event);

	m_bRun = 1;
	m_shutdown = 0;

	m_taskManagerThread = std::thread(EngineCpp::schedulerThread, &m_taskManager);

	//printf("Main Thread tid: %u\n", std::this_thread::get_id());

	return true;
}

void Engine::shutdown()
{
	m_scene.reset();

	if (m_audioAspect)
	{
		m_audioAspect->shutdown();
		delete m_audioAspect;
	}
	m_entityAspect.shutdown();
	m_physicsAspect.shutdown();

	if (m_renderAspect)
	{
		m_renderAspect->shutdown(m_systemAspect.getWindow().getHwnd());
		m_destroyFn(m_renderAspect);
		m_renderAspect = nullptr;
		m_destroyFn = nullptr;
	}

	m_systemAspect.shutdown();
	m_resourceAspect.shutdown();
	m_shutdown = 1;

	Locator::reset();

	m_taskManager.stop();
	if (m_taskManagerThread.joinable())
		m_taskManagerThread.join();

	m_taskManager.shutdown();

	//CpuProfiler::shutdown();

	m_allocator.clear();
	m_allocator.release();

#if _VX_MEM_PROFILE
	m_allocManager.print();
#endif

	if (m_audioAspectDll != nullptr)
	{
		FreeLibrary(m_audioAspectDll);
		m_audioAspectDll = nullptr;
	}

	if (m_renderAspectDll != nullptr)
	{
		FreeLibrary(m_renderAspectDll);
		m_renderAspectDll = nullptr;
	}

	m_memory.clear();
}

void Engine::start(Logfile* logfile)
{
	//RenderAspectThreadDesc desc{ &m_systemAspect.getWindow(), &g_engineConfig};
	//m_renderThread = vx::thread(&Engine::renderLoop, this, desc);

	std::string level;
	g_engineConfig.m_root.get("level")->as(&level);

	vx::Variant arg;
	arg.ptr = &m_scene;
	requestLoadFile(vx::FileEntry(level.c_str(), vx::FileType::Scene), arg);

	mainLoop(logfile);
}

void Engine::stop()
{
	m_bRun = 0;
}

void Engine::requestLoadFile(const vx::FileEntry &fileEntry, vx::Variant arg)
{
	m_resourceAspect.requestLoadFile(fileEntry, arg);
}

void Engine::keyPressed(u16 key)
{
	if (key == vx::Keyboard::Key_E)
	{
		m_entityAspect.onPressedActionKey();
	}
	else if (key == vx::Keyboard::Key_Escape)
	{
		stop();
	}
}

void Engine::keyReleased(u16 key)
{
	if (key == vx::Keyboard::Key_E)
	{
		m_entityAspect.onReleasedActionKey();
	}
}<commit_msg>removed gl renderer<commit_after>/*
The MIT License (MIT)

Copyright (c) 2015 Dennis Wandschura

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "Engine.h"
#include <vxEngineLib/Timer.h>
#include <vxEngineLib/EngineConfig.h>
#include <vxEngineLib/Locator.h>
#include "developer.h"
#include "EngineGlobals.h"
#include "CpuProfiler.h"
#include <vxEngineLib/MessageTypes.h>
#include <vxEngineLib/debugPrint.h>
#include <vxResourceAspect/FileEntry.h>
#include <vxEngineLib/Logfile.h>

Engine* g_pEngine{ nullptr };

namespace EngineCpp
{
	void callbackKeyPressed(u16 key)
	{
		g_pEngine->keyPressed(key);
	}

	void callbackKeyReleased(u16 key)
	{
		g_pEngine->keyReleased(key);
	}

	void schedulerThread(vx::TaskManager* scheduler)
	{
		std::atomic_uint running;
		running.store(1);

		scheduler->initializeThread(&running);

		while (running.load() != 0)
		{
			scheduler->swapBuffer();

			scheduler->update();
		}
	}
}

Engine::Engine()
	:m_msgManager(),
	m_actionManager(),
	m_taskManager(),
	m_systemAspect(),
	m_physicsAspect(),
	m_actorAspect(),
	m_renderAspect(nullptr),
	m_entityAspect(),
	m_bRun(0),
	m_resourceAspect(),
#if _VX_MEM_PROFILE
	m_allocManager(),
#endif
	m_allocator(),
	m_shutdown(0),
	m_scene(),
	m_renderAspectDll(nullptr),
	m_audioAspectDll(nullptr),
	m_destroyFn(nullptr)
{
	g_pEngine = this;
}

Engine::~Engine()
{
	if (m_shutdown == 0)
	{
		// something bad happened
		assert(false);
	}
}

void Engine::update()
{
	//printf("physx simulate\n");
	m_physicsAspect.update(g_dt);

	// process events
	m_msgManager.update();

	m_actionManager.update();

	m_resourceAspect.update();

	//printf("task manager begin\n");
	//m_taskManager.update();
	//m_taskManager.wait();
	//printf("task manager end\n");

	// update aspects in order
	//printf("physx fetch\n");
	m_physicsAspect.fetch();

	m_systemAspect.update(g_dt);

	m_entityAspect.update(g_dt, &m_actionManager);

	//CpuProfiler::popMarker();

	//CpuProfiler::pushMarker("physx");
	//CpuProfiler::popMarker();
}

void Engine::mainLoop(Logfile* logfile)
{
	auto frequency = Timer::getFrequency();
	const f64 invFrequency = 1.0 / frequency;

	LARGE_INTEGER last;
	QueryPerformanceCounter(&last);

	m_renderAspect->initializeProfiler(logfile);

	f32 accum = 0.0f;
	while (m_bRun != 0)
	{
		LARGE_INTEGER current;
		QueryPerformanceCounter(&current);

		auto frameTicks = (current.QuadPart - last.QuadPart) * 1000;
		f32 frameTime = static_cast<f32>(frameTicks * invFrequency) * 0.001f;
		frameTime = fminf(frameTime, g_dt);

		accum += frameTime;

		m_renderAspect->update();
		m_renderAspect->submitCommands();

		while (accum >= g_dt)
		{
			update();

			m_renderAspect->updateProfiler(g_dt);

			accum -= g_dt;
		}

		m_renderAspect->endFrame();

		last = current;
	}
}

bool Engine::initializeImpl(const std::string &dataDir)
{
	m_memory = Memory(200 MBYTE, 64);

	m_allocator = vx::StackAllocator(m_memory.get(), static_cast<u32>(m_memory.size()));

#if _VX_MEM_PROFILE
	m_allocManager.registerAllocator(&m_allocator, "mainAllocator");
#endif

	m_msgManager.initialize(&m_allocator, 255);
	Locator::provide(&m_msgManager);

	bool flipTextures = (g_engineConfig.m_rendererSettings.m_renderMode == Graphics::RendererSettings::Mode_GL);
	if (!m_resourceAspect.initialize(&m_allocator, dataDir, nullptr, &m_taskManager, &m_msgManager, flipTextures, false))
		return false;

	return true;
}

bool Engine::createRenderAspectGL(const RenderAspectDescription &desc)
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectGL_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectGL.dll");
#endif

	if (handle == nullptr)
		return false;

	auto proc = (CreateRenderAspectFunction)GetProcAddress(handle, "createRenderAspect");
	auto procDestroy = (DestroyRenderAspectFunction)GetProcAddress(handle, "destroyRenderAspect");
	if (proc == nullptr || procDestroy == nullptr)
		return false;

	RenderAspectInitializeError error;
	auto renderAspect = proc(desc, &error);
	if (renderAspect == nullptr)
		return false;

	m_renderAspect = renderAspect;
	m_renderAspectDll = handle;
	m_destroyFn = procDestroy;

	return true;
}

bool Engine::createRenderAspectDX12(const RenderAspectDescription &desc)
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectDX12_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxRenderAspectDX12.dll");
#endif
	if (handle == nullptr)
		return false;

	auto proc = (CreateRenderAspectFunction)GetProcAddress(handle, "createRenderAspect");
	auto procDestroy = (DestroyRenderAspectFunction)GetProcAddress(handle, "destroyRenderAspect");
	if (proc == nullptr || procDestroy == nullptr)
		return false;

	auto renderAspect = proc(desc, nullptr);
	if (renderAspect == nullptr)
		return false;

	m_renderAspect = renderAspect;
	m_renderAspectDll = handle;
	m_destroyFn = procDestroy;

	return true;
}

bool Engine::createAudioAspect()
{
#if _DEBUG
	auto handle = LoadLibrary(L"../../lib/vxAudioAspect_d.dll");
#else
	auto handle = LoadLibrary(L"../../lib/vxAudioAspect.dll");
#endif
	if (handle == nullptr)
		return false;

	auto proc = (CreateAudioAspectFunctionType)GetProcAddress(handle, "createAudioAspect");
	if (proc == nullptr)
		return false;

	auto audioAspect = proc();
	if (audioAspect == nullptr)
		return false;

	m_audioAspect = audioAspect;
	m_audioAspectDll = handle;

	if (!m_audioAspect->initialize())
		return false;

	return true;
}

bool Engine::initialize(Logfile* logfile)
{
	const std::string dataDir("../data/");

#if _VX_MEM_PROFILE
	vx::Allocator::setProfiler(&m_allocManager);
#endif

	if (!g_engineConfig.loadFromFile("settings.txt"))
	{
		logfile->append("could not load 'settings.txt'\n");
		//printf("could not load 'settings.txt'\n");
		return false;
	}

	g_engineConfig.m_editor = false;

	if (!initializeImpl(dataDir))
		return false;

	m_taskManager.initialize(2, 10, 30.0f, &m_allocator);

#if _VX_MEM_PROFILE
	//m_taskManager.initialize(1, &m_allocator, 1024, &m_allocManager);
#else
	//m_taskManager.initialize(1, &m_allocator, 1024, nullptr);
#endif

	if (!m_systemAspect.initialize(g_engineConfig, EngineCpp::callbackKeyPressed, EngineCpp::callbackKeyReleased, nullptr))
		return false;

	RenderAspectDescription renderAspectDesc =
	{
		dataDir,
		(void*)&m_systemAspect.getWindow(),
		nullptr,
		&m_allocator,
		&g_engineConfig,
		logfile,
		&m_resourceAspect,
		&m_msgManager,
		&m_taskManager
	};

	if (!createRenderAspectDX12(renderAspectDesc))
	{
		logfile->append("error dx12 renderer\n");
		return false;
	}
	/*auto renderMode = g_engineConfig.m_rendererSettings.m_renderMode;
	if (renderMode == Graphics::RendererSettings::Mode_GL)
	{
		if (!createRenderAspectGL(renderAspectDesc))
		{
			logfile->append("error opengl renderer\n");
			return false;
		}
	}
	else if (renderMode == Graphics::RendererSettings::Mode_DX12)
	{
		if (!createRenderAspectDX12(renderAspectDesc))
		{
			logfile->append("error dx12 renderer\n");
			return false;
		}
	}*/

	if (!m_physicsAspect.initialize(&m_taskManager))
		return false;

#if _VX_MEM_PROFILE
	if (!m_entityAspect.initialize(&m_allocator, &m_taskManager, &m_allocManager))
		return false;
#else
	if (!m_entityAspect.initialize(&m_allocator, &m_taskManager, nullptr))
		return false;
#endif

	if (!createAudioAspect())
		return false;

#if _VX_MEM_PROFILE
	m_actorAspect.initialize(&m_allocator, &m_allocManager);
#else
	m_actorAspect.initialize(&m_allocator, nullptr);
#endif

	Locator::provide(&m_physicsAspect);
	Locator::provide(m_renderAspect);
	Locator::provide(&m_resourceAspect);

	// register aspects that receive events
	m_msgManager.registerListener(m_renderAspect, 3, (u8)vx::MessageType::File_Event);
	m_msgManager.registerListener(&m_physicsAspect, 2, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event);
	m_msgManager.registerListener(&m_entityAspect, 1, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event);
	m_msgManager.registerListener(&m_actorAspect, 2, (u8)vx::MessageType::File_Event | (u8)vx::MessageType::Ingame_Event | (u8)vx::MessageType::AI_Event);

	m_bRun = 1;
	m_shutdown = 0;

	m_taskManagerThread = std::thread(EngineCpp::schedulerThread, &m_taskManager);

	//printf("Main Thread tid: %u\n", std::this_thread::get_id());

	return true;
}

void Engine::shutdown()
{
	m_scene.reset();

	if (m_audioAspect)
	{
		m_audioAspect->shutdown();
		delete m_audioAspect;
	}
	m_entityAspect.shutdown();
	m_physicsAspect.shutdown();

	if (m_renderAspect)
	{
		m_renderAspect->shutdown(m_systemAspect.getWindow().getHwnd());
		m_destroyFn(m_renderAspect);
		m_renderAspect = nullptr;
		m_destroyFn = nullptr;
	}

	m_systemAspect.shutdown();
	m_resourceAspect.shutdown();
	m_shutdown = 1;

	Locator::reset();

	m_taskManager.stop();
	if (m_taskManagerThread.joinable())
		m_taskManagerThread.join();

	m_taskManager.shutdown();

	//CpuProfiler::shutdown();

	m_allocator.clear();
	m_allocator.release();

#if _VX_MEM_PROFILE
	m_allocManager.print();
#endif

	if (m_audioAspectDll != nullptr)
	{
		FreeLibrary(m_audioAspectDll);
		m_audioAspectDll = nullptr;
	}

	if (m_renderAspectDll != nullptr)
	{
		FreeLibrary(m_renderAspectDll);
		m_renderAspectDll = nullptr;
	}

	m_memory.clear();
}

void Engine::start(Logfile* logfile)
{
	//RenderAspectThreadDesc desc{ &m_systemAspect.getWindow(), &g_engineConfig};
	//m_renderThread = vx::thread(&Engine::renderLoop, this, desc);

	std::string level;
	g_engineConfig.m_root.get("level")->as(&level);

	vx::Variant arg;
	arg.ptr = &m_scene;
	requestLoadFile(vx::FileEntry(level.c_str(), vx::FileType::Scene), arg);

	mainLoop(logfile);
}

void Engine::stop()
{
	m_bRun = 0;
}

void Engine::requestLoadFile(const vx::FileEntry &fileEntry, vx::Variant arg)
{
	m_resourceAspect.requestLoadFile(fileEntry, arg);
}

void Engine::keyPressed(u16 key)
{
	if (key == vx::Keyboard::Key_E)
	{
		m_entityAspect.onPressedActionKey();
	}
	else if (key == vx::Keyboard::Key_Escape)
	{
		stop();
	}
}

void Engine::keyReleased(u16 key)
{
	if (key == vx::Keyboard::Key_E)
	{
		m_entityAspect.onReleasedActionKey();
	}
}<|endoftext|>


<commit_before>/*++

Copyright (c) 2018 Brad Weinberger

Module Name:

   cornell_box.cc

Abstract:

   Integration tests which render a single triangle.

--*/

#include <string>

#include "iris_advanced_toolkit/pcg_random.h"
#include "iris_camera_toolkit/grid_pixel_sampler.h"
#include "iris_camera_toolkit/pfm_writer.h"
#include "iris_camera_toolkit/pinhole_camera.h"
#include "iris_physx_toolkit/attenuated_reflector.h"
#include "iris_physx_toolkit/cie_color_matcher.h"
#include "iris_physx_toolkit/constant_emissive_material.h"
#include "iris_physx_toolkit/constant_material.h"
#include "iris_physx_toolkit/interpolated_spectrum.h"
#include "iris_physx_toolkit/lambertian_brdf.h"
#include "iris_physx_toolkit/list_scene.h"
#include "iris_physx_toolkit/one_light_sampler.h"
#include "iris_physx_toolkit/path_tracer.h"
#include "iris_physx_toolkit/sample_tracer.h"
#include "iris_physx_toolkit/triangle.h"
#include "googletest/include/gtest/gtest.h"
#include "test_util/cornell_box.h"
#include "test_util/pfm.h"
#include "test_util/quad.h"

void
TestRenderSingleThreaded(
    _In_ PCCAMERA camera,
    _In_ PCLIST_SCENE scene,
    _In_ PONE_LIGHT_SAMPLER light_sampler,
    _In_ const std::string& file_name
    )
{
    PPIXEL_SAMPLER pixel_sampler;
    ISTATUS status =
        GridPixelSamplerAllocate(1, 1, false, 1, 1, false, &pixel_sampler);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PRANDOM rng;
    status = PermutedCongruentialRandomAllocate(
        0x853c49e6748fea9bULL,
        0xda3e39cb94b95bdbULL,
        &rng);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PINTEGRATOR path_tracer;
    status = PathTracerAllocate(0, 0, (float_t)0.0, &path_tracer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PCOLOR_MATCHER color_matcher;
    status = CieColorMatcherAllocate(&color_matcher);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSAMPLE_TRACER sample_tracer;
    status = PhysxSampleTracerAllocate(
        path_tracer,
        ListSceneTraceCallback,
        scene,
        OneLightSamplerSampleLightsCallback,
        light_sampler,
        color_matcher,
        &sample_tracer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PFRAMEBUFFER framebuffer;
    status = FramebufferAllocate(500, 500, &framebuffer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = IrisCameraRender(
        (float_t)0.001, camera, pixel_sampler, sample_tracer, rng, framebuffer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    bool equals;
    status = ExactlyEqualsPfmFile(framebuffer,
                                  file_name.c_str(),
                                  PFM_PIXEL_FORMAT_XYZ,
                                  &equals);
    ASSERT_EQ(status, ISTATUS_SUCCESS);
    EXPECT_TRUE(equals);

    if (!equals)
    {
        status = WriteToPfmFile(framebuffer,
                                file_name.c_str(),
                                PFM_PIXEL_FORMAT_XYZ);
        ASSERT_EQ(status, ISTATUS_SUCCESS);
    }

    PixelSamplerFree(pixel_sampler);
    RandomFree(rng);
    SampleTracerFree(sample_tracer);
    FramebufferFree(framebuffer);
    ColorMatcherRelease(color_matcher);
}

static
void
AddQuadToScene(
    _In_ POINT3 v0,
    _In_ POINT3 v1,
    _In_ POINT3 v2,
    _In_ POINT3 v3,
    _In_opt_ PMATERIAL front_material,
    _In_opt_ PMATERIAL back_material,
    _Inout_ PLIST_SCENE scene
    )
{
    PSHAPE shape0, shape1;
    ISTATUS status = EmissiveQuadAllocate(
        v0,
        v1,
        v2,
        v3,
        front_material,
        back_material,
        nullptr,
        nullptr,
        &shape0,
        &shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, shape0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    ShapeRelease(shape0);
    ShapeRelease(shape1);
}

TEST(CornellBoxTest, CornellBox)
{
    PREFLECTOR white_reflector;
    ISTATUS status =
        InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                      cornell_box_white_wall_samples,
                                      CORNELL_BOX_WALL_SAMPLES,
                                      &white_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF white_brdf;
    status = LambertianBrdfAllocate(white_reflector, &white_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL white_material;
    status = ConstantMaterialAllocate(white_brdf, &white_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PREFLECTOR red_reflector;
    status = InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                           cornell_box_red_wall_samples,
                                           CORNELL_BOX_WALL_SAMPLES,
                                           &red_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF red_brdf;
    status = LambertianBrdfAllocate(red_reflector, &red_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL red_material;
    status = ConstantMaterialAllocate(red_brdf, &red_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PREFLECTOR green_reflector;
    status = InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                           cornell_box_green_wall_samples,
                                           CORNELL_BOX_WALL_SAMPLES,
                                           &green_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF green_brdf;
    status = LambertianBrdfAllocate(green_reflector, &green_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL green_material;
    status = ConstantMaterialAllocate(green_brdf, &green_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSPECTRUM light_spectrum;
    status = InterpolatedSpectrumAllocate(cornell_box_light_wavelengths,
                                          cornell_box_light_samples,
                                          CORNELL_BOX_LIGHT_SAMPLES,
                                          &light_spectrum);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PEMISSIVE_MATERIAL light_material;
    status = ConstantEmissiveMaterialAllocate(light_spectrum, &light_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIST_SCENE scene;
    status = ListSceneAllocate(&scene);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PONE_LIGHT_SAMPLER light_sampler;
    status = OneLightSamplerAllocate(&light_sampler);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSHAPE light_shape0, light_shape1;
    status = EmissiveQuadAllocate(
        cornell_box_light[0],
        cornell_box_light[1],
        cornell_box_light[2],
        cornell_box_light[3],
        nullptr,
        nullptr,
        nullptr,
        light_material,
        &light_shape0,
        &light_shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, light_shape0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, light_shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIGHT light0;
    status = AreaLightAllocate(light_shape0,
                               TRIANGLE_BACK_FACE,
                               nullptr,
                               &light0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = OneLightSamplerAddLight(light_sampler, light0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIGHT light1;
    status = AreaLightAllocate(light_shape1,
                               TRIANGLE_BACK_FACE,
                               nullptr,
                               &light1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = OneLightSamplerAddLight(light_sampler, light1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    AddQuadToScene(
        cornell_box_ceiling[0],
        cornell_box_ceiling[1],
        cornell_box_ceiling[2],
        cornell_box_ceiling[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_back_wall[0],
        cornell_box_back_wall[1],
        cornell_box_back_wall[2],
        cornell_box_back_wall[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_floor[0],
        cornell_box_floor[1],
        cornell_box_floor[2],
        cornell_box_floor[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_left_wall[0],
        cornell_box_left_wall[1],
        cornell_box_left_wall[2],
        cornell_box_left_wall[3],
        red_material,
        red_material,
        scene);

    AddQuadToScene(
        cornell_box_right_wall[0],
        cornell_box_right_wall[1],
        cornell_box_right_wall[2],
        cornell_box_right_wall[3],
        green_material,
        green_material,
        scene);

    for (size_t i = 0; i < 5; i++)
    {
        AddQuadToScene(
            cornell_box_short_box[i][0],
            cornell_box_short_box[i][1],
            cornell_box_short_box[i][2],
            cornell_box_short_box[i][3],
            white_material,
            white_material,
            scene);
    }

    for (size_t i = 0; i < 5; i++)
    {
        AddQuadToScene(
            cornell_box_tall_box[i][0],
            cornell_box_tall_box[i][1],
            cornell_box_tall_box[i][2],
            cornell_box_tall_box[i][3],
            white_material,
            white_material,
            scene);
    }

    PCAMERA camera;
    status = PinholeCameraAllocate(
        cornell_box_camera_location,
        cornell_box_camera_direction,
        cornell_box_camera_up,
        cornell_box_focal_length,
        cornell_box_camera_width,
        cornell_box_camera_height,
        &camera);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    TestRenderSingleThreaded(camera,
                             scene,
                             light_sampler,
                             "test_results/cornell_box.pfm");

    SpectrumRelease(light_spectrum);
    ReflectorRelease(white_reflector);
    ReflectorRelease(red_reflector);
    ReflectorRelease(green_reflector);
    BrdfRelease(white_brdf);
    BrdfRelease(red_brdf);
    BrdfRelease(green_brdf);
    MaterialRelease(white_material);
    MaterialRelease(red_material);
    MaterialRelease(green_material);
    ShapeRelease(light_shape0);
    ShapeRelease(light_shape1);
    LightRelease(light0);
    LightRelease(light1);
    ListSceneFree(scene);
    OneLightSamplerFree(light_sampler);
    CameraFree(camera);
}<commit_msg>Add missing sqrt<commit_after>/*++

Copyright (c) 2018 Brad Weinberger

Module Name:

   cornell_box.cc

Abstract:

   Integration tests which render a single triangle.

--*/

#include <string>

#include "iris_advanced_toolkit/pcg_random.h"
#include "iris_camera_toolkit/grid_pixel_sampler.h"
#include "iris_camera_toolkit/pfm_writer.h"
#include "iris_camera_toolkit/pinhole_camera.h"
#include "iris_physx_toolkit/attenuated_reflector.h"
#include "iris_physx_toolkit/cie_color_matcher.h"
#include "iris_physx_toolkit/constant_emissive_material.h"
#include "iris_physx_toolkit/constant_material.h"
#include "iris_physx_toolkit/interpolated_spectrum.h"
#include "iris_physx_toolkit/lambertian_brdf.h"
#include "iris_physx_toolkit/list_scene.h"
#include "iris_physx_toolkit/one_light_sampler.h"
#include "iris_physx_toolkit/path_tracer.h"
#include "iris_physx_toolkit/sample_tracer.h"
#include "iris_physx_toolkit/triangle.h"
#include "googletest/include/gtest/gtest.h"
#include "test_util/cornell_box.h"
#include "test_util/pfm.h"
#include "test_util/quad.h"

void
TestRenderSingleThreaded(
    _In_ PCCAMERA camera,
    _In_ PCLIST_SCENE scene,
    _In_ PONE_LIGHT_SAMPLER light_sampler,
    _In_ const std::string& file_name
    )
{
    PPIXEL_SAMPLER pixel_sampler;
    ISTATUS status =
        GridPixelSamplerAllocate(4, 4, false, 1, 1, false, &pixel_sampler);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PRANDOM rng;
    status = PermutedCongruentialRandomAllocate(
        0x853c49e6748fea9bULL,
        0xda3e39cb94b95bdbULL,
        &rng);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PINTEGRATOR path_tracer;
    status = PathTracerAllocate(3, 8, (float_t)0.0, &path_tracer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PCOLOR_MATCHER color_matcher;
    status = CieColorMatcherAllocate(&color_matcher);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSAMPLE_TRACER sample_tracer;
    status = PhysxSampleTracerAllocate(
        path_tracer,
        ListSceneTraceCallback,
        scene,
        OneLightSamplerSampleLightsCallback,
        light_sampler,
        color_matcher,
        &sample_tracer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PFRAMEBUFFER framebuffer;
    status = FramebufferAllocate(500, 500, &framebuffer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = IrisCameraRenderParallel(16,
        (float_t)0.001, camera, pixel_sampler, sample_tracer, rng, framebuffer);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    bool equals;
    status = ExactlyEqualsPfmFile(framebuffer,
                                  file_name.c_str(),
                                  PFM_PIXEL_FORMAT_XYZ,
                                  &equals);
    //ASSERT_EQ(status, ISTATUS_SUCCESS);
    EXPECT_TRUE(equals);

    if (!equals)
    {
        status = WriteToPfmFile(framebuffer,
                                ("/mnt/c/Users/bradw/Documents/" + file_name).c_str(),
                                PFM_PIXEL_FORMAT_SRGB);
        ASSERT_EQ(status, ISTATUS_SUCCESS);
    }

    PixelSamplerFree(pixel_sampler);
    RandomFree(rng);
    SampleTracerFree(sample_tracer);
    FramebufferFree(framebuffer);
    ColorMatcherRelease(color_matcher);
}

static
void
AddQuadToScene(
    _In_ POINT3 v0,
    _In_ POINT3 v1,
    _In_ POINT3 v2,
    _In_ POINT3 v3,
    _In_opt_ PMATERIAL front_material,
    _In_opt_ PMATERIAL back_material,
    _Inout_ PLIST_SCENE scene
    )
{
    PSHAPE shape0, shape1;
    ISTATUS status = EmissiveQuadAllocate(
        v0,
        v1,
        v2,
        v3,
        front_material,
        back_material,
        nullptr,
        nullptr,
        &shape0,
        &shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, shape0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    ShapeRelease(shape0);
    ShapeRelease(shape1);
}

TEST(CornellBoxTest, CornellBox)
{
    PREFLECTOR white_reflector;
    ISTATUS status =
        InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                      cornell_box_white_wall_samples,
                                      CORNELL_BOX_WALL_SAMPLES,
                                      &white_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF white_brdf;
    status = LambertianBrdfAllocate(white_reflector, &white_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL white_material;
    status = ConstantMaterialAllocate(white_brdf, &white_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PREFLECTOR red_reflector;
    status = InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                           cornell_box_red_wall_samples,
                                           CORNELL_BOX_WALL_SAMPLES,
                                           &red_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF red_brdf;
    status = LambertianBrdfAllocate(red_reflector, &red_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL red_material;
    status = ConstantMaterialAllocate(red_brdf, &red_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PREFLECTOR green_reflector;
    status = InterpolatedReflectorAllocate(cornell_box_wall_wavelengths,
                                           cornell_box_green_wall_samples,
                                           CORNELL_BOX_WALL_SAMPLES,
                                           &green_reflector);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PBRDF green_brdf;
    status = LambertianBrdfAllocate(green_reflector, &green_brdf);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PMATERIAL green_material;
    status = ConstantMaterialAllocate(green_brdf, &green_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSPECTRUM light_spectrum;
    status = InterpolatedSpectrumAllocate(cornell_box_light_wavelengths,
                                          cornell_box_light_samples,
                                          CORNELL_BOX_LIGHT_SAMPLES,
                                          &light_spectrum);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PEMISSIVE_MATERIAL light_material;
    status = ConstantEmissiveMaterialAllocate(light_spectrum, &light_material);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIST_SCENE scene;
    status = ListSceneAllocate(&scene);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PONE_LIGHT_SAMPLER light_sampler;
    status = OneLightSamplerAllocate(&light_sampler);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PSHAPE light_shape0, light_shape1;
    status = EmissiveQuadAllocate(
        cornell_box_light[0],
        cornell_box_light[1],
        cornell_box_light[2],
        cornell_box_light[3],
        nullptr,
        nullptr,
        nullptr,
        light_material,
        &light_shape0,
        &light_shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, light_shape0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = ListSceneAddShape(scene, light_shape1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIGHT light0;
    status = AreaLightAllocate(light_shape0,
                               TRIANGLE_BACK_FACE,
                               nullptr,
                               &light0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = OneLightSamplerAddLight(light_sampler, light0);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    PLIGHT light1;
    status = AreaLightAllocate(light_shape1,
                               TRIANGLE_BACK_FACE,
                               nullptr,
                               &light1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    status = OneLightSamplerAddLight(light_sampler, light1);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    AddQuadToScene(
        cornell_box_ceiling[0],
        cornell_box_ceiling[1],
        cornell_box_ceiling[2],
        cornell_box_ceiling[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_back_wall[0],
        cornell_box_back_wall[1],
        cornell_box_back_wall[2],
        cornell_box_back_wall[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_floor[0],
        cornell_box_floor[1],
        cornell_box_floor[2],
        cornell_box_floor[3],
        white_material,
        white_material,
        scene);

    AddQuadToScene(
        cornell_box_left_wall[0],
        cornell_box_left_wall[1],
        cornell_box_left_wall[2],
        cornell_box_left_wall[3],
        red_material,
        red_material,
        scene);

    AddQuadToScene(
        cornell_box_right_wall[0],
        cornell_box_right_wall[1],
        cornell_box_right_wall[2],
        cornell_box_right_wall[3],
        green_material,
        green_material,
        scene);

    for (size_t i = 0; i < 5; i++)
    {
        AddQuadToScene(
            cornell_box_short_box[i][0],
            cornell_box_short_box[i][1],
            cornell_box_short_box[i][2],
            cornell_box_short_box[i][3],
            white_material,
            white_material,
            scene);
    }

    for (size_t i = 0; i < 5; i++)
    {
        AddQuadToScene(
            cornell_box_tall_box[i][0],
            cornell_box_tall_box[i][1],
            cornell_box_tall_box[i][2],
            cornell_box_tall_box[i][3],
            white_material,
            white_material,
            scene);
    }

    PCAMERA camera;
    status = PinholeCameraAllocate(
        cornell_box_camera_location,
        cornell_box_camera_direction,
        cornell_box_camera_up,
        cornell_box_focal_length,
        cornell_box_camera_width,
        cornell_box_camera_height,
        &camera);
    ASSERT_EQ(status, ISTATUS_SUCCESS);

    TestRenderSingleThreaded(camera,
                             scene,
                             light_sampler,
                             "test_results/cornell_box.pfm");

    SpectrumRelease(light_spectrum);
    ReflectorRelease(white_reflector);
    ReflectorRelease(red_reflector);
    ReflectorRelease(green_reflector);
    BrdfRelease(white_brdf);
    BrdfRelease(red_brdf);
    BrdfRelease(green_brdf);
    MaterialRelease(white_material);
    MaterialRelease(red_material);
    MaterialRelease(green_material);
    ShapeRelease(light_shape0);
    ShapeRelease(light_shape1);
    LightRelease(light0);
    LightRelease(light1);
    ListSceneFree(scene);
    OneLightSamplerFree(light_sampler);
    CameraFree(camera);
}<|endoftext|>


<commit_before>// Some day, I will figure out how to use Catch nicely within Xcode to run some tests

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "choreograph/Choreograph.hpp"
#include "cinder/Timer.h"
#include "cinder/Vector.h"
#include "cinder/Timeline.h"

using namespace std;
using namespace cinder;
using namespace choreograph;

class ScopedTimer
{
public:
  ScopedTimer( const std::string &message, float *output = nullptr ):
  _message( message ),
  _output( output )
  {}
  ~ScopedTimer()
  {
    _timer.stop();
    cout << "[" + _message + "] Elapsed time: " << _timer.getSeconds() * 1000 << "ms" << endl;
    if( _output ) {
      *_output = _timer.getSeconds() * 1000;
    }
  }
private:
  float       *_output = nullptr;
  std::string _message;
  ci::Timer   _timer = ci::Timer( true );
};

TEST_CASE( "Performance stuff", "[library]" ) {
  co::Timeline test_timeline;
  ci::TimelineRef cinder_timeline = ci::Timeline::create();

  const int tween_count = 5000;
  const float dt = 1.0f / 60.0f;

  SECTION( "Tween many targets" ) {
    cout << "Many Targets, One Phrase Each." << endl;
    for( int j = 0; j < 2; ++j )
    {
      vector<Output<vec2>> targets( tween_count, vec2( 0 ) );
      vector<Anim<vec2>> cinder_targets( tween_count, vec2( 0 ) );
      float choreograph, cinder;

      { // Measure basic performance.
        ScopedTimer performance( "Choreograph Timeline", &choreograph );
        //
        for( int i = 0; i < tween_count; ++i )
        {
          test_timeline.move( &targets[i] ).getSequence().hold( 1.0f ).rampTo( vec2( i * 5, i * 20 ), 2.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          test_timeline.step( dt );
        }
      }

      { // Compare to cinder timeline perf.
        ScopedTimer perf( "Cinder Timeline", &cinder );
        for( int i = 0; i < tween_count; ++i )
        {
          cinder_timeline->apply( &cinder_targets[i], vec2( i * 5, i * 20 ), 2.0f ).delay( 1.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          cinder_timeline->step( dt );
        }
      }

      cout << "Comparative timeline performance (Choreograph:Cinder): " << (choreograph / cinder) << endl;
    }

  }

  SECTION( "Tween one target many times" ) {
    cout << "Single Target, Many Phrases." << endl;
    for( int j = 0; j < 2; ++j )
    {
      Output<vec2>  target( vec2( 0 ) );
      Anim<vec2>    cinder_target( vec2( 0 ) );
      float choreograph, cinder;

      { // Measure basic performance.
        ScopedTimer performance( "Choreograph Timeline", &choreograph );
        //
        for( int i = 0; i < tween_count; ++i )
        {
          test_timeline.queue( &target ).hold( 1.0f ).rampTo( vec2( i * 5, i * 20 ), 2.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          test_timeline.step( dt );
        }
      }

      { // Compare to cinder timeline perf.
        ScopedTimer perf( "Cinder Timeline", &cinder );
        for( int i = 0; i < tween_count; ++i )
        {
          cinder_timeline->appendTo( &cinder_target, vec2( i * 5, i * 20 ), 2.0f ).delay( 1.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          cinder_timeline->step( dt );
        }
      }

      cout << "Comparative timeline performance (Choreograph:Cinder): " << (choreograph / cinder) << endl;
    }
  }

  SECTION( "" ) {

  }
  cout << endl << endl;
}
<commit_msg>Reasonable set of benchmark tests.<commit_after>// Some day, I will figure out how to use Catch nicely within Xcode to run some tests

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "choreograph/Choreograph.hpp"
#include "cinder/Timer.h"
#include "cinder/Vector.h"
#include "cinder/Timeline.h"

using namespace std;
using namespace cinder;
using namespace choreograph;

class ScopedTimer
{
public:
  ScopedTimer( const std::string &message, float *output = nullptr ):
  _message( message ),
  _output( output )
  {}
  ~ScopedTimer()
  {
    _timer.stop();
    string message = "[" + _message + "]";
    if( message.size() < 50 ) {
      message = message + string( 50 - message.size(), ' ' );
    }
    cout << message << _timer.getSeconds() * 1000 << "ms" << endl;
    if( _output ) {
      *_output = _timer.getSeconds() * 1000;
    }
  }
private:
  float       *_output = nullptr;
  std::string _message;
  ci::Timer   _timer = ci::Timer( true );
};

TEST_CASE( "Creating Motions" ) {
  co::Timeline test_timeline;
  float dt = 1.0f / 60.0f;
  const size_t count = 10e3; // 10k
  SequenceRef<vec2> sequence = make_shared<Sequence<vec2>>( vec2( 1.0f ) );
  sequence->rampTo( vec2( 5.0f ), 1.0f ).rampTo( vec2( 10.0f, 6.0f ), 0.5f );

  cout << "Working with " << count << " motions." << endl;

  vector<Output<vec2>> targets( count, vec2( 0 ) );
  {
    ScopedTimer timer( "Creating Motions" );
    for( auto &target : targets ) {
      test_timeline.move( &target ).getSequence().rampTo( vec2( 10.0f ), 1.0f );
    }
  }

  {
    ScopedTimer timer( "Stepping Motions 1x" );

    test_timeline.step( dt );
  }

  {
    ScopedTimer timer( "Stepping Motions 60x" );
    for( int i = 0; i < 60; ++i ) {
      test_timeline.step( dt );
    }
  }

  {
    ScopedTimer timer( "Clearing Motions" );
    for( auto &target : targets ) {
      target.disconnect();
    }
  }

  {
    ScopedTimer timer( "Stepping Empty Timeline 60x" );
    for( int i = 0; i < 60; ++i ) {
      test_timeline.step( dt );
    }
  }

  {
    ScopedTimer timer( "Creating Motions from shared Sequence" );
    for( auto &target : targets ) {
      test_timeline.move( &target, sequence );
    }
  }

  {
    ScopedTimer timer( "Stepping Motions with shared Sequence 1x" );

    test_timeline.step( dt );
  }

  {
    ScopedTimer timer( "Stepping Motions with shared Sequence 60x" );
    for( int i = 0; i < 60; ++i ) {
      test_timeline.step( dt );
    }
  }
}

TEST_CASE( "Comparative Performance with ci::Timeline", "[library]" ) {
  co::Timeline test_timeline;
  ci::TimelineRef cinder_timeline = ci::Timeline::create();

  const int tween_count = 5000;
  const float dt = 1.0f / 60.0f;

  SECTION( "Tween many targets" ) {
    cout << "Many Targets, One Phrase Each." << endl;
    for( int j = 0; j < 2; ++j )
    {
      vector<Output<vec2>> targets( tween_count, vec2( 0 ) );
      vector<Anim<vec2>> cinder_targets( tween_count, vec2( 0 ) );
      float choreograph, cinder;

      { // Measure basic performance.
        ScopedTimer performance( "Choreograph Timeline", &choreograph );
        //
        for( int i = 0; i < tween_count; ++i )
        {
          test_timeline.move( &targets[i] ).getSequence().hold( 1.0f ).rampTo( vec2( i * 5, i * 20 ), 2.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          test_timeline.step( dt );
        }
      }

      { // Compare to cinder timeline perf.
        ScopedTimer perf( "Cinder Timeline", &cinder );
        for( int i = 0; i < tween_count; ++i )
        {
          cinder_timeline->apply( &cinder_targets[i], vec2( i * 5, i * 20 ), 2.0f ).delay( 1.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          cinder_timeline->step( dt );
        }
      }

      cout << "Comparative timeline performance (Choreograph:Cinder): " << (choreograph / cinder) << endl;
    }

  }

  SECTION( "Tween one target many times" ) {
    cout << "Single Target, Many Phrases." << endl;
    for( int j = 0; j < 2; ++j )
    {
      Output<vec2>  target( vec2( 0 ) );
      Anim<vec2>    cinder_target( vec2( 0 ) );
      float choreograph, cinder;

      { // Measure basic performance.
        ScopedTimer performance( "Choreograph Timeline", &choreograph );
        //
        for( int i = 0; i < tween_count; ++i )
        {
          test_timeline.queue( &target ).hold( 1.0f ).rampTo( vec2( i * 5, i * 20 ), 2.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          test_timeline.step( dt );
        }
      }

      { // Compare to cinder timeline perf.
        ScopedTimer perf( "Cinder Timeline", &cinder );
        for( int i = 0; i < tween_count; ++i )
        {
          cinder_timeline->appendTo( &cinder_target, vec2( i * 5, i * 20 ), 2.0f ).delay( 1.0f );
        }
        for( float t = 0.0f; t <= 3.0f; t += dt ) {
          cinder_timeline->step( dt );
        }
      }

      cout << "Comparative timeline performance (Choreograph:Cinder): " << (choreograph / cinder) << endl;
    }
  }

  cout << endl;
}
<|endoftext|>


<commit_before>/***********************************************************************
 *    filename:   InputAggregator.cpp
 *    created:    10/7/2013
 *    author:     Timotei Dolean <timotei21@gmail.com>
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include <boost/test/unit_test.hpp>
#include <boost/assign.hpp>

#include <vector>
#include <iostream>
#include <map>

#include "CEGUI/CEGUI.h"

using namespace CEGUI;

struct InputEventHandler
{
    virtual void handle(const InputEvent* event) = 0;
};

template <typename TInput, typename TClass>
struct InputEventHandlerImpl : public InputEventHandler
{
    typedef void(TClass::*HandlerFunctionType)(const TInput*);

    InputEventHandlerImpl(HandlerFunctionType handler_func, TClass* obj) :
        d_handlerFunc(handler_func),
        d_obj(obj)
    {}

    void handle(const InputEvent* event)
    {
        (d_obj->*d_handlerFunc)((const TInput*)event);
    }

private:
    HandlerFunctionType d_handlerFunc;
    TClass* d_obj;
};

class MockInputEventReceiver : public InputEventReceiver
{
public:
    std::string d_text;
    float d_totalScroll;
    Vector2f d_pointerPosition;
    Vector2f d_pointerTotalDelta;
    std::vector<SemanticValue> d_semanticValues;

    MockInputEventReceiver() :
        d_text(""),
        d_pointerPosition(0.0f, 0.0f),
        d_pointerTotalDelta(0.0f, 0.0f),
        d_totalScroll(0)
    {}

    ~MockInputEventReceiver()
    {
        for (HandlersMap::const_iterator itor = d_handlersMap.begin();
            itor != d_handlersMap.end(); ++ itor)
        {
            delete (*itor).second;
        }

        d_handlersMap.clear();
    }

    void injectInputEvent(const InputEvent* event)
    {
        HandlersMap::const_iterator itor = d_handlersMap.find(event->d_eventType);
        if (itor != d_handlersMap.end())
        {
            (*itor).second->handle(event);
        }
        else
        {
            std::cout << "No event handler for event type: " << event->d_eventType << std::endl;
        }
    }

    void handleTextEvent(const TextInputEvent* event)
    {
        d_text += event->d_character;
    }

    void handleMovementEvent(const PointerMovementInputEvent* event)
    {
        d_pointerPosition = event->d_position;
        d_pointerTotalDelta += event->d_delta;
    }

    void handleScrollEvent(const ScrollInputEvent* event)
    {
        d_totalScroll += event->d_delta;
    }

    void handleSemanticEvent(const SemanticInputEvent* event)
    {
        d_semanticValues.push_back(event->d_value);
    }

    void initializeEventHandlers()
    {
        d_handlersMap.insert(std::make_pair(TextInputEventType,
            new InputEventHandlerImpl<TextInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleTextEvent, this)));

        d_handlersMap.insert(std::make_pair(MovementInputEventType,
            new InputEventHandlerImpl<PointerMovementInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleMovementEvent, this)));

        d_handlersMap.insert(std::make_pair(ScrollInputEventType,
            new InputEventHandlerImpl<ScrollInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleScrollEvent, this)));

        d_handlersMap.insert(std::make_pair(SemanticInputEventType,
            new InputEventHandlerImpl<SemanticInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleSemanticEvent, this)));
    }

private:
    typedef std::map<int, InputEventHandler*> HandlersMap;
    HandlersMap d_handlersMap;
};

struct InputAggregatorFixture
{
    InputAggregatorFixture()
    {
        d_inputEventReceiver = new MockInputEventReceiver;
        d_inputEventReceiver->initializeEventHandlers();
        d_inputAggregator = new InputAggregator(d_inputEventReceiver);
    }

    ~InputAggregatorFixture()
    {
        delete d_inputEventReceiver;
        delete d_inputAggregator;
    }

    InputAggregator* d_inputAggregator;
    MockInputEventReceiver* d_inputEventReceiver;
};

//----------------------------------------------------------------------------//

BOOST_FIXTURE_TEST_SUITE(InputAggregator, InputAggregatorFixture)

BOOST_AUTO_TEST_CASE(TextEventOneChar)
{
    d_inputAggregator->injectChar('a');

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_text, "a");
}

BOOST_AUTO_TEST_CASE(TextEventMultipleChars)
{
    d_inputAggregator->injectChar('a');
    d_inputAggregator->injectChar('b');
    d_inputAggregator->injectChar('c');

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_text, "abc");
}

BOOST_AUTO_TEST_CASE(MovementEventNoDelta)
{
    d_inputAggregator->injectMouseMove(0, 0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 0);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 0);
}

BOOST_AUTO_TEST_CASE(MovementEventSingleDelta)
{
    d_inputAggregator->injectMouseMove(0, 0);
    d_inputAggregator->injectMouseMove(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);
}

BOOST_AUTO_TEST_CASE(MovementEventMultipleDeltas)
{
    d_inputAggregator->injectMouseMove(0, 0);
    d_inputAggregator->injectMouseMove(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);

    d_inputAggregator->injectMouseMove(3, -3);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 6);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 2);
}

BOOST_AUTO_TEST_CASE(MovementEventZeroPosition)
{
    d_inputAggregator->injectMousePosition(0, 0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 0);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 0);
}

BOOST_AUTO_TEST_CASE(MovementEventNonZeroPosition)
{
    d_inputAggregator->injectMousePosition(30, 40);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 30);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 40);
}

BOOST_AUTO_TEST_CASE(MovementEventMultiplePositions)
{
    d_inputAggregator->injectMousePosition(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);

    d_inputAggregator->injectMousePosition(3, -3);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, -3);
}

BOOST_AUTO_TEST_CASE(ScrollEventNoDelta)
{
    d_inputAggregator->injectMouseWheelChange(0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 0);
}

BOOST_AUTO_TEST_CASE(ScrollEventMultipleDelta)
{
    d_inputAggregator->injectMouseWheelChange(1);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 1);

    d_inputAggregator->injectMouseWheelChange(3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 4);

    d_inputAggregator->injectMouseWheelChange(5);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 9);

    d_inputAggregator->injectMouseWheelChange(-2);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 7);
}

BOOST_AUTO_TEST_CASE(CutRequestToCut)
{
    std::vector<SemanticValue> expected_values =
        boost::assign::list_of(Cut);

    d_inputAggregator->injectCutRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(CopyRequestToCopy)
{
    std::vector<SemanticValue> expected_values =
        boost::assign::list_of(Copy);

    d_inputAggregator->injectCopyRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(PasteRequestToPaste)
{
    std::vector<SemanticValue> expected_values =
        boost::assign::list_of(Paste);

    d_inputAggregator->injectPasteRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(MouseClickToPointerActivate)
{
    std::vector<SemanticValue> expected_values =
        boost::assign::list_of(PointerActivate);

    d_inputAggregator->injectMouseButtonClick(LeftButton);

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Remove the dependency on boost assign<commit_after>/***********************************************************************
 *    filename:   InputAggregator.cpp
 *    created:    10/7/2013
 *    author:     Timotei Dolean <timotei21@gmail.com>
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include <boost/test/unit_test.hpp>

#include <vector>
#include <iostream>
#include <map>

#include "CEGUI/CEGUI.h"

using namespace CEGUI;

struct InputEventHandler
{
    virtual void handle(const InputEvent* event) = 0;
};

template <typename TInput, typename TClass>
struct InputEventHandlerImpl : public InputEventHandler
{
    typedef void(TClass::*HandlerFunctionType)(const TInput*);

    InputEventHandlerImpl(HandlerFunctionType handler_func, TClass* obj) :
        d_handlerFunc(handler_func),
        d_obj(obj)
    {}

    void handle(const InputEvent* event)
    {
        (d_obj->*d_handlerFunc)((const TInput*)event);
    }

private:
    HandlerFunctionType d_handlerFunc;
    TClass* d_obj;
};

class MockInputEventReceiver : public InputEventReceiver
{
public:
    std::string d_text;
    float d_totalScroll;
    Vector2f d_pointerPosition;
    Vector2f d_pointerTotalDelta;
    std::vector<SemanticValue> d_semanticValues;

    MockInputEventReceiver() :
        d_text(""),
        d_pointerPosition(0.0f, 0.0f),
        d_pointerTotalDelta(0.0f, 0.0f),
        d_totalScroll(0)
    {}

    ~MockInputEventReceiver()
    {
        for (HandlersMap::const_iterator itor = d_handlersMap.begin();
            itor != d_handlersMap.end(); ++ itor)
        {
            delete (*itor).second;
        }

        d_handlersMap.clear();
    }

    void injectInputEvent(const InputEvent* event)
    {
        HandlersMap::const_iterator itor = d_handlersMap.find(event->d_eventType);
        if (itor != d_handlersMap.end())
        {
            (*itor).second->handle(event);
        }
        else
        {
            std::cout << "No event handler for event type: " << event->d_eventType << std::endl;
        }
    }

    void handleTextEvent(const TextInputEvent* event)
    {
        d_text += event->d_character;
    }

    void handleMovementEvent(const PointerMovementInputEvent* event)
    {
        d_pointerPosition = event->d_position;
        d_pointerTotalDelta += event->d_delta;
    }

    void handleScrollEvent(const ScrollInputEvent* event)
    {
        d_totalScroll += event->d_delta;
    }

    void handleSemanticEvent(const SemanticInputEvent* event)
    {
        d_semanticValues.push_back(event->d_value);
    }

    void initializeEventHandlers()
    {
        d_handlersMap.insert(std::make_pair(TextInputEventType,
            new InputEventHandlerImpl<TextInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleTextEvent, this)));

        d_handlersMap.insert(std::make_pair(MovementInputEventType,
            new InputEventHandlerImpl<PointerMovementInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleMovementEvent, this)));

        d_handlersMap.insert(std::make_pair(ScrollInputEventType,
            new InputEventHandlerImpl<ScrollInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleScrollEvent, this)));

        d_handlersMap.insert(std::make_pair(SemanticInputEventType,
            new InputEventHandlerImpl<SemanticInputEvent, MockInputEventReceiver>(
                &MockInputEventReceiver::handleSemanticEvent, this)));
    }

private:
    typedef std::map<int, InputEventHandler*> HandlersMap;
    HandlersMap d_handlersMap;
};

struct InputAggregatorFixture
{
    InputAggregatorFixture()
    {
        d_inputEventReceiver = new MockInputEventReceiver;
        d_inputEventReceiver->initializeEventHandlers();
        d_inputAggregator = new InputAggregator(d_inputEventReceiver);
    }

    ~InputAggregatorFixture()
    {
        delete d_inputEventReceiver;
        delete d_inputAggregator;
    }

    InputAggregator* d_inputAggregator;
    MockInputEventReceiver* d_inputEventReceiver;
};

//----------------------------------------------------------------------------//

BOOST_FIXTURE_TEST_SUITE(InputAggregator, InputAggregatorFixture)

BOOST_AUTO_TEST_CASE(TextEventOneChar)
{
    d_inputAggregator->injectChar('a');

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_text, "a");
}

BOOST_AUTO_TEST_CASE(TextEventMultipleChars)
{
    d_inputAggregator->injectChar('a');
    d_inputAggregator->injectChar('b');
    d_inputAggregator->injectChar('c');

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_text, "abc");
}

BOOST_AUTO_TEST_CASE(MovementEventNoDelta)
{
    d_inputAggregator->injectMouseMove(0, 0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 0);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 0);
}

BOOST_AUTO_TEST_CASE(MovementEventSingleDelta)
{
    d_inputAggregator->injectMouseMove(0, 0);
    d_inputAggregator->injectMouseMove(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);
}

BOOST_AUTO_TEST_CASE(MovementEventMultipleDeltas)
{
    d_inputAggregator->injectMouseMove(0, 0);
    d_inputAggregator->injectMouseMove(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);

    d_inputAggregator->injectMouseMove(3, -3);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 6);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 2);
}

BOOST_AUTO_TEST_CASE(MovementEventZeroPosition)
{
    d_inputAggregator->injectMousePosition(0, 0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 0);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 0);
}

BOOST_AUTO_TEST_CASE(MovementEventNonZeroPosition)
{
    d_inputAggregator->injectMousePosition(30, 40);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 30);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 40);
}

BOOST_AUTO_TEST_CASE(MovementEventMultiplePositions)
{
    d_inputAggregator->injectMousePosition(3, 5);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition,
        d_inputEventReceiver->d_pointerTotalDelta);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, 5);

    d_inputAggregator->injectMousePosition(3, -3);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_x, 3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_pointerPosition.d_y, -3);
}

BOOST_AUTO_TEST_CASE(ScrollEventNoDelta)
{
    d_inputAggregator->injectMouseWheelChange(0);

    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 0);
}

BOOST_AUTO_TEST_CASE(ScrollEventMultipleDelta)
{
    d_inputAggregator->injectMouseWheelChange(1);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 1);

    d_inputAggregator->injectMouseWheelChange(3);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 4);

    d_inputAggregator->injectMouseWheelChange(5);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 9);

    d_inputAggregator->injectMouseWheelChange(-2);
    BOOST_CHECK_EQUAL(d_inputEventReceiver->d_totalScroll, 7);
}

BOOST_AUTO_TEST_CASE(CutRequestToCut)
{
    std::vector<SemanticValue> expected_values;
    expected_values.push_back(Cut);

    d_inputAggregator->injectCutRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(CopyRequestToCopy)
{
    std::vector<SemanticValue> expected_values;
    expected_values.push_back(Copy);

    d_inputAggregator->injectCopyRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(PasteRequestToPaste)
{
    std::vector<SemanticValue> expected_values;
    expected_values.push_back(Paste);

    d_inputAggregator->injectPasteRequest();

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_CASE(MouseClickToPointerActivate)
{
    std::vector<SemanticValue> expected_values;
    expected_values.push_back(PointerActivate);

    d_inputAggregator->injectMouseButtonClick(LeftButton);

    BOOST_CHECK_EQUAL_COLLECTIONS(expected_values.begin(), expected_values.end(),
        d_inputEventReceiver->d_semanticValues.begin(),
        d_inputEventReceiver->d_semanticValues.end());
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "thruster_tortuga.h"

ThrusterTortugaNode::ThrusterTortugaNode(int argc, char **argv, int rate){
    ros::Rate loop_rate(rate);
    subscriber = n.subscribe("/qubo/thruster_input", 1000, &ThrusterTortugaNode::thrusterCallBack, this);
    // copied exactly from lcdshow:
    fd = openSensorBoard("/dev/ttyUSB0");

}

ThrusterTortugaNode::~ThrusterTortugaNode(){
    setSpeeds(fd, 0, 0, 0, 0, 0, 0);
    //SG: does close make sense there?
    close(fd);
}

void ThrusterTortugaNode::update(){
    //Will need more here I bet.
    ros::spinOnce();
}

void ThrusterTortugaNode::publish(){
    setSpeeds(fd, msg.data[0], msg.data[1], msg.data[2], msg.data[3], msg.data[4], msg.data[5]);
}

void ThrusterTortugaNode::thrusterCallBack(const std_msgs::Float64MultiArray sim_msg){
    //SG: TODO change this shit
    msg.data = sim_msg.data;
}
<commit_msg>no major changes, just changed a few variable names, more to follow<commit_after>#include "thruster_tortuga.h"

ThrusterTortugaNode::ThrusterTortugaNode(int argc, char **argv, int rate){
    ros::Rate loop_rate(rate);
    subscriber = n.subscribe("/qubo/thruster_input", 1000, &ThrusterTortugaNode::thrusterCallBack, this);
    // copied exactly from lcdshow:
    fd = openSensorBoard("/dev/ttyUSB0");

}

ThrusterTortugaNode::~ThrusterTortugaNode(){
    setSpeeds(fd, 0, 0, 0, 0, 0, 0);
    //SG: does close make sense there?
    close(fd);
}

void ThrusterTortugaNode::update(){
    //Will need more here I bet.
    ros::spinOnce();

}

void ThrusterTortugaNode::publish(){
    setSpeeds(fd, msg.data[0], msg.data[1], msg.data[2], msg.data[3], msg.data[4], msg.data[5]);
}

void ThrusterTortugaNode::thrusterCallBack(const std_msgs::Float64MultiArray new_vector){
    //SG: TODO change this shit
    msg.data = new_vector.data;
}
<|endoftext|>


<commit_before>
#include <GL/glew.h>

#include <algorithm>
#include <random>
#include <cassert>
#include <chrono>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/constants.hpp>

#include <glow/Error.h>
#include <glow/Uniform.h>
#include <glow/Program.h>
#include <glow/Shader.h>
#include <glow/Buffer.h>
#include <glow/logging.h>
#include <glow/AutoTimer.h>
#include <glow/Timer.h>
#include <glow/VertexArrayObject.h>

#include <glowutils/File.h>
#include <glowutils/AxisAlignedBoundingBox.h>
#include <glowutils/MathMacros.h>
#include <glowutils/Icosahedron.h>
#include <glowutils/Camera.h>
#include <glowutils/AdaptiveGrid.h>
#include <glowutils/AbstractCoordinateProvider.h>
#include <glowutils/WorldInHandNavigation.h>
#include <glowutils/CameraPathRecorder.h>
#include <glowutils/CameraPathPlayer.h>

#include <glowwindow/ContextFormat.h>
#include <glowwindow/Context.h>
#include <glowwindow/Window.h>
#include <glowwindow/WindowEventHandler.h>

using namespace glow;
using namespace glowwindow;
using namespace glowutils;
using namespace glm;

class EventHandler : public WindowEventHandler, AbstractCoordinateProvider
{
public:
    EventHandler()
    : m_camera(vec3(0.f, 1.f, 4.0f))
    , angle(0)
    , player(m_camera)
    , iterations(2)
    , usePath(false)
    {
        m_aabb.extend(vec3(-8.f, -1.f, -8.f));
        m_aabb.extend(vec3(8.f, 1.f, 8.f));

        m_nav.setCamera(&m_camera);
        m_nav.setCoordinateProvider(this);
        m_nav.setBoundaryHint(m_aabb);

        vec3 up(0.0, 1.0, 0.0);
        vec3 center(0.0, 0.0, 0.0);
        float fov = 60.0;
        float height = 1.0;
        float d = 4.0;

        /*path
            << CameraPathPoint(vec3(0.0, 1.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(0.0, 1.0, 5.0), center, up, fov)
            << CameraPathPoint(vec3(2.0, 2.0, 5.0), center, vec3(-1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0, 2.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(1.0, 2.0, 10.0), center, up, fov)
            << CameraPathPoint(vec3(0.0, 2.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(2.0, 2.0, 5.0), vec3(-5.0, -1.0, -1.0), vec3(1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(0.0, 1.0, 4.0), center, up, fov);*/

        path
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, 1.0*d), vec3(0.0, 5.0, 0.0), vec3(-1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0*d, height*2, 1.0*d), center, vec3(0.0, -1.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0*d, height*6, 3.0*d), center, vec3(0.0, 0.0, 1.0), fov)
            << CameraPathPoint(vec3(-1.0*d, height, -4.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
        ;

        /*path
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, 1.0*d), center, up, fov)
            << CameraPathPoint(vec3(1.0*d, height, 1.0*d), center, up, fov)
            << CameraPathPoint(vec3(1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
        ;*/

        player.setPath(path);
    }

    virtual ~EventHandler()
    {
    }

    void createAndSetupTexture();
    void createAndSetupShaders();
	void createAndSetupGeometry();

    virtual void initialize(Window & window) override
    {
        DebugMessageOutput::enable();

        glClearColor(1.0f, 1.0f, 1.0f, 0.f);

        m_sphere = new Program();
        m_sphere->attach(
            createShaderFromFile(GL_VERTEX_SHADER,   "data/adaptive-grid/sphere.vert")
        ,   createShaderFromFile(GL_FRAGMENT_SHADER, "data/adaptive-grid/sphere.frag"));

        m_icosahedron = new Icosahedron(iterations);
        m_agrid = new AdaptiveGrid(16U);

        m_camera.setZNear(0.1f);
        m_camera.setZFar(1024.f);

        m_agrid->setCamera(&m_camera);

        player.createVao();

        timer.start();

        window.addTimer(0, 0);
    }

    virtual void framebufferResizeEvent(ResizeEvent & event) override
    {
        glViewport(0, 0, event.width(), event.height());
        m_camera.setViewport(event.width(), event.height());
    }

    virtual void paintEvent(PaintEvent &) override
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        m_agrid->update();
        m_sphere->setUniform("transform", m_camera.viewProjection());

        m_sphere->use();
        m_icosahedron->draw();
        m_sphere->release();

        player.draw(m_camera.viewProjection());

        m_agrid->draw();
    }

    virtual void keyPressEvent(KeyEvent & event) override
    {
        switch (event.key())
        {
            case GLFW_KEY_SLASH:
                if (iterations>1)
                    m_icosahedron = new Icosahedron(--iterations);
                break;
            case GLFW_KEY_RIGHT_BRACKET:
                if (iterations<7)
                    m_icosahedron = new Icosahedron(++iterations);
                break;
            case GLFW_KEY_T:
                usePath = !usePath;
                break;
        }
        //glow::debug() << event.key();
    }

    virtual void idle(Window & window) override
    {
        //window.repaint();
    }

    virtual void timerEvent(TimerEvent & event) override
    {
        auto d = std::chrono::duration<long double, std::nano>(timer.elapsed());
        timer.reset();

        static auto duration = std::chrono::seconds(10);

        if (usePath)
        {
            angle+= d/std::chrono::duration_cast<std::chrono::duration<long double, std::nano>>(duration);

            while (angle>1)
                angle = 0;

            float t = angle;

            player.play(t);
        }

        event.window()->repaint();
    }

//-----------------

    virtual void mousePressEvent(MouseEvent & event) override
    {
        switch (event.button())
        {
            case GLFW_MOUSE_BUTTON_LEFT:
                m_nav.panBegin(event.pos());
                event.accept();
                break;

            case GLFW_MOUSE_BUTTON_RIGHT:
                m_nav.rotateBegin(event.pos());
                event.accept();
                break;
        }
    }
    virtual void mouseMoveEvent(MouseEvent & event) override
    {
        switch (m_nav.mode())
        {
            case WorldInHandNavigation::PanInteraction:
                m_nav.panProcess(event.pos());
                event.accept();
                break;

            case WorldInHandNavigation::RotateInteraction:
                m_nav.rotateProcess(event.pos());
                event.accept();
        }
    }
    virtual void mouseReleaseEvent(MouseEvent & event) override
    {
        switch (event.button())
        {
            case GLFW_MOUSE_BUTTON_LEFT:
                m_nav.panEnd();
                event.accept();
                break;

            case GLFW_MOUSE_BUTTON_RIGHT:
                m_nav.rotateEnd();
                event.accept();
                break;
        }
    }

    void scrollEvent(ScrollEvent & event) override
    {
        if (WorldInHandNavigation::NoInteraction != m_nav.mode())
            return;

        m_nav.scaleAtMouse(event.pos(), -event.offset().y * 0.1f);
        event.accept();
    }

    virtual const float depthAt(const ivec2 & windowCoordinates)
    {
        return AbstractCoordinateProvider::depthAt(m_camera, GL_DEPTH_COMPONENT, windowCoordinates);
    }

    virtual const vec3 objAt(const ivec2 & windowCoordinates)
    {
        return unproject(m_camera, static_cast<GLenum>(GL_DEPTH_COMPONENT), windowCoordinates);
    }

    virtual const vec3 objAt(const ivec2 & windowCoordinates, const float depth)
    {
        return unproject(m_camera, depth, windowCoordinates);
    }

    virtual const glm::vec3 objAt(
        const ivec2 & windowCoordinates
    ,   const float depth
    ,   const mat4 & viewProjectionInverted)
    {
        return unproject(m_camera, viewProjectionInverted, depth, windowCoordinates);
    }

protected:

    ref_ptr<Program> m_sphere;

    ref_ptr<Icosahedron> m_icosahedron;
    ref_ptr<AdaptiveGrid> m_agrid;

    Timer timer;
    Camera m_camera;
    float angle;
    CameraPath path;
    CameraPathPlayer player;
    unsigned iterations;

    bool usePath;

    WorldInHandNavigation m_nav;
    AxisAlignedBoundingBox m_aabb;
};

/** This example shows ... .
*/
int main(int argc, char* argv[])
{
    ContextFormat format;
    format.setVersion(4, 0);
    format.setProfile(ContextFormat::CoreProfile);
    format.setDepthBufferSize(16);

    Window window;
    window.setEventHandler(new EventHandler());

    window.create(format, "Camera Path Example");
    window.context()->setSwapInterval(Context::VerticalSyncronization);
    window.show();

    return MainLoop::run();
}
<commit_msg>Fixed Visual C++ compile errors<commit_after>
#include <GL/glew.h>

#include <algorithm>
#include <random>
#include <cassert>
#include <chrono>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/constants.hpp>

#include <glow/Error.h>
#include <glow/Uniform.h>
#include <glow/Program.h>
#include <glow/Shader.h>
#include <glow/Buffer.h>
#include <glow/logging.h>
#include <glow/AutoTimer.h>
#include <glow/Timer.h>
#include <glow/VertexArrayObject.h>

#include <glowutils/File.h>
#include <glowutils/AxisAlignedBoundingBox.h>
#include <glowutils/MathMacros.h>
#include <glowutils/Icosahedron.h>
#include <glowutils/Camera.h>
#include <glowutils/AdaptiveGrid.h>
#include <glowutils/AbstractCoordinateProvider.h>
#include <glowutils/WorldInHandNavigation.h>
#include <glowutils/CameraPathRecorder.h>
#include <glowutils/CameraPathPlayer.h>

#include <glowwindow/ContextFormat.h>
#include <glowwindow/Context.h>
#include <glowwindow/Window.h>
#include <glowwindow/WindowEventHandler.h>

using namespace glow;
using namespace glowwindow;
using namespace glowutils;
using namespace glm;

class EventHandler : public WindowEventHandler, AbstractCoordinateProvider
{
public:
    EventHandler()
    : m_camera(vec3(0.f, 1.f, 4.0f))
    , angle(0)
    , player(m_camera)
    , iterations(2)
    , usePath(false)
    {
        m_aabb.extend(vec3(-8.f, -1.f, -8.f));
        m_aabb.extend(vec3(8.f, 1.f, 8.f));

        m_nav.setCamera(&m_camera);
        m_nav.setCoordinateProvider(this);
        m_nav.setBoundaryHint(m_aabb);

        vec3 up(0.0, 1.0, 0.0);
        vec3 center(0.0, 0.0, 0.0);
        float fov = 60.0;
        float height = 1.0;
        float d = 4.0;

        /*path
            << CameraPathPoint(vec3(0.0, 1.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(0.0, 1.0, 5.0), center, up, fov)
            << CameraPathPoint(vec3(2.0, 2.0, 5.0), center, vec3(-1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0, 2.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(1.0, 2.0, 10.0), center, up, fov)
            << CameraPathPoint(vec3(0.0, 2.0, 4.0), center, up, fov)
            << CameraPathPoint(vec3(2.0, 2.0, 5.0), vec3(-5.0, -1.0, -1.0), vec3(1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(0.0, 1.0, 4.0), center, up, fov);*/

        path
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, 1.0*d), vec3(0.0, 5.0, 0.0), vec3(-1.0, 0.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0*d, height*2, 1.0*d), center, vec3(0.0, -1.0, 0.0), fov)
            << CameraPathPoint(vec3(1.0*d, height*6, 3.0*d), center, vec3(0.0, 0.0, 1.0), fov)
            << CameraPathPoint(vec3(-1.0*d, height, -4.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
        ;

        /*path
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, 1.0*d), center, up, fov)
            << CameraPathPoint(vec3(1.0*d, height, 1.0*d), center, up, fov)
            << CameraPathPoint(vec3(1.0*d, height, -1.0*d), center, up, fov)
            << CameraPathPoint(vec3(-1.0*d, height, -1.0*d), center, up, fov)
        ;*/

        player.setPath(path);
    }

    virtual ~EventHandler()
    {
    }

    void createAndSetupTexture();
    void createAndSetupShaders();
	void createAndSetupGeometry();

    virtual void initialize(Window & window) override
    {
        DebugMessageOutput::enable();

        glClearColor(1.0f, 1.0f, 1.0f, 0.f);

        m_sphere = new Program();
        m_sphere->attach(
            createShaderFromFile(GL_VERTEX_SHADER,   "data/adaptive-grid/sphere.vert")
        ,   createShaderFromFile(GL_FRAGMENT_SHADER, "data/adaptive-grid/sphere.frag"));

        m_icosahedron = new Icosahedron(iterations);
        m_agrid = new AdaptiveGrid(16U);

        m_camera.setZNear(0.1f);
        m_camera.setZFar(1024.f);

        m_agrid->setCamera(&m_camera);

        player.createVao();

        timer.start();

        window.addTimer(0, 0);
    }

    virtual void framebufferResizeEvent(ResizeEvent & event) override
    {
        glViewport(0, 0, event.width(), event.height());
        m_camera.setViewport(event.width(), event.height());
    }

    virtual void paintEvent(PaintEvent &) override
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        m_agrid->update();
        m_sphere->setUniform("transform", m_camera.viewProjection());

        m_sphere->use();
        m_icosahedron->draw();
        m_sphere->release();

        player.draw(m_camera.viewProjection());

        m_agrid->draw();
    }

    virtual void keyPressEvent(KeyEvent & event) override
    {
        switch (event.key())
        {
            case GLFW_KEY_SLASH:
                if (iterations>1)
                    m_icosahedron = new Icosahedron(--iterations);
                break;
            case GLFW_KEY_RIGHT_BRACKET:
                if (iterations<7)
                    m_icosahedron = new Icosahedron(++iterations);
                break;
            case GLFW_KEY_T:
                usePath = !usePath;
                break;
        }
        //glow::debug() << event.key();
    }

    virtual void idle(Window & window) override
    {
        //window.repaint();
    }

    virtual void timerEvent(TimerEvent & event) override
    {
        auto d = std::chrono::duration<long double, std::nano>(timer.elapsed());
        timer.reset();

        static auto duration = std::chrono::seconds(10);

        if (usePath)
        {
			angle += static_cast<float>(d.count() / std::chrono::duration_cast<std::chrono::duration<long double, std::nano>>(duration).count());

            while (angle>1)
                angle = 0;

            float t = angle;

            player.play(t);
        }

        event.window()->repaint();
    }

//-----------------

    virtual void mousePressEvent(MouseEvent & event) override
    {
        switch (event.button())
        {
            case GLFW_MOUSE_BUTTON_LEFT:
                m_nav.panBegin(event.pos());
                event.accept();
                break;

            case GLFW_MOUSE_BUTTON_RIGHT:
                m_nav.rotateBegin(event.pos());
                event.accept();
                break;
        }
    }
    virtual void mouseMoveEvent(MouseEvent & event) override
    {
        switch (m_nav.mode())
        {
            case WorldInHandNavigation::PanInteraction:
                m_nav.panProcess(event.pos());
                event.accept();
                break;

            case WorldInHandNavigation::RotateInteraction:
                m_nav.rotateProcess(event.pos());
                event.accept();
        }
    }
    virtual void mouseReleaseEvent(MouseEvent & event) override
    {
        switch (event.button())
        {
            case GLFW_MOUSE_BUTTON_LEFT:
                m_nav.panEnd();
                event.accept();
                break;

            case GLFW_MOUSE_BUTTON_RIGHT:
                m_nav.rotateEnd();
                event.accept();
                break;
        }
    }

    void scrollEvent(ScrollEvent & event) override
    {
        if (WorldInHandNavigation::NoInteraction != m_nav.mode())
            return;

        m_nav.scaleAtMouse(event.pos(), -event.offset().y * 0.1f);
        event.accept();
    }

    virtual const float depthAt(const ivec2 & windowCoordinates)
    {
        return AbstractCoordinateProvider::depthAt(m_camera, GL_DEPTH_COMPONENT, windowCoordinates);
    }

    virtual const vec3 objAt(const ivec2 & windowCoordinates)
    {
        return unproject(m_camera, static_cast<GLenum>(GL_DEPTH_COMPONENT), windowCoordinates);
    }

    virtual const vec3 objAt(const ivec2 & windowCoordinates, const float depth)
    {
        return unproject(m_camera, depth, windowCoordinates);
    }

    virtual const glm::vec3 objAt(
        const ivec2 & windowCoordinates
    ,   const float depth
    ,   const mat4 & viewProjectionInverted)
    {
        return unproject(m_camera, viewProjectionInverted, depth, windowCoordinates);
    }

protected:

    ref_ptr<Program> m_sphere;

    ref_ptr<Icosahedron> m_icosahedron;
    ref_ptr<AdaptiveGrid> m_agrid;

    Timer timer;
    Camera m_camera;
    float angle;
    CameraPath path;
    CameraPathPlayer player;
    unsigned iterations;

    bool usePath;

    WorldInHandNavigation m_nav;
    AxisAlignedBoundingBox m_aabb;
};

/** This example shows ... .
*/
int main(int argc, char* argv[])
{
    ContextFormat format;
    format.setVersion(4, 0);
    format.setProfile(ContextFormat::CoreProfile);
    format.setDepthBufferSize(16);

    Window window;
    window.setEventHandler(new EventHandler());

    window.create(format, "Camera Path Example");
    window.context()->setSwapInterval(Context::VerticalSyncronization);
    window.show();

    return MainLoop::run();
}
<|endoftext|>