From d8c4c6e5ff9138285aed5b10429f5ea5ab64e151 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 7 Jan 2016 15:22:46 +0100 Subject: [PATCH 01/29] Created a primitive SoundSystem. Can play a sound with 'P' button. Using resourcemanager. Not using the created components yet. --- assets | 2 +- deps | 2 +- include/Engine/Sound/EPlaySound.h | 18 +++ include/Engine/Sound/Sound.h | 113 +++++++++++++++++++ include/Engine/Sound/SoundSystem.h | 62 ++++++++++ include/Game/Game.h | 7 ++ resources/Schema/Components.xsd | 2 + resources/Schema/Components/Listener.xml | 3 + resources/Schema/Components/Listener.xsd | 8 ++ resources/Schema/Components/SoundEmitter.xml | 7 ++ resources/Schema/Components/SoundEmitter.xsd | 22 ++++ resources/Schema/Types/Entity.xsd | 2 + src/Engine/CMakeLists.txt | 11 +- src/Engine/Sound/SoundSystem.cpp | 66 +++++++++++ src/Game/Game.cpp | 18 ++- 15 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 include/Engine/Sound/EPlaySound.h create mode 100644 include/Engine/Sound/Sound.h create mode 100644 include/Engine/Sound/SoundSystem.h create mode 100644 resources/Schema/Components/Listener.xml create mode 100644 resources/Schema/Components/Listener.xsd create mode 100644 resources/Schema/Components/SoundEmitter.xml create mode 100644 resources/Schema/Components/SoundEmitter.xsd create mode 100644 src/Engine/Sound/SoundSystem.cpp diff --git a/assets b/assets index 673d4a4e..6cbf2365 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 673d4a4e4c5a3f5bc9fedf82234e8f8751f63a44 +Subproject commit 6cbf2365d49e6280750ea3bcd0f9c271779e6f15 diff --git a/deps b/deps index 1ae6ba5b..293516d6 160000 --- a/deps +++ b/deps @@ -1 +1 @@ -Subproject commit 1ae6ba5b1297ed71b560aee211b9f0007ba52547 +Subproject commit 293516d671b97de26594fe979b7898b7e271e24c diff --git a/include/Engine/Sound/EPlaySound.h b/include/Engine/Sound/EPlaySound.h new file mode 100644 index 00000000..83fc4629 --- /dev/null +++ b/include/Engine/Sound/EPlaySound.h @@ -0,0 +1,18 @@ +#ifndef Events_PlaySound_h__ +#define Events_PlaySound_h__ + +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace Events +{ + + struct PlaySound : Event +{ + std::string FilePath; + EntityID emitter; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/Sound.h b/include/Engine/Sound/Sound.h new file mode 100644 index 00000000..ffb9b30e --- /dev/null +++ b/include/Engine/Sound/Sound.h @@ -0,0 +1,113 @@ +#ifndef Sound_h__ +#define Sound_h__ + +#include "Core/ResourceManager.h" + +class Sound : public Resource +{ + friend class ResourceManager; +public: + Sound(std::string path) { m_Buffer = LoadFile(path); } + ~Sound() { ClearBuffer(); } + ALuint Buffer() { return m_Buffer; } + std::string Path() { return m_Path; } + float Gain() { return m_Gain; } + void SetGain(float value) { m_Gain = value; } + void ClearBuffer() { alDeleteBuffers(1, &m_Buffer); m_BufferCache.clear(); }; + +private: + float m_Gain = 1; + ALuint m_Buffer; + std::string m_Path; + + // File info + char m_Type[4]; + unsigned long m_Size, m_ChunkSize; + short m_FormatType, m_Channels; + unsigned long m_SampleRate, m_AvgBytesPerSec; + short m_BytesPerSample, m_BitsPerSample; + unsigned int m_DataSize; + std::map m_BufferCache; + + ALuint LoadFile(std::string path) + { + if (m_BufferCache.find(path) != m_BufferCache.end()) { + return m_BufferCache[path]; + } + + //// Open file + FILE *fp = fopen(path.c_str(), "rb"); + if (!fp) { + printf("Failed to open file %s, no such file exists", path.c_str()); + return 0; + } + + //// CHECK FOR VALID WAVE-FILE + fread(m_Type, sizeof(char), 4, fp); + if (m_Type[0] != 'R' || m_Type[1] != 'I' || m_Type[2] != 'F' || m_Type[3] != 'F') { + printf("ERROR: No RIFF in WAVE-file"); + return 0; + } + + fread(&m_Size, 4 * sizeof(char), 1, fp); + fread(m_Type, sizeof(char), 4, fp); + if (m_Type[0] != 'W' || m_Type[1] != 'A' || m_Type[2] != 'V' || m_Type[3] != 'E') { + printf("ERROR: Not WAVE-file"); + return 0; + } + + fread(m_Type, sizeof(char), 4, fp); + if (m_Type[0] != 'f' || m_Type[1] != 'm' || m_Type[2] != 't' || m_Type[3] != ' ') { + printf("ERROR: No fmt in WAVE-file"); + return 0; + } + + //// READ THE DATA FROM WAVE-FILE + fread(&m_ChunkSize, 4 * sizeof(char), 1, fp); + fread(&m_FormatType, 2 * sizeof(char), 1, fp); + fread(&m_Channels, 2 * sizeof(char), 1, fp); + fread(&m_SampleRate, 4 * sizeof(char), 1, fp); + fread(&m_AvgBytesPerSec, 4 * sizeof(char), 1, fp); + fread(&m_BytesPerSample, 2 * sizeof(char), 1, fp); + fread(&m_BitsPerSample, 2 * sizeof(char), 1, fp); + + fread(m_Type, sizeof(char), 4, fp); + if (m_Type[0] != 'd' || m_Type[1] != 'a' || m_Type[2] != 't' || m_Type[3] != 'a') { + printf("ERROR: WAVE-file Missing data"); + return 0; + } + + fread(&m_DataSize, 4 * sizeof(char), 1, fp); + + unsigned char* buf = new unsigned char[m_DataSize]; + fread(buf, sizeof(char), m_DataSize, fp); + fclose(fp); + + //// Create buffer + ALuint format = 0; + if (m_BitsPerSample == 8) { + if (m_Channels == 1) { + format = AL_FORMAT_MONO8; + } else if (m_Channels == 2) { + format = AL_FORMAT_STEREO8; + } + } + if (m_BitsPerSample == 16) { + if (m_Channels == 1) { + format = AL_FORMAT_MONO16; + } else if (m_Channels == 2) { + format = AL_FORMAT_STEREO16; + } + } + + ALuint buffer; + alGenBuffers(1, &buffer); + alBufferData(buffer, format, buf, m_DataSize, m_SampleRate); + delete[] buf; + + m_BufferCache[path] = buffer; + return buffer; + } +}; + +#endif diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h new file mode 100644 index 00000000..0035a3bb --- /dev/null +++ b/include/Engine/Sound/SoundSystem.h @@ -0,0 +1,62 @@ +#ifndef SoundSystem_h__ +#define SoundSystem_h__ + +#include + +#include "glm/common.hpp" +#include "OpenAL/al.h" +#include "OpenAL/alc.h" + +#include "Core/World.h" +#include "Core/EventBroker.h" +#include "Sound/Sound.h" +#include "Sound/EPlaySound.h" + +struct Source +{ + Sound* SoundResource; + ALuint ALsource; +}; + +class SoundSystem +{ +public: + SoundSystem() { } + SoundSystem(EventBroker* eventBroker); + ~SoundSystem(); + void Update() { } // Update emitters +private: + // Private setters and getters for working with glm + void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; + glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; }; + void setListenerVel(glm::vec3 vel) { alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); }; + glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; }; + void setListenerOri(glm::vec3 ori) { alListener3f(AL_ORIENTATION, ori.x, ori.y, ori.z); }; + glm::vec3 listenerOri() { glm::vec3 ori; alGetListener3f(AL_ORIENTATION, &ori.x, &ori.y, &ori.z); return ori; }; + void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); }; + void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); }; + void setSourceOri(ALuint source, glm::vec3 ori) { ALfloat sori[3] = { ori.x, ori.y, ori.z }; alSourcefv(source, AL_ORIENTATION, sori); }; + + // Logic + World* m_World; + EventBroker* m_EventBroker; + + ALuint createSource(); + void playSound(Source source); + void stopSound(Source source); + void stopEmitter(EntityID emitter); + + // OpenAL system variables + ALCdevice* m_ALCdevice = nullptr; + ALCcontext* m_ALCcontext = nullptr; + + // Logic + std::unordered_map m_Sources; + + // Events + EventRelay m_EPlaySound; + bool OnPlaySound(const Events::PlaySound &e); + +}; + +#endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 33dc88a6..6b284c74 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -25,6 +25,10 @@ #include "Network/Server.h" #include "Network/Client.h" +// Sound +#include "Sound/SoundSystem.h" +#include "Sound/EPlaySound.h" + class Game { @@ -54,6 +58,9 @@ private: Network* m_ClientOrServer; bool m_IsClientOrServer = false; + // Sound + SoundSystem* m_SoundSystem; + EventRelay m_EInputCommand; bool debugOnInputCommand(const Events::InputCommand& e); diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index fd04fd39..a287431c 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -8,4 +8,6 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/Listener.xml b/resources/Schema/Components/Listener.xml new file mode 100644 index 00000000..7d1fac13 --- /dev/null +++ b/resources/Schema/Components/Listener.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Listener.xsd b/resources/Schema/Components/Listener.xsd new file mode 100644 index 00000000..5f71f11a --- /dev/null +++ b/resources/Schema/Components/Listener.xsd @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/SoundEmitter.xml b/resources/Schema/Components/SoundEmitter.xml new file mode 100644 index 00000000..a032dfbb --- /dev/null +++ b/resources/Schema/Components/SoundEmitter.xml @@ -0,0 +1,7 @@ + + 1.0 + 1.0 + 20.0 + 1.0 + 1.0 + \ No newline at end of file diff --git a/resources/Schema/Components/SoundEmitter.xsd b/resources/Schema/Components/SoundEmitter.xsd new file mode 100644 index 00000000..6bebcac5 --- /dev/null +++ b/resources/Schema/Components/SoundEmitter.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + The "volume" of the emitter. A value betweeen 0-1 + + The pitch of the emitter. A value betweeen 0-1 + + The distance where there will no longer be any attenuation. + + The rolloff rate of the source. + + The distance that the source will be the loudest. + + + + \ No newline at end of file diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 92f7dc31..67612935 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -15,6 +15,8 @@ + + diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index 5d43db8b..40bc9cb0 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -9,8 +9,8 @@ find_package(ZLIB REQUIRED) find_package(PNG REQUIRED) find_package(Xerces REQUIRED) # Because FindOpenAL is retarded -#set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/AL") -#find_package(OpenAL REQUIRED) +set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/deps/include/OpenAL") +find_package(OpenAL REQUIRED) if(UNIX) find_package(X11 REQUIRED) endif() @@ -52,6 +52,12 @@ file(GLOB SOURCE_FILES_Network ) source_group(Network FILES ${SOURCE_FILES_Network}) +file(GLOB SOURCE_FILES_Sound + "${INCLUDE_PATH}/Sound/*.h" + "Sound/*.cpp" +) +source_group(Sound FILES ${SOURCE_FILES_Sound}) + file(GLOB SOURCE_FILES_Rendering "${INCLUDE_PATH}/Rendering/*.h" "Rendering/*.cpp" @@ -86,6 +92,7 @@ set(SOURCE_FILES ${SOURCE_FILES_Core_Util} ${SOURCE_FILES_Input} ${SOURCE_FILES_Network} + ${SOURCE_FILES_Sound} ${SOURCE_FILES_GUI} ${SOURCE_FILES_Rendering} ${SOURCE_FILES_Rendering_Util} diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp new file mode 100644 index 00000000..965f97a4 --- /dev/null +++ b/src/Engine/Sound/SoundSystem.cpp @@ -0,0 +1,66 @@ +#include "Sound/SoundSystem.h" + +SoundSystem::SoundSystem(EventBroker* eventBroker) +{ + m_EventBroker = eventBroker; + // Initialize OpenAL + m_ALCdevice = alcOpenDevice(nullptr); + if (m_ALCdevice != nullptr) { + m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); + alcMakeContextCurrent(m_ALCcontext); + } else { + LOG_ERROR("OpenAL failed to initialize."); + } + + alSpeedOfSound(340.29f); // Speed of sound + alDistanceModel(AL_INVERSE_DISTANCE); + + EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); + //m_EPlaySound = decltype(m_EPlaySound)(std::bind(&SoundSystem::OnPlaySound, this, std::placeholders::_1)); + //m_EventBroker->Subscribe(m_EPlaySound); +} + +SoundSystem::~SoundSystem() +{ + alcDestroyContext(m_ALCcontext); + alcCloseDevice(m_ALCdevice); + delete m_ALCcontext; + delete m_ALCdevice; +} + +ALuint SoundSystem::createSource() +{ + ALuint source; + alGenSources((ALuint)1, &source); + alSourcei(source, AL_REFERENCE_DISTANCE, 1.0); + alSourcei(source, AL_MAX_DISTANCE, FLT_MAX); + return source; +} + +void SoundSystem::playSound(Source source) +{ + alSourcei(source.ALsource, AL_BUFFER, source.SoundResource->Buffer()); + alSourcePlay(source.ALsource); +} + +void SoundSystem::stopSound(Source source) +{ } + +void SoundSystem::stopEmitter(EntityID emitter) +{ } + +bool SoundSystem::OnPlaySound(const Events::PlaySound & e) +{ + Sound *sound = ResourceManager::Load(e.FilePath); + if (sound == nullptr) { + return false; + } + ALuint source = createSource(); + Source sauce; + sauce.ALsource = source; + sauce.SoundResource = sound; + playSound(sauce); + LOG_INFO("You are playing an imaginary sound now! :D"); + return false; +} + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 033db642..66ab6fae 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -5,6 +5,7 @@ Game::Game(int argc, char* argv[]) { ResourceManager::RegisterType("ConfigFile"); + ResourceManager::RegisterType("Sound"); ResourceManager::RegisterType("Model"); ResourceManager::RegisterType("Texture"); ResourceManager::RegisterType("EntityXMLFile"); @@ -63,6 +64,9 @@ Game::Game(int argc, char* argv[]) //boost::thread workerThread(&Game::networkFunction, this); networkFunction(); } + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand); + m_SoundSystem = new SoundSystem(m_EventBroker); + m_LastTime = glfwGetTime(); } @@ -103,9 +107,11 @@ void Game::Tick() // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); + debugTick(dt); m_Renderer->Update(dt); m_EventBroker->Process(); - + m_EventBroker->Process(); + m_SoundSystem->Update(); m_RenderQueueFactory->Update(m_World); GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); @@ -114,6 +120,16 @@ void Game::Tick() m_EventBroker->Clear(); } +bool Game::debugOnInputCommand(const Events::InputCommand & e) +{ + if (e.Command == "PlaySound" && e.Value > 0) { + Events::PlaySound e; + e.FilePath = "Audio/crosscounter.wav"; + m_EventBroker->Publish(e); + } + return true; +} + void Game::debugTick(double dt) { m_EventBroker->Process(); From 2838446072fd3464718a342e0768c75ac7050416 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 7 Jan 2016 16:03:33 +0100 Subject: [PATCH 02/29] In lack of camera entity I created a Listener cube to test 3D sound. Works fine. Updates listener pos each tick. --- include/Engine/Sound/SoundSystem.h | 4 ++-- src/Engine/Sound/SoundSystem.cpp | 21 +++++++++++++++------ src/Game/Game.cpp | 9 ++++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h index 0035a3bb..0555feb4 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundSystem.h @@ -22,9 +22,9 @@ class SoundSystem { public: SoundSystem() { } - SoundSystem(EventBroker* eventBroker); + SoundSystem(World* world, EventBroker* eventBroker); ~SoundSystem(); - void Update() { } // Update emitters + void Update(); // Update emitters private: // Private setters and getters for working with glm void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index 965f97a4..b9736096 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -1,8 +1,9 @@ #include "Sound/SoundSystem.h" -SoundSystem::SoundSystem(EventBroker* eventBroker) +SoundSystem::SoundSystem(World* world, EventBroker* eventBroker) { m_EventBroker = eventBroker; + m_World = world; // Initialize OpenAL m_ALCdevice = alcOpenDevice(nullptr); if (m_ALCdevice != nullptr) { @@ -16,20 +17,29 @@ SoundSystem::SoundSystem(EventBroker* eventBroker) alDistanceModel(AL_INVERSE_DISTANCE); EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); - //m_EPlaySound = decltype(m_EPlaySound)(std::bind(&SoundSystem::OnPlaySound, this, std::placeholders::_1)); - //m_EventBroker->Subscribe(m_EPlaySound); } SoundSystem::~SoundSystem() -{ +{ alcDestroyContext(m_ALCcontext); alcCloseDevice(m_ALCdevice); delete m_ALCcontext; delete m_ALCdevice; } +void SoundSystem::Update() +{ + // Should only be one listener. + auto listenerComponents = m_World->GetComponents("Listener"); + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + EntityID listener = (*it).EntityID; + auto transform = m_World->GetComponent(listener, "Transform"); + setListenerPos(transform["Position"]); + } +} + ALuint SoundSystem::createSource() -{ +{ ALuint source; alGenSources((ALuint)1, &source); alSourcei(source, AL_REFERENCE_DISTANCE, 1.0); @@ -60,7 +70,6 @@ bool SoundSystem::OnPlaySound(const Events::PlaySound & e) sauce.ALsource = source; sauce.SoundResource = sound; playSound(sauce); - LOG_INFO("You are playing an imaginary sound now! :D"); return false; } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 66ab6fae..1863fa38 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -65,7 +65,14 @@ Game::Game(int argc, char* argv[]) networkFunction(); } EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand); - m_SoundSystem = new SoundSystem(m_EventBroker); + m_SoundSystem = new SoundSystem(m_World, m_EventBroker); + + auto soundListenerCube = m_World->CreateEntity(); + m_World->AttachComponent(soundListenerCube, "Listener"); + m_World->AttachComponent(soundListenerCube, "Transform"); + auto model = m_World->AttachComponent(soundListenerCube, "Model"); + model["Resource"] = "Models/Core/UnitCube.obj"; + model["Color"] = glm::vec4(1, 0, 0, 1); m_LastTime = glfwGetTime(); } From da6e50dc7eb17671664033b871e58fc57c657ba6 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 7 Jan 2016 17:04:43 +0100 Subject: [PATCH 03/29] Correct orientation. Need to clean this up. --- include/Engine/Sound/SoundSystem.h | 17 ++++++++++++++++- src/Engine/Sound/SoundSystem.cpp | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h index 0555feb4..de31e216 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundSystem.h @@ -4,6 +4,7 @@ #include #include "glm/common.hpp" +#include "glm/gtx/rotate_vector.hpp" #include "OpenAL/al.h" #include "OpenAL/alc.h" @@ -31,7 +32,21 @@ private: glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; }; void setListenerVel(glm::vec3 vel) { alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); }; glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; }; - void setListenerOri(glm::vec3 ori) { alListener3f(AL_ORIENTATION, ori.x, ori.y, ori.z); }; + void setListenerOri(glm::vec3 ori) + { + glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); + forward = glm::rotateX(forward, ori.x); + forward = glm::rotateY(forward, ori.y); + forward = glm::rotateZ(forward, ori.z); + glm::normalize(forward); + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); + up = glm::rotateX(up, ori.x); + up = glm::rotateY(up, ori.y); + up = glm::rotateZ(up, ori.z); + glm::normalize(up); + ALfloat lori[6] = { forward.x, forward.y, forward.z , up.x, up.y, up.z }; + alListenerfv(AL_ORIENTATION, lori); + }; glm::vec3 listenerOri() { glm::vec3 ori; alGetListener3f(AL_ORIENTATION, &ori.x, &ori.y, &ori.z); return ori; }; void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); }; void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); }; diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index b9736096..64312fa8 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -35,6 +35,7 @@ void SoundSystem::Update() EntityID listener = (*it).EntityID; auto transform = m_World->GetComponent(listener, "Transform"); setListenerPos(transform["Position"]); + setListenerOri(transform["Orientation"]); } } From 3cce9f80751d5bc2da692d9570e511e0f92f5967 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 8 Jan 2016 15:29:20 +0100 Subject: [PATCH 04/29] Using absolute transform --- include/Engine/Sound/SoundSystem.h | 28 ++--- resources/Schema/Components/SoundEmitter.xml | 1 + resources/Schema/Components/SoundEmitter.xsd | 1 + src/Engine/Sound/SoundSystem.cpp | 116 ++++++++++++++++--- 4 files changed, 111 insertions(+), 35 deletions(-) diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h index de31e216..5a8225ef 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundSystem.h @@ -10,6 +10,7 @@ #include "Core/World.h" #include "Core/EventBroker.h" +#include "Rendering/RenderQueueFactory.h" // Absolute transform #include "Sound/Sound.h" #include "Sound/EPlaySound.h" @@ -27,35 +28,27 @@ public: ~SoundSystem(); void Update(); // Update emitters private: - // Private setters and getters for working with glm + // Help functions for working with OpenaAL void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; glm::vec3 listnerPos() { glm::vec3 pos; alGetListener3f(AL_POSITION, &pos.x, &pos.y, &pos.z); return pos; }; void setListenerVel(glm::vec3 vel) { alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); }; glm::vec3 listenerVel() { glm::vec3 vel; alGetListener3f(AL_VELOCITY, &vel.x, &vel.y, &vel.z); return vel; }; - void setListenerOri(glm::vec3 ori) - { - glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); - forward = glm::rotateX(forward, ori.x); - forward = glm::rotateY(forward, ori.y); - forward = glm::rotateZ(forward, ori.z); - glm::normalize(forward); - glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); - up = glm::rotateX(up, ori.x); - up = glm::rotateY(up, ori.y); - up = glm::rotateZ(up, ori.z); - glm::normalize(up); - ALfloat lori[6] = { forward.x, forward.y, forward.z , up.x, up.y, up.z }; - alListenerfv(AL_ORIENTATION, lori); - }; + void setListenerOri(glm::vec3 ori); glm::vec3 listenerOri() { glm::vec3 ori; alGetListener3f(AL_ORIENTATION, &ori.x, &ori.y, &ori.z); return ori; }; void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); }; void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); }; - void setSourceOri(ALuint source, glm::vec3 ori) { ALfloat sori[3] = { ori.x, ori.y, ori.z }; alSourcefv(source, AL_ORIENTATION, sori); }; + + bool isPlaying(ALuint source); // Logic World* m_World; EventBroker* m_EventBroker; + void initOpenAL(); + void updateEmitters(); + void updateListener(); + void deleteInactiveEmitters(); + void addNewEmitters(); ALuint createSource(); void playSound(Source source); void stopSound(Source source); @@ -71,7 +64,6 @@ private: // Events EventRelay m_EPlaySound; bool OnPlaySound(const Events::PlaySound &e); - }; #endif \ No newline at end of file diff --git a/resources/Schema/Components/SoundEmitter.xml b/resources/Schema/Components/SoundEmitter.xml index a032dfbb..cbcfc440 100644 --- a/resources/Schema/Components/SoundEmitter.xml +++ b/resources/Schema/Components/SoundEmitter.xml @@ -1,4 +1,5 @@ + Audio/crosscounter.wav 1.0 1.0 20.0 diff --git a/resources/Schema/Components/SoundEmitter.xsd b/resources/Schema/Components/SoundEmitter.xsd index 6bebcac5..31c18ce9 100644 --- a/resources/Schema/Components/SoundEmitter.xsd +++ b/resources/Schema/Components/SoundEmitter.xsd @@ -6,6 +6,7 @@ + The "volume" of the emitter. A value betweeen 0-1 diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index 64312fa8..fd379d50 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -4,6 +4,17 @@ SoundSystem::SoundSystem(World* world, EventBroker* eventBroker) { m_EventBroker = eventBroker; m_World = world; + + initOpenAL(); + + alSpeedOfSound(340.29f); // Speed of sound + alDistanceModel(AL_INVERSE_DISTANCE); + + EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); +} + +void SoundSystem::initOpenAL() +{ // Initialize OpenAL m_ALCdevice = alcOpenDevice(nullptr); if (m_ALCdevice != nullptr) { @@ -12,11 +23,6 @@ SoundSystem::SoundSystem(World* world, EventBroker* eventBroker) } else { LOG_ERROR("OpenAL failed to initialize."); } - - alSpeedOfSound(340.29f); // Speed of sound - alDistanceModel(AL_INVERSE_DISTANCE); - - EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); } SoundSystem::~SoundSystem() @@ -28,14 +34,67 @@ SoundSystem::~SoundSystem() } void SoundSystem::Update() +{ + //deleteInactiveEmitters(); // Not tested + addNewEmitters(); + updateEmitters(); + updateListener(); +} + +void SoundSystem::deleteInactiveEmitters() +{ + auto emitterComponents = m_World->GetComponents("SoundEmitter"); + for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { + EntityID emitter = (*it).EntityID; + if (isPlaying(m_Sources[emitter].ALsource)) { // The sound is still playing, do not remove + continue; + } + alDeleteBuffers(1, &m_Sources[emitter].ALsource); + delete m_Sources[emitter].SoundResource; + m_Sources.erase(emitter); + } +} + +void SoundSystem::addNewEmitters() +{ + auto emitterComponents = m_World->GetComponents("SoundEmitter"); + for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { + EntityID emitter = (*it).EntityID; + std::unordered_map::iterator i; + i = m_Sources.find(emitter); + if (i == m_Sources.end()) { // Did not exist, add it + Source source; + source.ALsource = createSource(); + source.SoundResource = ResourceManager::Load((std::string)(*it)["FilePath"]); + m_Sources[emitter] = source; + } + } +} + +void SoundSystem::updateEmitters() +{ + auto emitterComponents = m_World->GetComponents("SoundEmitter"); + for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { + EntityID emitter = (*it).EntityID; + std::unordered_map::iterator i; + i = m_Sources.find(emitter); + if (i != m_Sources.end()) { + setSourcePos(m_Sources[emitter].ALsource, RenderQueueFactory::AbsolutePosition(m_World, emitter)); + } + // No orientation, emitts in all directions + // Velocity for doppler effect + } +} + +void SoundSystem::updateListener() { // Should only be one listener. auto listenerComponents = m_World->GetComponents("Listener"); for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { EntityID listener = (*it).EntityID; - auto transform = m_World->GetComponent(listener, "Transform"); - setListenerPos(transform["Position"]); - setListenerOri(transform["Orientation"]); + setListenerPos(RenderQueueFactory::AbsolutePosition(m_World, listener)); + setListenerOri(glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, listener))); + // Velocity for doppler effect } } @@ -62,15 +121,38 @@ void SoundSystem::stopEmitter(EntityID emitter) bool SoundSystem::OnPlaySound(const Events::PlaySound & e) { - Sound *sound = ResourceManager::Load(e.FilePath); - if (sound == nullptr) { - return false; - } - ALuint source = createSource(); - Source sauce; - sauce.ALsource = source; - sauce.SoundResource = sound; - playSound(sauce); + //Sound *sound = ResourceManager::Load(e.FilePath); + //if (sound == nullptr) { + // return false; + //} + //ALuint source = createSource(); + //Source sauce; + //sauce.ALsource = source; + //sauce.SoundResource = sound; + //playSound(sauce); return false; } +void SoundSystem::setListenerOri(glm::vec3 ori) +{ + glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); + forward = glm::rotateX(forward, ori.x); + forward = glm::rotateY(forward, ori.y); + forward = glm::rotateZ(forward, ori.z); + glm::normalize(forward); + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); + up = glm::rotateX(up, ori.x); + up = glm::rotateY(up, ori.y); + up = glm::rotateZ(up, ori.z); + glm::normalize(up); + ALfloat lOri[6] = { forward.x, forward.y, forward.z, up.x, up.y, up.z }; + alListenerfv(AL_ORIENTATION, lOri); +} + +bool SoundSystem::isPlaying(ALuint source) +{ + ALenum state; + alGetSourcei(source, AL_SOURCE_STATE, &state); + return (state == AL_PLAYING); +} + From f80ad1377b88b9d3f88a76f1c78b2ac99b04ab7b Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 11 Jan 2016 17:52:27 +0100 Subject: [PATCH 05/29] Making use of Doppler effect. Added a bunch of events: Pause, stop, continue, variations of play. --- README.md | 3 +- include/Engine/Sound/EContinueSound.h | 17 ++ include/Engine/Sound/EPauseSound.h | 17 ++ include/Engine/Sound/EPlaySound.h | 2 +- include/Engine/Sound/EPlaySoundOnEntity.h | 21 +++ include/Engine/Sound/EPlaySoundOnPosition.h | 26 +++ include/Engine/Sound/EStopSound.h | 17 ++ include/Engine/Sound/SoundSystem.h | 37 ++-- include/Game/Game.h | 4 +- resources/Schema/Components/SoundEmitter.xml | 1 + resources/Schema/Components/SoundEmitter.xsd | 12 +- src/Engine/Sound/SoundSystem.cpp | 179 +++++++++++++++---- src/Game/Game.cpp | 14 +- 13 files changed, 296 insertions(+), 54 deletions(-) create mode 100644 include/Engine/Sound/EContinueSound.h create mode 100644 include/Engine/Sound/EPauseSound.h create mode 100644 include/Engine/Sound/EPlaySoundOnEntity.h create mode 100644 include/Engine/Sound/EPlaySoundOnPosition.h create mode 100644 include/Engine/Sound/EStopSound.h diff --git a/README.md b/README.md index 7c5f2268..7a488299 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo | **[zlib](http://www.zlib.net)** | 1.28 | [zlib License](http://www.zlib.net/zlib_license.html) | | **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) | | **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) | -| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) | +| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) +| **[OpenAL](https://www.openal.org/)** | 1.1 | [OpenAL License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) | #### External libraries Libraries that are too big to be bundled with the project. diff --git a/include/Engine/Sound/EContinueSound.h b/include/Engine/Sound/EContinueSound.h new file mode 100644 index 00000000..2c624b0b --- /dev/null +++ b/include/Engine/Sound/EContinueSound.h @@ -0,0 +1,17 @@ +#ifndef Events_ContinueSound_h__ +#define Events_ContinueSound_h__ + +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace Events +{ + +struct ContinueSound : Event +{ + EntityID EmitterID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/EPauseSound.h b/include/Engine/Sound/EPauseSound.h new file mode 100644 index 00000000..f9e2e6f0 --- /dev/null +++ b/include/Engine/Sound/EPauseSound.h @@ -0,0 +1,17 @@ +#ifndef Events_PauseSound_h__ +#define Events_PauseSound_h__ + +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace Events +{ + +struct PauseSound : Event +{ + EntityID EmitterID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/EPlaySound.h b/include/Engine/Sound/EPlaySound.h index 83fc4629..9c9eab0a 100644 --- a/include/Engine/Sound/EPlaySound.h +++ b/include/Engine/Sound/EPlaySound.h @@ -10,7 +10,7 @@ namespace Events struct PlaySound : Event { std::string FilePath; - EntityID emitter; + EntityID EmitterID; }; } diff --git a/include/Engine/Sound/EPlaySoundOnEntity.h b/include/Engine/Sound/EPlaySoundOnEntity.h new file mode 100644 index 00000000..39dea432 --- /dev/null +++ b/include/Engine/Sound/EPlaySoundOnEntity.h @@ -0,0 +1,21 @@ +#ifndef Events_PlaySoundOnEntity_h__ +#define Events_PlaySoundOnEntity_h__ + +#include +#include "Core/Entity.h" +#include "Core/Event.h" + +namespace Events +{ + +// Plays a sound on an entity with a SoundEmitter component attached. +// Sound behavior is thereby specified in the SoundEmitter component. +struct PlaySoundOnEntity : public Event +{ + EntityID EmitterID = 0; + std::string FilePath = ""; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/EPlaySoundOnPosition.h b/include/Engine/Sound/EPlaySoundOnPosition.h new file mode 100644 index 00000000..6a6b4d13 --- /dev/null +++ b/include/Engine/Sound/EPlaySoundOnPosition.h @@ -0,0 +1,26 @@ +#ifndef Events_PlaySoundOnPosition_h__ +#define Events_PlaySoundOnPosition_h__ + +#include +#include +#include "Core/Event.h" + +namespace Events +{ + +// Plays a sound on a given position +struct PlaySoundOnPosition : public Event +{ + glm::vec3 Position = glm::vec3(0); + std::string FilePath = ""; + float Gain = 1; + float Pitch = 1; + bool Loop = false; + float MaxDistance = 20; + float RollOffFactor = 1; + float ReferenceDistance = 1; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/EStopSound.h b/include/Engine/Sound/EStopSound.h new file mode 100644 index 00000000..b6cd37b8 --- /dev/null +++ b/include/Engine/Sound/EStopSound.h @@ -0,0 +1,17 @@ +#ifndef Events_StopSound_h__ +#define Events_StopSound_h__ + +#include "Core/EventBroker.h" +#include "Core/Entity.h" + +namespace Events +{ + +struct StopSound : Event +{ + EntityID EmitterID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundSystem.h index 5a8225ef..5100a54b 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundSystem.h @@ -4,7 +4,7 @@ #include #include "glm/common.hpp" -#include "glm/gtx/rotate_vector.hpp" +#include "glm/gtx/rotate_vector.hpp" // Calculate Up vector #include "OpenAL/al.h" #include "OpenAL/alc.h" @@ -13,9 +13,16 @@ #include "Rendering/RenderQueueFactory.h" // Absolute transform #include "Sound/Sound.h" #include "Sound/EPlaySound.h" +#include "Sound/EPlaySoundOnEntity.h" +#include "Sound/EPlaySoundOnPosition.h" +#include "Sound/EPauseSound.h" +#include "Sound/EStopSound.h" +#include "Sound/EContinueSound.h" + struct Source { + Source() { } Sound* SoundResource; ALuint ALsource; }; @@ -38,32 +45,42 @@ private: void setSourcePos(ALuint source, glm::vec3 pos) { ALfloat spos[3] = { pos.x, pos.y, pos.z }; alSourcefv(source, AL_POSITION, spos); }; void setSourceVel(ALuint source, glm::vec3 vel) { ALfloat svel[3] = { vel.x, vel.y, vel.z }; alSourcefv(source, AL_VELOCITY, svel); }; - bool isPlaying(ALuint source); - // Logic - World* m_World; - EventBroker* m_EventBroker; - void initOpenAL(); void updateEmitters(); void updateListener(); void deleteInactiveEmitters(); void addNewEmitters(); - ALuint createSource(); - void playSound(Source source); - void stopSound(Source source); + Source* createSource(std::string filePath); + void playSound(Source* source); + void stopSound(Source* source); void stopEmitter(EntityID emitter); + void stopEmitters(); + bool isPlaying(ALuint source); + void setSoundProperties(ALuint source, float gain, float pitch, bool loop, float maxDistance, float rollOffFactor, float referenceDistance); // OpenAL system variables ALCdevice* m_ALCdevice = nullptr; ALCcontext* m_ALCcontext = nullptr; // Logic - std::unordered_map m_Sources; + World* m_World; + EventBroker* m_EventBroker; + std::unordered_map m_Sources; // Events EventRelay m_EPlaySound; bool OnPlaySound(const Events::PlaySound &e); + EventRelay m_EPlaySoundOnEntity; + bool OnPlaySoundOnEntity(const Events::PlaySoundOnEntity &e); + EventRelay m_EPlaySoundOnPosition; + bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e); + EventRelay m_EPauseSound; + bool OnPauseSound(const Events::PauseSound &e); + EventRelay m_EStopSound; + bool OnStopSound(const Events::StopSound &e); + EventRelay m_EContinueSound; + bool OnContinueSound(const Events::ContinueSound &e); }; #endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 6b284c74..a4264840 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -27,7 +27,9 @@ // Sound #include "Sound/SoundSystem.h" -#include "Sound/EPlaySound.h" +//#include "Sound/EPlaySound.h" +//#include "Sound/EPlaySoundOnEntity.h" +//#include "Sound/EPlaySoundOnPosition.h" class Game diff --git a/resources/Schema/Components/SoundEmitter.xml b/resources/Schema/Components/SoundEmitter.xml index cbcfc440..871919f1 100644 --- a/resources/Schema/Components/SoundEmitter.xml +++ b/resources/Schema/Components/SoundEmitter.xml @@ -2,6 +2,7 @@ Audio/crosscounter.wav 1.0 1.0 + false 20.0 1.0 1.0 diff --git a/resources/Schema/Components/SoundEmitter.xsd b/resources/Schema/Components/SoundEmitter.xsd index 31c18ce9..c734e6ba 100644 --- a/resources/Schema/Components/SoundEmitter.xsd +++ b/resources/Schema/Components/SoundEmitter.xsd @@ -7,15 +7,17 @@ - + The "volume" of the emitter. A value betweeen 0-1 - + The pitch of the emitter. A value betweeen 0-1 - + + If the sound should loop or not. + The distance where there will no longer be any attenuation. - + The rolloff rate of the source. - + The distance that the source will be the loudest. diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index fd379d50..582ca2db 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -8,9 +8,15 @@ SoundSystem::SoundSystem(World* world, EventBroker* eventBroker) initOpenAL(); alSpeedOfSound(340.29f); // Speed of sound - alDistanceModel(AL_INVERSE_DISTANCE); + alDistanceModel(AL_LINEAR_DISTANCE); + alDopplerFactor(1); EVENT_SUBSCRIBE_MEMBER(m_EPlaySound, &SoundSystem::OnPlaySound); + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundSystem::OnPlaySoundOnEntity); + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundSystem::OnPlaySoundOnPosition); + EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundSystem::OnStopSound); + EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundSystem::OnPauseSound); + EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundSystem::OnContinueSound); } void SoundSystem::initOpenAL() @@ -27,12 +33,31 @@ void SoundSystem::initOpenAL() SoundSystem::~SoundSystem() { + stopEmitters(); // Stopps emitters + deleteInactiveEmitters(); // Deletes stopped emitters + + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + m_World->DeleteEntity((*it).first); + } + m_Sources.clear(); + alcDestroyContext(m_ALCcontext); alcCloseDevice(m_ALCdevice); delete m_ALCcontext; delete m_ALCdevice; } +void SoundSystem::stopEmitters() +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + if (isPlaying((*it).second->ALsource)) { + stopSound((*it).second); + } + } +} + void SoundSystem::Update() { //deleteInactiveEmitters(); // Not tested @@ -44,14 +69,19 @@ void SoundSystem::Update() void SoundSystem::deleteInactiveEmitters() { auto emitterComponents = m_World->GetComponents("SoundEmitter"); - for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { + for (auto it = emitterComponents->begin(); it != emitterComponents->end();) { EntityID emitter = (*it).EntityID; - if (isPlaying(m_Sources[emitter].ALsource)) { // The sound is still playing, do not remove + if (isPlaying(m_Sources[emitter]->ALsource)) { // The sound is still playing, do not remove + it++; continue; } - alDeleteBuffers(1, &m_Sources[emitter].ALsource); - delete m_Sources[emitter].SoundResource; - m_Sources.erase(emitter); + else { + alDeleteBuffers(1, &m_Sources[emitter]->ALsource); + alDeleteSources(1, &m_Sources[emitter]->ALsource); + //delete m_Sources[emitter]->SoundResource; + m_Sources.erase(emitter); + m_World->DeleteEntity(emitter); + } } } @@ -60,12 +90,19 @@ void SoundSystem::addNewEmitters() auto emitterComponents = m_World->GetComponents("SoundEmitter"); for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { EntityID emitter = (*it).EntityID; - std::unordered_map::iterator i; + std::unordered_map::iterator i; i = m_Sources.find(emitter); if (i == m_Sources.end()) { // Did not exist, add it - Source source; - source.ALsource = createSource(); - source.SoundResource = ResourceManager::Load((std::string)(*it)["FilePath"]); + Source* source = createSource((std::string)(*it)["FilePath"]); + setSoundProperties ( + source->ALsource, + (float)(double)(*it)["Gain"], + (float)(double)(*it)["Pitch"], + (bool)(*it)["Loop"], + (float)(double)(*it)["MaxDistance"], + (float)(double)(*it)["RollOffFactor"], + (float)(double)(*it)["ReferenceDistance"] + ); m_Sources[emitter] = source; } } @@ -76,13 +113,26 @@ void SoundSystem::updateEmitters() auto emitterComponents = m_World->GetComponents("SoundEmitter"); for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { EntityID emitter = (*it).EntityID; - std::unordered_map::iterator i; + std::unordered_map::iterator i; i = m_Sources.find(emitter); if (i != m_Sources.end()) { - setSourcePos(m_Sources[emitter].ALsource, RenderQueueFactory::AbsolutePosition(m_World, emitter)); + glm::vec3 previousPos; + alGetSource3f(m_Sources[emitter]->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos + glm::vec3 nextPos = RenderQueueFactory::AbsolutePosition(m_World, emitter); // Get next pos + glm::vec3 velocity = nextPos - previousPos; // Calculate velocity + setSourcePos(m_Sources[emitter]->ALsource, nextPos); // Set next pos + setSourceVel(m_Sources[emitter]->ALsource, velocity); // Set velocity + setSoundProperties( + m_Sources[emitter]->ALsource, + (float)(double)(*it)["Gain"], + (float)(double)(*it)["Pitch"], + (bool)(*it)["Loop"], + (float)(double)(*it)["MaxDistance"], + (float)(double)(*it)["RollOffFactor"], + (float)(double)(*it)["ReferenceDistance"] + ); } // No orientation, emitts in all directions - // Velocity for doppler effect } } @@ -92,47 +142,97 @@ void SoundSystem::updateListener() auto listenerComponents = m_World->GetComponents("Listener"); for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { EntityID listener = (*it).EntityID; - setListenerPos(RenderQueueFactory::AbsolutePosition(m_World, listener)); + glm::vec3 previousPos; + alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos + glm::vec3 nextPos = RenderQueueFactory::AbsolutePosition(m_World, listener); // Get next (current) pos + glm::vec3 velocity = nextPos - previousPos; // Calculate velocity + setListenerPos(nextPos); + setListenerVel(velocity); setListenerOri(glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, listener))); - // Velocity for doppler effect } } -ALuint SoundSystem::createSource() +Source* SoundSystem::createSource(std::string filePath) { - ALuint source; - alGenSources((ALuint)1, &source); - alSourcei(source, AL_REFERENCE_DISTANCE, 1.0); - alSourcei(source, AL_MAX_DISTANCE, FLT_MAX); + ALuint alSource; + alGenSources((ALuint)1, &alSource); + alSourcei(alSource, AL_REFERENCE_DISTANCE, 1.0); + alSourcei(alSource, AL_MAX_DISTANCE, FLT_MAX); + Source* source = new Source(); + source->ALsource = alSource; + source->SoundResource = ResourceManager::Load(filePath); return source; } -void SoundSystem::playSound(Source source) +void SoundSystem::playSound(Source* source) { - alSourcei(source.ALsource, AL_BUFFER, source.SoundResource->Buffer()); - alSourcePlay(source.ALsource); + alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); + alSourcePlay(source->ALsource); } -void SoundSystem::stopSound(Source source) -{ } +void SoundSystem::stopSound(Source* source) +{ + alSourceStop(source->ALsource); +} void SoundSystem::stopEmitter(EntityID emitter) -{ } +{ + +} bool SoundSystem::OnPlaySound(const Events::PlaySound & e) { - //Sound *sound = ResourceManager::Load(e.FilePath); - //if (sound == nullptr) { - // return false; - //} - //ALuint source = createSource(); - //Source sauce; - //sauce.ALsource = source; - //sauce.SoundResource = sound; - //playSound(sauce); + Source* sauce = createSource(e.FilePath); + playSound(sauce); return false; } +bool SoundSystem::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) +{ + Source* source = createSource(e.FilePath); + m_Sources[e.emitterID] = source; + playSound(source); + return false; +} + +bool SoundSystem::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) +{ + Source* source = createSource(e.FilePath); + auto emitterID = m_World->CreateEntity(); + auto transform = m_World->AttachComponent(emitterID, "Transform"); + (glm::vec3&)transform["Position"] = e.Position; + auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); + (float&)(double)emitter["Gain"] = e.Gain; + (float&)(double)emitter["Pitch"] = e.Pitch; + (bool&)emitter["Loop"] = e.Loop; + (float&)(double)emitter["MaxDistance"] = e.MaxDistance; + (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; + (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; + auto model = m_World->AttachComponent(emitterID, "Model"); + (std::string&)model["Resource"] = "Models/Core/UnitCube.obj"; + m_Sources[emitterID] = source; + playSound(source); + return false; +} + +bool SoundSystem::OnPauseSound(const Events::PauseSound & e) +{ + alSourcePause(m_Sources[e.EmitterID]->ALsource); + return false; +} + +bool SoundSystem::OnStopSound(const Events::StopSound & e) +{ + alSourceStop(m_Sources[e.EmitterID]->ALsource); + return false; +} + +bool SoundSystem::OnContinueSound(const Events::ContinueSound & e) +{ + alSourcePlay(m_Sources[e.EmitterID]->ALsource); + return true; +} + void SoundSystem::setListenerOri(glm::vec3 ori) { glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); @@ -156,3 +256,12 @@ bool SoundSystem::isPlaying(ALuint source) return (state == AL_PLAYING); } +void SoundSystem::setSoundProperties(ALuint source, float gain, float pitch, bool loop, float maxDistance, float rollOffFactor, float referenceDistance) +{ + alSourcef(source, AL_GAIN, gain); + alSourcef(source, AL_PITCH, pitch); + alSourcei(source, AL_LOOPING, (int)loop); // YOLO + alSourcef(source, AL_MAX_DISTANCE, maxDistance); + alSourcef(source, AL_ROLLOFF_FACTOR, rollOffFactor); + alSourcef(source, AL_REFERENCE_DISTANCE, referenceDistance); +} diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 1863fa38..86682591 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -130,8 +130,20 @@ void Game::Tick() bool Game::debugOnInputCommand(const Events::InputCommand & e) { if (e.Command == "PlaySound" && e.Value > 0) { - Events::PlaySound e; + Events::PlaySoundOnEntity e; + e.emitterID = 18; e.FilePath = "Audio/crosscounter.wav"; + //e.emitterID = 18; // rofl + m_EventBroker->Publish(e); + } + if (e.Command == "Reload" && e.Value > 0) { + Events::PauseSound e; + e.EmitterID = 18; + m_EventBroker->Publish(e); + } + if (e.Command == "Crouch" && e.Value > 0) { + Events::ContinueSound e; + e.EmitterID = 18; m_EventBroker->Publish(e); } return true; From 0cf8d2655745d5b76a6f590c10463ee4f57a904a Mon Sep 17 00:00:00 2001 From: Tleety Date: Mon, 11 Jan 2016 17:56:58 +0100 Subject: [PATCH 06/29] Revert "Revert "Forward+"" This reverts commit b908a9f9c683abae3a745105bd945af980a7d2b1. --- include/Engine/Rendering/DrawFinalPass.h | 38 +++++ include/Engine/Rendering/DrawFinalPassState.h | 15 ++ include/Engine/Rendering/LightCullingPass.h | 78 +++++++++ .../Engine/Rendering/LightCullingPassState.h | 0 include/Engine/Rendering/PickingPass.h | 6 +- include/Engine/Rendering/RenderQueue.h | 11 +- include/Engine/Rendering/Renderer.h | 65 +------- resources/Schema/Components.xsd | 1 + resources/Schema/Components/PointLight.xml | 7 + resources/Schema/Components/PointLight.xsd | 20 +++ resources/Schema/Entities/Test.xml | 8 +- resources/Schema/Types/Entity.xsd | 1 + resources/Shaders/CullLights.comp.glsl | 154 ++++++++++++++++++ resources/Shaders/ForwardPlus.frag.glsl | 132 +++++++++++++++ resources/Shaders/ForwardPlus.vert.glsl | 34 ++++ resources/Shaders/GridFrustum.comp.glsl | 51 +++--- resources/Shaders/cullLights.comp.glsl | 35 ---- src/Engine/Rendering/DrawFinalPass.cpp | 65 ++++++++ src/Engine/Rendering/DrawFinalPassState.cpp | 17 ++ src/Engine/Rendering/DrawScenePass.cpp | 15 +- src/Engine/Rendering/LightCullingPass.cpp | 126 ++++++++++++++ .../Rendering/LightCullingPassState.cpp | 0 src/Engine/Rendering/RenderQueueFactory.cpp | 28 ++++ src/Engine/Rendering/RenderState.cpp | 1 + src/Engine/Rendering/Renderer.cpp | 144 +--------------- 25 files changed, 780 insertions(+), 272 deletions(-) create mode 100644 include/Engine/Rendering/DrawFinalPass.h create mode 100644 include/Engine/Rendering/DrawFinalPassState.h create mode 100644 include/Engine/Rendering/LightCullingPass.h create mode 100644 include/Engine/Rendering/LightCullingPassState.h create mode 100644 resources/Schema/Components/PointLight.xml create mode 100644 resources/Schema/Components/PointLight.xsd create mode 100644 resources/Shaders/CullLights.comp.glsl create mode 100644 resources/Shaders/ForwardPlus.frag.glsl create mode 100644 resources/Shaders/ForwardPlus.vert.glsl delete mode 100644 resources/Shaders/cullLights.comp.glsl create mode 100644 src/Engine/Rendering/DrawFinalPass.cpp create mode 100644 src/Engine/Rendering/DrawFinalPassState.cpp create mode 100644 src/Engine/Rendering/LightCullingPass.cpp create mode 100644 src/Engine/Rendering/LightCullingPassState.cpp diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h new file mode 100644 index 00000000..1a201daf --- /dev/null +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -0,0 +1,38 @@ +#ifndef DrawFinalPass_h__ +#define DrawFinalPass_h__ + +#include "IRenderer.h" +#include "DrawFinalPassState.h" +#include "LightCullingPass.h" +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "Util/UnorderedMapVec2.h" +#include "Texture.h" + +class DrawFinalPass +{ +public: + DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass); + ~DrawFinalPass() { } + void InitializeTextures(); + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + + void Draw(RenderQueueCollection& rq); + + //Getters + + +private: + void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; + + Texture* m_WhiteTexture; + + const IRenderer* m_Renderer; + const LightCullingPass* m_LightCullingPass; + + ShaderProgram* m_ForwardPlusProgram; + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPassState.h b/include/Engine/Rendering/DrawFinalPassState.h new file mode 100644 index 00000000..72d8e392 --- /dev/null +++ b/include/Engine/Rendering/DrawFinalPassState.h @@ -0,0 +1,15 @@ +#ifndef DrawFinalPassState_h__ +#define DrawFinalPassState_h__ + +#include "Rendering/RenderState.h" + +class DrawFinalPassState : public RenderState +{ +public: + DrawFinalPassState(); + ~DrawFinalPassState(); +private: + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h new file mode 100644 index 00000000..e08aacdf --- /dev/null +++ b/include/Engine/Rendering/LightCullingPass.h @@ -0,0 +1,78 @@ +#ifndef LightCullingPass_h__ +#define LightCullingPass_h__ + +#define TILE_SIZE 16 +#define NUM_LIGHTS 1000 + +#include "IRenderer.h" +#include "LightCullingPassState.h" +#include "ShaderProgram.h" + + +class LightCullingPass +{ +public: + LightCullingPass(IRenderer* renderer); + ~LightCullingPass(); + + void GenerateNewFrustum(); + void CullLights(); + void FillLightList(RenderQueueCollection& rq); + + GLuint FrustumSSBO() const { return m_FrustumSSBO; } + GLuint LightSSBO() const { return m_LightSSBO; } + GLuint LightGridSSBO() const { return m_LightGridSSBO; } + GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; } + GLuint LightIndexSSBO() const { return m_LightIndexSSBO; } +private: + + void InitializeSSBOs(); + void InitializeShaderPrograms(); + + const IRenderer* m_Renderer; + + GLuint m_FrustumSSBO = 0; + GLuint m_LightSSBO = 0; + GLuint m_LightGridSSBO = 0; + GLuint m_LightOffsetSSBO = 0; + GLuint m_LightIndexSSBO = 0; + + ShaderProgram* m_CalculateFrustumProgram; + ShaderProgram* m_LightCullProgram; + + struct Plane { + glm::vec3 Normal; + float d; + }; + + struct Frustum { + Plane Planes[4]; + }; + Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution + + //This should be a component + struct PointLight { + glm::vec4 Position = glm::vec4(0.f); + glm::vec4 Color = glm::vec4(1.f); + float Radius = 5.f; + float Intensity = 0.8f; + float Falloff = 0.3f; + float Padding = 1337; + }; + std::vector m_PointLights; + + struct LightGrid { + float Start; + float Amount; + glm::vec2 Padding; + }; + + LightGrid m_LightGrid[80*45]; //TODO: Renderer: Make this change with resolution + + int m_LightOffset = 0; + + float m_LightIndex[80*45*200]; //TODO: Renderer: Make this change with resolution +}; + + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/LightCullingPassState.h b/include/Engine/Rendering/LightCullingPassState.h new file mode 100644 index 00000000..e69de29b diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index e1bc42db..0c1261ce 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -1,6 +1,8 @@ #ifndef PickingPass_h__ #define PickingPass_h__ + + #include "IRenderer.h" #include "PickingPassState.h" #include "FrameBuffer.h" @@ -9,6 +11,8 @@ #include "../Core/EventBroker.h" #include "EPicking.h" + + class PickingPass { public: @@ -20,7 +24,6 @@ public: void Draw(RenderQueueCollection& rq); - //Getters const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } const std::unordered_map& PickingColorsToEntity() const { return m_PickingColorsToEntity; } @@ -28,7 +31,6 @@ public: GLuint DepthBuffer() const { return m_DepthBuffer; } const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; } - private: void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index 2942c743..44d5e172 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -82,11 +82,12 @@ struct SpriteJob : RenderJob struct PointLightJob : RenderJob { - glm::vec3 Position; - glm::vec3 SpecularColor = glm::vec3(1, 1, 1); - glm::vec3 DiffuseColor = glm::vec3(1, 1, 1); - float Radius = 1.f; - float Intensity = 0.8f; + glm::vec4 Position; + glm::vec4 Color; + float Radius; + float Intensity; + float Falloff; + float padding = 123; void CalculateHash() override { diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 19b48e1a..c9f5d76f 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -13,19 +13,8 @@ #include "PickingPass.h" #include "DrawScenePass.h" #include "DebugCameraInputController.h" - - -#define TILE_SIZE 16 -#define NUM_LIGHTS 3 - - -enum lightType -{ - Point, - Spot, - Directional, - Area -}; +#include "LightCullingPass.h" +#include "DrawFinalPass.h" #include "../Core/EventBroker.h" #include "EPicking.h" @@ -58,70 +47,24 @@ private: DrawScenePass* m_DrawScenePass; PickingPass* m_PickingPass; + LightCullingPass* m_LightCullingPass; ImGuiRenderPass* m_ImGuiRenderPass; + DrawFinalPass* m_DrawFinalPass; //----------------------Functions----------------------// void InitializeWindow(); void InitializeShaders(); void InitializeTextures(); - void InitializeSSBOs(); void InitializeRenderPasses(); //TODO: Renderer: Get InputUpdate out of renderer void InputUpdate(double dt); //void PickingPass(RenderQueueCollection& rq); void DrawScreenQuad(GLuint textureToDraw); - //----------------------Forward+-----------------------// - void CalculateFrustum(); - void CullLights(); - //Frustum - struct Plane { - glm::vec3 Normal; - float d; - }; - struct Frustum { - Plane Planes[4]; - }; - Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution - - //Lights - void TEMPCreateLights(); - //TODO: Renderer: Add Directionllights, spotlights and area lights to this as type. - struct PointLight { - glm::vec4 Position = glm::vec4(0.f); - glm::vec4 Color = glm::vec4(1.f); - float Radius = 5.f; - float Intensity = 0.8f; - float Falloff = 0.3f; - float Padding = 1337; - }; - PointLight m_PointLights[NUM_LIGHTS]; - - struct LightGrid { - int Amount; - int Start; - glm::vec2 Padding; - }; - LightGrid m_LightGrid[80*45]; - - int m_LightOffset = 0; - - int m_LightIndex[80*45*200]; - - //-------------------------SSBO------------------------// - GLuint m_FrustumSSBO = 0; - GLuint m_LightSSBO = 1; - GLuint m_LightGridSSBO = 2; - GLuint m_LightOffsetSSBO = 3; - GLuint m_LightIndexSSBO = 4; - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_DrawScreenQuadProgram; - ShaderProgram* m_CalculateFrustumProgram; - ShaderProgram* m_LightCullProgram; - }; #endif \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 7fcdd565..459fd9d7 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -7,6 +7,7 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/PointLight.xml b/resources/Schema/Components/PointLight.xml new file mode 100644 index 00000000..6b1382db --- /dev/null +++ b/resources/Schema/Components/PointLight.xml @@ -0,0 +1,7 @@ + + + 1.0 + 0.8 + 0.3 + true + \ No newline at end of file diff --git a/resources/Schema/Components/PointLight.xsd b/resources/Schema/Components/PointLight.xsd new file mode 100644 index 00000000..d1a9f52c --- /dev/null +++ b/resources/Schema/Components/PointLight.xsd @@ -0,0 +1,20 @@ + + + + + + + + A pointlight that lights up geometry in a radius. + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 528c7e95..809bca51 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -10,7 +10,7 @@ - + +