From 1c260872d1f6577f701dbfe0b04b2815f999dded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Mendon=C3=A7a?= Date: Sun, 15 Oct 2023 10:40:38 +0100 Subject: [PATCH] refactor(engine): change gizmos structure to not have logic on resources --- core/include/cubos/core/gl/render_device.hpp | 2 +- core/src/cubos/core/gl/ogl_render_device.cpp | 53 ++- docs/pages/3_examples/2_engine/main.md | 1 + engine/include/cubos/engine/gizmos/gizmos.hpp | 82 +++-- engine/include/cubos/engine/gizmos/plugin.hpp | 2 +- engine/samples/gizmos/main.cpp | 12 +- engine/samples/gizmos/page.md | 19 ++ engine/src/cubos/engine/gizmos/gizmos.cpp | 304 ++++++------------ engine/src/cubos/engine/gizmos/plugin.cpp | 30 +- .../cubos/engine/gizmos/types/box_gizmo.hpp | 57 ++++ .../cubos/engine/gizmos/types/line_gizmo.hpp | 50 +++ 11 files changed, 369 insertions(+), 243 deletions(-) create mode 100644 engine/samples/gizmos/page.md create mode 100644 engine/src/cubos/engine/gizmos/types/box_gizmo.hpp create mode 100644 engine/src/cubos/engine/gizmos/types/line_gizmo.hpp diff --git a/core/include/cubos/core/gl/render_device.hpp b/core/include/cubos/core/gl/render_device.hpp index 304b6e83aa..cc145580e6 100644 --- a/core/include/cubos/core/gl/render_device.hpp +++ b/core/include/cubos/core/gl/render_device.hpp @@ -884,7 +884,7 @@ namespace cubos::core::gl /// @param stencil Stencil value. virtual void clearStencil(int stencil) = 0; - /// @brief Draws Lines. + /// @brief Draws lines. /// @param offset Index of the first vertex to be drawn. /// @param count Number of vertices that will be drawn. virtual void drawLines(std::size_t offset, std::size_t count) = 0; diff --git a/core/src/cubos/core/gl/ogl_render_device.cpp b/core/src/cubos/core/gl/ogl_render_device.cpp index 3ee2dafd31..c869b69d36 100644 --- a/core/src/cubos/core/gl/ogl_render_device.cpp +++ b/core/src/cubos/core/gl/ogl_render_device.cpp @@ -842,8 +842,19 @@ class OGLVertexBuffer : public impl::VertexBuffer void* map() override { + GLenum glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } glBindBuffer(GL_ARRAY_BUFFER, this->id); - return glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + void* r = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } + return r; } void unmap() override @@ -1451,17 +1462,32 @@ void OGLRenderDevice::setFramebuffer(Framebuffer fb) RasterState OGLRenderDevice::createRasterState(const RasterStateDesc& desc) { + GLenum glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } auto rs = std::make_shared(); rs->cullEnabled = static_cast(desc.cullEnabled); rs->scissorEnabled = static_cast(desc.scissorEnabled); faceToGL(desc.cullFace, rs->cullFace); windingToGL(desc.frontFace, rs->frontFace); rasterModeToGL(desc.rasterMode, rs->polygonMode); + glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } return rs; } void OGLRenderDevice::setRasterState(RasterState rs) { + GLenum glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } auto rsImpl = std::static_pointer_cast(rs ? rs : mDefaultRS); if (rsImpl->cullEnabled == 0U) @@ -1485,6 +1511,11 @@ void OGLRenderDevice::setRasterState(RasterState rs) glFrontFace(rsImpl->frontFace); glPolygonMode(GL_FRONT_AND_BACK, rsImpl->polygonMode); + glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } } DepthStencilState OGLRenderDevice::createDepthStencilState(const DepthStencilStateDesc& desc) @@ -2449,13 +2480,33 @@ void OGLRenderDevice::drawTriangles(std::size_t offset, std::size_t count) void OGLRenderDevice::drawLines(std::size_t offset, std::size_t count) { + GLenum glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } glDrawArrays(GL_LINES, static_cast(offset), static_cast(count)); + glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } } void OGLRenderDevice::drawTrianglesIndexed(std::size_t offset, std::size_t count) { + GLenum glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } glDrawElements(GL_TRIANGLES, static_cast(count), static_cast(mCurrentIndexFormat), reinterpret_cast(offset * mCurrentIndexSz)); + glErr = glGetError(); + if (glErr != 0) + { + LOG_GL_ERROR(glErr); + } } void OGLRenderDevice::drawTrianglesInstanced(std::size_t offset, std::size_t count, std::size_t instanceCount) diff --git a/docs/pages/3_examples/2_engine/main.md b/docs/pages/3_examples/2_engine/main.md index 06d0ab0c53..2aa943d6bf 100644 --- a/docs/pages/3_examples/2_engine/main.md +++ b/docs/pages/3_examples/2_engine/main.md @@ -8,6 +8,7 @@ multiple plugins of the engine: - @subpage examples-engine-hello-cubos - @copybrief examples-engine-hello-cubos - @subpage examples-engine-settings - @copybrief examples-engine-settings - @subpage examples-engine-renderer - @copybrief examples-engine-renderer +- @subpage examples-engine-gizmos - @copybrief examples-engine-gizmos - @subpage examples-engine-scene - @copybrief examples-engine-scene - @subpage examples-engine-input - @copybrief examples-engine-input - @subpage examples-engine-assets - @copybrief examples-engine-assets diff --git a/engine/include/cubos/engine/gizmos/gizmos.hpp b/engine/include/cubos/engine/gizmos/gizmos.hpp index a264530992..3668519693 100644 --- a/engine/include/cubos/engine/gizmos/gizmos.hpp +++ b/engine/include/cubos/engine/gizmos/gizmos.hpp @@ -11,22 +11,42 @@ #include -using cubos::core::gl::RenderDevice; -using cubos::core::gl::ShaderPipeline; -using cubos::engine::DeltaTime; - namespace cubos::engine { - /// @brief Resource which draws gizmos. + /// @brief Resource that holds the information needed to draw a gizmo + class GizmosRenderer final + { + public: + cubos::core::gl::ShaderPipeline pipeline; ///< Shader pipeline to be used when drawing gizmos + cubos::core::gl::RenderDevice* renderDevice; ///< Active render device + + /// @brief Set of buffers and structs that hold te information needed to draw a specific type of mesh + struct Primitive + { + cubos::core::gl::VertexBuffer vb; + cubos::core::gl::VertexArray va; + cubos::core::gl::IndexBuffer ib; + cubos::core::gl::VertexArrayDesc vaDesc; + }; + + Primitive linePrimitive; ///< GL line information + Primitive boxPrimitive; ///< GL box information + + /// @brief Sets up the GizmosRenderer to be used + /// @param renderDevice the current RenderDevice being used + void init(cubos::core::gl::RenderDevice* renderDevice); + + private: + void initLinePrimitive(); + void initBoxPrimitive(); + }; + + /// @brief Resource which queues for drawing gizmos, basic primitives useful for debugging and tools. /// /// @ingroup gizmos-plugin class Gizmos final { public: - /// @brief Initiates the Gizmos resource. - /// @param renderDevice Active render device. - void init(RenderDevice& renderDevice); - /// @brief Sets the color to be used when drawing any subsequent gizmos. /// @param color Color to be used. void color(const glm::vec3& color); @@ -55,18 +75,40 @@ namespace cubos::engine /// frame. void drawWireBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan = 0); - /// @brief Draws all the gizmos that were called to be drawn. - /// @param deltaTime Resource holding the time since the previous frame. - void drawQueuedGizmos(DeltaTime deltaTime); + /// @brief Class that describes a type of gizmo + class GizmoBase + { + protected: + const std::string& mId; ///< Gizmo identifier + glm::vec3 mColor; ///< Color of the gizmo + float mLifespan; ///< Time in seconds the gizmo has left to live + + public: + GizmoBase(const std::string& id, glm::vec3 color, float lifespan) + : mId(id) + , mColor(color) + , mLifespan(lifespan) + { + } + + /// @brief draws the gizmo to screen + /// @param renderer the GizmosRenderer in use + virtual void draw(GizmosRenderer renderer) = 0; + + /// @brief decreases the time the gizmo has left before it is destroyed + /// @param delta the time in seconds since the last frame + bool decreaseLifespan(float delta) + { + mLifespan -= delta; + return mLifespan <= 0; + } + + virtual ~GizmoBase() = default; + }; + std::vector> gizmosVector; ///< Queued gizmos to be drawn. private: - ShaderPipeline mPipeline; ///< Shader pipeline to be used when drawing gizmos - RenderDevice* mRenderDevice; ///< Active render device - glm::vec3 mColor; ///< Currently set color - class GizmoBase; - class LineGizmo; - class BoxGizmo; - std::vector> mGizmosVector; ///< Queued gizmos to be drawn. + glm::vec3 mColor; ///< Currently set color }; -} // namespace cubos::engine +} // namespace cubos::engine \ No newline at end of file diff --git a/engine/include/cubos/engine/gizmos/plugin.hpp b/engine/include/cubos/engine/gizmos/plugin.hpp index 2508f199fe..f5e6dfcf63 100644 --- a/engine/include/cubos/engine/gizmos/plugin.hpp +++ b/engine/include/cubos/engine/gizmos/plugin.hpp @@ -14,7 +14,7 @@ namespace cubos::engine { /// @defgroup gizmos-plugin Gizmos /// @ingroup engine - /// @brief Allows gizmos to be drawn. + /// @brief Used to draw gizmos helpful for debugging and tools. /// /// ## Resources /// - @ref Gizmos - stores gizmos information. diff --git a/engine/samples/gizmos/main.cpp b/engine/samples/gizmos/main.cpp index a5973d0373..1ab29abac6 100644 --- a/engine/samples/gizmos/main.cpp +++ b/engine/samples/gizmos/main.cpp @@ -6,11 +6,9 @@ using cubos::core::ecs::Commands; using cubos::core::ecs::Write; -using cubos::engine::Gizmos; - using namespace cubos::engine; -static void mockCamera(Write camera, Commands cmds) +static void setCameraSystem(Write camera, Commands cmds) { camera->entities[0] = cmds.create() .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) @@ -42,15 +40,17 @@ static void drawStartingLineSystem(Write gizmos) } /// [Start Up System] -/// [Run] int main(int argc, char** argv) { + /// [Adding plugin] Cubos cubos{argc, argv}; cubos.addPlugin(gizmosPlugin); + /// [Adding plugin] cubos.addPlugin(rendererPlugin); - cubos.startupSystem(mockCamera); + cubos.startupSystem(setCameraSystem); + /// [Run] cubos.startupSystem(drawStartingLineSystem).tagged("sample.init").after("cubos.gizmos.init"); cubos.system(drawSystem); + /// [Run] cubos.run(); } -/// [Run] diff --git a/engine/samples/gizmos/page.md b/engine/samples/gizmos/page.md new file mode 100644 index 0000000000..d2f0c68082 --- /dev/null +++ b/engine/samples/gizmos/page.md @@ -0,0 +1,19 @@ +# Gizmos {#examples-engine-gizmos} + +@brief Using the @ref gizmos-plugin plugin. + +This example shows the @ref gizmos-plugin plugin, which allows drawing simple primitives. These are not intended for use in the final product, only in developer tools and for debugging. + +The plugin function is included from the @ref engine/gizmos/plugin.hpp header. + +@snippet gizmos/main.cpp Adding plugin + +To draw a gizmo, all you need to do is to get a reference to the @ref cubos::engine::Gizmos resource, and then call the draw function on it for the gizmo you want to draw. Additionally, you can also call the @ref cubos::engine::Gizmos::color function to set the color for future gizmos. So, for example if you want to draw a line in a given system, all you need to do is the following: + +@snippet gizmos/main.cpp Start Up System + +This code will draw a red line from the top-left of the screen to the bottom right, and it will stay there for 10 seconds. + +In this other example, we draw a line, a box, and a wire box. Unlike the one in the previous example, this system is not a start-up system, so the draw functions get called every single frame. When this happensl, you should set the lifetime of a gizmo to 0, which means it will be drawn for a single frame only. This way we avoid drawing gizmos on top of identical ones that were already there, or in the case of moving gizmos, leaving a trail of old version behind them. + +@snippet gizmos/main.cpp System \ No newline at end of file diff --git a/engine/src/cubos/engine/gizmos/gizmos.cpp b/engine/src/cubos/engine/gizmos/gizmos.cpp index 723a870477..a4a9b237b7 100644 --- a/engine/src/cubos/engine/gizmos/gizmos.cpp +++ b/engine/src/cubos/engine/gizmos/gizmos.cpp @@ -5,131 +5,19 @@ #include -using cubos::core::gl::IndexBuffer; -using cubos::core::gl::IndexFormat; -using cubos::core::gl::RasterMode; -using cubos::core::gl::RasterStateDesc; -using cubos::core::gl::ShaderBindingPoint; -using cubos::core::gl::Stage; -using cubos::core::gl::Type; -using cubos::core::gl::Usage; -using cubos::core::gl::VertexArray; -using cubos::core::gl::VertexArrayDesc; +#include "types/box_gizmo.hpp" +#include "types/line_gizmo.hpp" + using cubos::engine::DeltaTime; using cubos::engine::Gizmos; +using cubos::engine::GizmosRenderer; -/// @brief A gizmo to be drawn -class Gizmos::GizmoBase -{ -protected: - const std::string& mId; - glm::vec3 mColor; - float mLifespan; - VertexArray mVa; - IndexBuffer mIb; - VertexArrayDesc mVaDesc; - -public: - GizmoBase(const std::string& id, glm::vec3 color, float lifespan) - : mId(id) - , mColor(color) - , mLifespan(lifespan) - { - } - - virtual void draw(RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) = 0; - - bool decreaseLifespan(float delta) - { - mLifespan -= delta; - return mLifespan <= 0; - } - - virtual ~GizmoBase() = default; -}; - -/// @brief A line gizmo to be drawn -class Gizmos::LineGizmo : public Gizmos::GizmoBase -{ -public: - LineGizmo(const std::string& id, glm::vec3 from, glm::vec3 to, const glm::vec3& color, float lifespan, - RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) - : Gizmos::GizmoBase(id, color, lifespan) - , mPointA(from) - , mPointB(to) - { - mVaDesc.elementCount = 1; - mVaDesc.elements[0].name = "position"; - mVaDesc.elements[0].type = Type::Float; - mVaDesc.elements[0].size = 3; - mVaDesc.elements[0].buffer.index = 0; - mVaDesc.elements[0].buffer.offset = 0; - mVaDesc.elements[0].buffer.stride = 3 * sizeof(float); - mVaDesc.shaderPipeline = shaderPipeline; - - float verts[] = {mPointA[0], mPointA[1], mPointA[2], mPointB[0], mPointB[1], mPointB[2]}; - renderDevice.setShaderPipeline(shaderPipeline); - mVaDesc.buffers[0] = renderDevice.createVertexBuffer(sizeof(verts), verts, Usage::Static); - mVa = renderDevice.createVertexArray(mVaDesc); - } - void draw(RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) override; - -private: - glm::vec3 mPointA; - glm::vec3 mPointB; -}; - -/// @brief A box gizmo to be drawn -class Gizmos::BoxGizmo : public Gizmos::GizmoBase -{ -public: - BoxGizmo(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, const glm::vec3& color, float lifespan, - RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) - : Gizmos::GizmoBase(id, color, lifespan) - , mPointA(corner) - , mPointB(oppositeCorner) - { - mVaDesc.elementCount = 1; - mVaDesc.elements[0].name = "position"; - mVaDesc.elements[0].type = Type::Float; - mVaDesc.elements[0].size = 3; - mVaDesc.elements[0].buffer.index = 0; - mVaDesc.elements[0].buffer.offset = 0; - mVaDesc.elements[0].buffer.stride = 3 * sizeof(float); - mVaDesc.shaderPipeline = shaderPipeline; - - float verts[] = {mPointA[0], mPointA[1], mPointA[2], mPointB[0], mPointA[1], mPointA[2], - mPointB[0], mPointA[1], mPointB[2], mPointA[0], mPointA[1], mPointB[2], - mPointA[0], mPointB[1], mPointB[2], mPointA[0], mPointB[1], mPointA[2], - mPointB[0], mPointB[1], mPointA[2], mPointB[0], mPointB[1], mPointB[2]}; - renderDevice.setShaderPipeline(shaderPipeline); - mVaDesc.buffers[0] = renderDevice.createVertexBuffer(sizeof(verts), verts, Usage::Static); - mVa = renderDevice.createVertexArray(mVaDesc); - - unsigned int indices[] = {// front - 0, 6, 1, 0, 5, 6, - // right - 1, 7, 2, 1, 6, 7, - // back - 2, 7, 3, 3, 7, 4, - // left - 3, 5, 0, 3, 4, 5, - // bottom - 3, 1, 2, 3, 0, 1, - // top - 5, 7, 6, 5, 4, 7}; - mIb = renderDevice.createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static); - } - void draw(RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) override; +using namespace cubos::core::gl; -private: - glm::vec3 mPointA; - glm::vec3 mPointB; -}; - -void Gizmos::init(RenderDevice& renderDevice) +void GizmosRenderer::init(RenderDevice* currentRenderDevice) { - auto vs = renderDevice.createShaderStage(Stage::Vertex, R"( + renderDevice = currentRenderDevice; + auto vs = renderDevice->createShaderStage(Stage::Vertex, R"( #version 330 core in vec3 position; @@ -145,7 +33,7 @@ void Gizmos::init(RenderDevice& renderDevice) } )"); - auto ps = renderDevice.createShaderStage(Stage::Pixel, R"( + auto ps = renderDevice->createShaderStage(Stage::Pixel, R"( #version 330 core out vec4 color; @@ -157,9 +45,60 @@ void Gizmos::init(RenderDevice& renderDevice) color = vec4(objColor, 1.0f); } )"); + pipeline = renderDevice->createShaderPipeline(vs, ps); + initLinePrimitive(); + initBoxPrimitive(); +} - mRenderDevice = &renderDevice; - mPipeline = renderDevice.createShaderPipeline(vs, ps); +void GizmosRenderer::initLinePrimitive() +{ + linePrimitive.vaDesc.elementCount = 1; + linePrimitive.vaDesc.elements[0].name = "position"; + linePrimitive.vaDesc.elements[0].type = Type::Float; + linePrimitive.vaDesc.elements[0].size = 3; + linePrimitive.vaDesc.elements[0].buffer.index = 0; + linePrimitive.vaDesc.elements[0].buffer.offset = 0; + linePrimitive.vaDesc.elements[0].buffer.stride = 3 * sizeof(float); + linePrimitive.vaDesc.shaderPipeline = pipeline; + + float verts[] = {0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F}; + renderDevice->setShaderPipeline(pipeline); + linePrimitive.vb = renderDevice->createVertexBuffer(sizeof(verts), verts, Usage::Dynamic); + linePrimitive.vaDesc.buffers[0] = linePrimitive.vb; + linePrimitive.va = renderDevice->createVertexArray(linePrimitive.vaDesc); +} + +void GizmosRenderer::initBoxPrimitive() +{ + boxPrimitive.vaDesc.elementCount = 1; + boxPrimitive.vaDesc.elements[0].name = "position"; + boxPrimitive.vaDesc.elements[0].type = Type::Float; + boxPrimitive.vaDesc.elements[0].size = 3; + boxPrimitive.vaDesc.elements[0].buffer.index = 0; + boxPrimitive.vaDesc.elements[0].buffer.offset = 0; + boxPrimitive.vaDesc.elements[0].buffer.stride = 3 * sizeof(float); + boxPrimitive.vaDesc.shaderPipeline = pipeline; + + float verts[] = {0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 1.0F, 0.0F, 0.0F, 1.0F, + 0.0F, 1.0F, 1.0F, 0.0F, 1.0F, 0.0F, 1.0F, 1.0F, 0.0F, 1.0F, 1.0F, 1.0F}; + renderDevice->setShaderPipeline(pipeline); + boxPrimitive.vb = renderDevice->createVertexBuffer(sizeof(verts), verts, Usage::Dynamic); + boxPrimitive.vaDesc.buffers[0] = boxPrimitive.vb; + boxPrimitive.va = renderDevice->createVertexArray(boxPrimitive.vaDesc); + + unsigned int indices[] = {// front + 0, 6, 1, 0, 5, 6, + // right + 1, 7, 2, 1, 6, 7, + // back + 2, 7, 3, 3, 7, 4, + // left + 3, 5, 0, 3, 4, 5, + // bottom + 3, 1, 2, 3, 0, 1, + // top + 5, 7, 6, 5, 4, 7}; + boxPrimitive.ib = renderDevice->createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static); } void Gizmos::color(const glm::vec3& color) @@ -169,104 +108,49 @@ void Gizmos::color(const glm::vec3& color) void Gizmos::drawLine(const std::string& id, glm::vec3 from, glm::vec3 to, float lifespan) { - mGizmosVector.push_back(std::make_shared(id, from, to, mColor, lifespan, *mRenderDevice, mPipeline)); + gizmosVector.push_back(std::make_shared(id, from, to, mColor, lifespan)); } void Gizmos::drawBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan) { - mGizmosVector.push_back( - std::make_shared(id, corner, oppositeCorner, mColor, lifespan, *mRenderDevice, mPipeline)); + gizmosVector.push_back(std::make_shared(id, corner, oppositeCorner, mColor, lifespan)); } void Gizmos::drawWireBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan) { // Front - mGizmosVector.push_back(std::make_shared(id, corner, glm::vec3{oppositeCorner[0], corner[1], corner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, corner, glm::vec3{corner[0], oppositeCorner[1], corner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, - glm::vec3{corner[0], oppositeCorner[1], corner[2]}, mColor, - lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, - glm::vec3{oppositeCorner[0], corner[1], corner[2]}, mColor, - lifespan, *mRenderDevice, mPipeline)); + gizmosVector.push_back( + std::make_shared(id, corner, glm::vec3{oppositeCorner[0], corner[1], corner[2]}, mColor, lifespan)); + gizmosVector.push_back( + std::make_shared(id, corner, glm::vec3{corner[0], oppositeCorner[1], corner[2]}, mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, + glm::vec3{corner[0], oppositeCorner[1], corner[2]}, mColor, + lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, + glm::vec3{oppositeCorner[0], corner[1], corner[2]}, mColor, + lifespan)); // Back - mGizmosVector.push_back(std::make_shared(id, oppositeCorner, - glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, oppositeCorner, - glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, - glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, - glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); + gizmosVector.push_back(std::make_shared( + id, oppositeCorner, glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, mColor, lifespan)); + gizmosVector.push_back(std::make_shared( + id, oppositeCorner, glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, + glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, + mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, + glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, + mColor, lifespan)); // Sides - mGizmosVector.push_back(std::make_shared(id, corner, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], oppositeCorner[1], corner[2]}, - glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], corner[1], corner[2]}, - glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, - mColor, lifespan, *mRenderDevice, mPipeline)); - mGizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, - oppositeCorner, mColor, lifespan, *mRenderDevice, mPipeline)); -} - -void Gizmos::drawQueuedGizmos(DeltaTime deltaTime) -{ - std::vector toRemove; - for (std::size_t i = 0; i < mGizmosVector.size(); i++) - { - auto& gizmo = *mGizmosVector[i]; - gizmo.draw(*mRenderDevice, mPipeline); - if (gizmo.decreaseLifespan(deltaTime.value)) - { - toRemove.push_back(i); - } - } - while (!toRemove.empty()) - { - std::size_t i = toRemove.back(); - toRemove.pop_back(); - mGizmosVector[i] = mGizmosVector.back(); - mGizmosVector.pop_back(); - } -} - -void Gizmos::LineGizmo::draw(RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) -{ - renderDevice.setVertexArray(mVa); - - auto v = glm::translate(glm::mat4(1.0F), glm::vec3(-1.0F, -1.0F, 0.0F)); - auto p = glm::ortho(-0.5F, 0.5F, -0.5F, 0.5F); - auto vp = v * p; - auto mvpBuffer = renderDevice.createConstantBuffer(sizeof(glm::mat4), &vp, Usage::Static); - shaderPipeline->getBindingPoint("MVP")->bind(mvpBuffer); - - shaderPipeline->getBindingPoint("objColor")->setConstant(mColor); - renderDevice.setRasterState(renderDevice.createRasterState(RasterStateDesc{})); - renderDevice.drawLines(0, 2); + gizmosVector.push_back( + std::make_shared(id, corner, glm::vec3{corner[0], corner[1], oppositeCorner[2]}, mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{corner[0], oppositeCorner[1], corner[2]}, + glm::vec3{corner[0], oppositeCorner[1], oppositeCorner[2]}, + mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], corner[1], corner[2]}, + glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, + mColor, lifespan)); + gizmosVector.push_back(std::make_shared(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, + oppositeCorner, mColor, lifespan)); } - -void Gizmos::BoxGizmo::draw(RenderDevice& renderDevice, const ShaderPipeline& shaderPipeline) -{ - renderDevice.setVertexArray(mVa); - renderDevice.setIndexBuffer(mIb); - - auto v = glm::translate(glm::mat4(1.0F), glm::vec3(-1.0F, -1.0F, 0.0F)); - auto p = glm::ortho(-0.5F, 0.5F, -0.5F, 0.5F); - auto vp = v * p; - auto mvpBuffer = renderDevice.createConstantBuffer(sizeof(glm::mat4), &vp, Usage::Static); - shaderPipeline->getBindingPoint("MVP")->bind(mvpBuffer); - - shaderPipeline->getBindingPoint("objColor")->setConstant(mColor); - renderDevice.setRasterState(renderDevice.createRasterState(RasterStateDesc{})); - renderDevice.drawTrianglesIndexed(0, 36); -} \ No newline at end of file diff --git a/engine/src/cubos/engine/gizmos/plugin.cpp b/engine/src/cubos/engine/gizmos/plugin.cpp index 8f5d8f5cd4..fed4661310 100644 --- a/engine/src/cubos/engine/gizmos/plugin.cpp +++ b/engine/src/cubos/engine/gizmos/plugin.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -8,24 +9,45 @@ using cubos::core::ecs::Read; using cubos::core::ecs::Write; +using cubos::core::gl::RenderDevice; +using cubos::core::gl::Stage; + using cubos::core::io::Window; using cubos::engine::DeltaTime; using cubos::engine::Gizmos; +using cubos::engine::GizmosRenderer; -static void drawGizmosSystem(Write gizmos, Read deltaTime) +static void drawGizmosSystem(Write gizmos, Read gizmosRenderer, Read deltaTime) { - gizmos->drawQueuedGizmos(*deltaTime); + std::vector toRemove; + for (std::size_t i = 0; i < gizmos->gizmosVector.size(); i++) + { + auto& gizmo = *(gizmos->gizmosVector[i]); + gizmo.draw(*gizmosRenderer); + if (gizmo.decreaseLifespan(deltaTime->value)) + { + toRemove.push_back(i); + } + } + while (!toRemove.empty()) + { + std::size_t i = toRemove.back(); + toRemove.pop_back(); + gizmos->gizmosVector[i] = gizmos->gizmosVector.back(); + gizmos->gizmosVector.pop_back(); + } } -static void initGizmosSystem(Write gizmos, Read window) +static void initGizmosSystem(Write gizmosRenderer, Read window) { - gizmos->init((*window)->renderDevice()); + gizmosRenderer->init(&(*window)->renderDevice()); } void cubos::engine::gizmosPlugin(Cubos& cubos) { cubos.addResource(); + cubos.addResource(); cubos.addPlugin(cubos::engine::windowPlugin); cubos.startupSystem(initGizmosSystem).tagged("cubos.gizmos.init").after("cubos.window.init"); diff --git a/engine/src/cubos/engine/gizmos/types/box_gizmo.hpp b/engine/src/cubos/engine/gizmos/types/box_gizmo.hpp new file mode 100644 index 0000000000..561cd2288b --- /dev/null +++ b/engine/src/cubos/engine/gizmos/types/box_gizmo.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include + +/// @brief A gizmo that is a filled box +class BoxGizmo : public cubos::engine::Gizmos::GizmoBase +{ +private: + glm::vec3 mPointA; + glm::vec3 mPointB; + +public: + /// @brief BoxGizmo constructor + /// @param id identifier of the gizmo + /// @param corner point at one of the corners of the box + /// @param oppositeCorner point at the opposite corner of the box + /// @param color color for the gizmo to be drawn in + /// @param lifespan time the gizmo will remain on screen, in seconds + BoxGizmo(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, const glm::vec3& color, float lifespan) + : cubos::engine::Gizmos::GizmoBase(id, color, lifespan) + , mPointA(corner) + , mPointB(oppositeCorner) + { + } + + /// @brief draws the gizmo to screen + /// @param renderer the GizmosRenderer in use + void draw(cubos::engine::GizmosRenderer renderer) override + { + auto* verts = static_cast(renderer.boxPrimitive.vb->map()); + verts[0] = {mPointA[0], mPointA[1], mPointA[2]}; + verts[1] = {mPointB[0], mPointA[1], mPointA[2]}; + verts[2] = {mPointB[0], mPointA[1], mPointB[2]}; + verts[3] = {mPointA[0], mPointA[1], mPointB[2]}; + verts[4] = {mPointA[0], mPointB[1], mPointB[2]}; + verts[5] = {mPointA[0], mPointB[1], mPointA[2]}; + verts[6] = {mPointB[0], mPointB[1], mPointA[2]}; + verts[7] = {mPointB[0], mPointB[1], mPointB[2]}; + + renderer.boxPrimitive.vb->unmap(); + + renderer.renderDevice->setVertexArray(renderer.boxPrimitive.va); + renderer.renderDevice->setIndexBuffer(renderer.boxPrimitive.ib); + + auto v = glm::translate(glm::mat4(1.0F), glm::vec3(-1.0F, -1.0F, 0.0F)); + auto p = glm::ortho(-0.5F, 0.5F, -0.5F, 0.5F); + auto vp = v * p; + auto mvpBuffer = + renderer.renderDevice->createConstantBuffer(sizeof(glm::mat4), &vp, cubos::core::gl::Usage::Static); + renderer.pipeline->getBindingPoint("MVP")->bind(mvpBuffer); + + renderer.pipeline->getBindingPoint("objColor")->setConstant(mColor); + renderer.renderDevice->setRasterState( + renderer.renderDevice->createRasterState(cubos::core::gl::RasterStateDesc{})); + renderer.renderDevice->drawTrianglesIndexed(0, 36); + } +}; diff --git a/engine/src/cubos/engine/gizmos/types/line_gizmo.hpp b/engine/src/cubos/engine/gizmos/types/line_gizmo.hpp new file mode 100644 index 0000000000..412c3a8728 --- /dev/null +++ b/engine/src/cubos/engine/gizmos/types/line_gizmo.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include + +/// @brief A gizmo that is a line connecting two points +class LineGizmo : public cubos::engine::Gizmos::GizmoBase +{ +private: + glm::vec3 mPointA; + glm::vec3 mPointB; + +public: + /// @brief LineGizmo constructor + /// @param id identifier of the gizmo + /// @param from point at one of the ends of the line + /// @param to point at the other end of the line + /// @param color color for the gizmo to be drawn in + /// @param lifespan time the gizmo will remain on screen, in seconds + LineGizmo(const std::string& id, glm::vec3 from, glm::vec3 to, const glm::vec3& color, float lifespan) + : cubos::engine::Gizmos::GizmoBase(id, color, lifespan) + , mPointA(from) + , mPointB(to) + { + } + + /// @brief draws the gizmo to screen + /// @param renderer the GizmosRenderer in use + void draw(cubos::engine::GizmosRenderer renderer) override + { + auto* verts = static_cast(renderer.linePrimitive.vb->map()); + verts[0] = {mPointA[0], mPointA[1], mPointA[2]}; + verts[1] = {mPointB[0], mPointB[1], mPointB[2]}; + + renderer.linePrimitive.vb->unmap(); + + renderer.renderDevice->setVertexArray(renderer.linePrimitive.va); + + auto v = glm::translate(glm::mat4(1.0F), glm::vec3(-1.0F, -1.0F, 0.0F)); + auto p = glm::ortho(-0.5F, 0.5F, -0.5F, 0.5F); + auto vp = v * p; + auto mvpBuffer = + renderer.renderDevice->createConstantBuffer(sizeof(glm::mat4), &vp, cubos::core::gl::Usage::Dynamic); + renderer.pipeline->getBindingPoint("MVP")->bind(mvpBuffer); + + renderer.pipeline->getBindingPoint("objColor")->setConstant(mColor); + renderer.renderDevice->setRasterState( + renderer.renderDevice->createRasterState(cubos::core::gl::RasterStateDesc{})); + renderer.renderDevice->drawLines(0, 2); + } +}; \ No newline at end of file