diff --git a/include/Engine/Rendering/EPicking.h b/include/Engine/Rendering/EPicking.h new file mode 100644 index 00000000..df75854a --- /dev/null +++ b/include/Engine/Rendering/EPicking.h @@ -0,0 +1,69 @@ +#ifndef Events_Picking_h__ +#define Events_Picking_h__ + +#include "../OpenGL.h" +#include "../GLM.h" + +#include "../Core/EventBroker.h" +#include "Util/ScreenCoords.h" +#include "FrameBuffer.h" +#include "../Core/Entity.h" +#include "Util/UnorderedMapVec2.h" + +namespace Events +{ + +/** Thrown Every frame, use functions to pick*/ +struct Picking : Event +{ +public: + Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map* pickingColorsToEntity) + : PickingBuffer(pickingBuffer) + , DepthBuffer(depthBuffer) + , ProjectionMatrix(projectionMatrix) + , ViewMatrix(viewMatrix) + , Resolution(resolution) + , PickingColorsToEntity(pickingColorsToEntity) + { } + + + + struct PickData + { + //Picked Entity + EntityID Entity; + //World position of the "pick" + glm::vec3 Position; + }; + + PickData Pick(glm::vec2 screenCoord) const + { + PickData pickData; + + ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer); + + auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1])); + if (it != PickingColorsToEntity->end()) { + pickData.Entity = it->second; + } else { + pickData.Entity = -1; + } + pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, Resolution.Width - screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix); + + return pickData; + } + + +private: + FrameBuffer* PickingBuffer; + GLuint* DepthBuffer; + const glm::mat4 ProjectionMatrix; + const glm::mat4 ViewMatrix; + const Rectangle Resolution; + const std::unordered_map* PickingColorsToEntity; + +}; + +} + +#endif diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index b1b76468..76de0818 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -11,15 +11,24 @@ #include "FrameBuffer.h" #include "../Core/World.h" +#include "../Core/EventBroker.h" +#include "EPicking.h" + class Renderer : public IRenderer { public: + Renderer(EventBroker* eventBroker) + : m_EventBroker(eventBroker) + { } + virtual void Initialize() override; virtual void Update(double dt) override; virtual void Draw(RenderQueueCollection& rq) override; private: //----------------------Variables----------------------// + EventBroker* m_EventBroker; + Texture* m_ErrorTexture; Texture* m_WhiteTexture; float m_CameraMoveSpeed; @@ -31,8 +40,6 @@ private: Model* m_UnitQuad; Model* m_UnitSphere; - - std::unordered_map m_PickingColorsToEntity; //----------------------Functions----------------------// diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index aba512fd..6f4235d2 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -3,7 +3,6 @@ void Renderer::Initialize() { InitializeWindow(); - // Create default camera m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10)); @@ -116,26 +115,6 @@ void Renderer::InputUpdate(double dt) static double mousePosX, mousePosY; glfwGetCursorPos(m_Window, &mousePosX, &mousePosY); - if (glfwGetMouseButton(m_Window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) { - ScreenCoords::PixelData data = ScreenCoords::ToPixelData(mousePosX, m_Resolution.Height - mousePosY, &m_PickingBuffer, m_DepthBuffer); - - glm::vec3 viewPos = ScreenCoords::ToWorldPos(mousePosX, m_Resolution.Height - mousePosY, data.Depth, m_Resolution, m_Camera->ProjectionMatrix(), m_Camera->ViewMatrix()); - // glm::vec3 worldPos = glm::vec3(glm::inverse(m_Camera->ViewMatrix()) * glm::vec4(viewPos, 1.f)); - - //printf("R: %f, G: %f, Depth: %f\n", data.Color[0], data.Color[1], data.Depth); - //printf("view: x: %f, y: %f z: %f, Length: %f\n\n", viewPos.x, viewPos.y, viewPos.z, glm::length(viewPos)); - //printf("\n\n---------------------------\n"); - auto got = m_PickingColorsToEntity.find(glm::vec2(data.Color[0], data.Color[1])); - if (got == m_PickingColorsToEntity.end()) - printf("Color (R:%f, G:%f) not found.\n", data.Color[0], data.Color[1]); - else - printf("R:%f G:%f, EntityID: %i\n", got->first.r, got->first.g, got->second); - //printf("----\n"); - //for (auto i : m_PickingColorsToEntity) { - // printf("Entity: %i, Color: R: %f, G: %f\n", i.second, i.first.r, i.first.g); - //} - //printf("---------------------------\n\n"); - } if (glfwGetKey(m_Window, GLFW_KEY_SPACE) == GLFW_PRESS) { @@ -161,7 +140,8 @@ void Renderer::InputUpdate(double dt) void Renderer::Update(double dt) { - InputUpdate(dt); + m_EventBroker->Process(); + InputUpdate(dt); } @@ -276,6 +256,17 @@ void Renderer::PickingPass(RenderQueueCollection& rq) m_PickingBuffer.Unbind(); GLERROR("PickingPass Error"); + //Publish pick event every frame with the pick data that can be picked by the event + Events::Picking pickEvent = Events::Picking( + &m_PickingBuffer, + &m_DepthBuffer, + m_Camera->ProjectionMatrix(), + m_Camera->ViewMatrix(), + m_Resolution, + &m_PickingColorsToEntity); + + m_EventBroker->Publish(pickEvent); + } diff --git a/src/Engine/Rendering/Util/ScreenCoords.cpp b/src/Engine/Rendering/Util/ScreenCoords.cpp index e999c895..36dd08a1 100644 --- a/src/Engine/Rendering/Util/ScreenCoords.cpp +++ b/src/Engine/Rendering/Util/ScreenCoords.cpp @@ -56,3 +56,4 @@ ScreenCoords::PixelData ScreenCoords::ToPixelData(glm::vec2 screenCoord, FrameBu { return ToPixelData(screenCoord.x, screenCoord.y, PickDataBuffer, DepthBuffer); } + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 15dde3a0..bff6aebc 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -16,7 +16,7 @@ Game::Game(int argc, char* argv[]) m_RenderQueueFactory = new RenderQueueFactory(); // Create the renderer - m_Renderer = new Renderer(); + m_Renderer = new Renderer(m_EventBroker); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); m_Renderer->SetResolution(Rectangle( @@ -65,12 +65,12 @@ void Game::Tick() m_EventBroker->Swap(); m_InputManager->Update(dt); - m_Renderer->Update(dt); m_EventBroker->Swap(); // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); testTick(dt); + m_Renderer->Update(dt); m_RenderQueueFactory->Update(m_World); m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());