Skip to content

Commit

Permalink
feat(gizmos): add ring gizmo
Browse files Browse the repository at this point in the history
  • Loading branch information
DiogoMendonc-a committed Jan 31, 2024
1 parent 1bce7c5 commit dac8150
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 0 deletions.
12 changes: 12 additions & 0 deletions engine/include/cubos/engine/gizmos/gizmos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ namespace cubos::engine
glm::vec3 secondBaseCenter, float secondBaseRadius, float lifespan = 0.0F,
Space space = Space::World);

/// @brief Draws a ring gizmo.
/// @param id Identifier of the gizmo.
/// @param firstBasePosition Center of one of the bases.
/// @param secondBasePosition Center of the second base.
/// @param outerRadius Radius of one of the ring.
/// @param innerRadius Radius of the of the hole.
/// @param lifespan How long the line will be on screen for, in seconds. Defaults to 0, which means a single
/// frame.
/// @param space Space to draw the gizmo in.
void drawRing(const std::string& id, glm::vec3 firstBasePosition, glm::vec3 secondBasePosition,
float outerRadius, float innerRadius, float lifespan = 0.0F, Space space = Space::World);

/// @brief Draws an arrow gizmo.
/// @param id Identifier of the gizmo.
/// @param origin Point from which the arrow starts.
Expand Down
9 changes: 9 additions & 0 deletions engine/src/cubos/engine/gizmos/gizmos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "types/box.hpp"
#include "types/cut_cone.hpp"
#include "types/line.hpp"
#include "types/ring.hpp"

using cubos::engine::DeltaTime;
using cubos::engine::Gizmos;
Expand Down Expand Up @@ -127,6 +128,14 @@ void Gizmos::drawCutCone(const std::string& id, glm::vec3 firstBaseCenter, float
space);
}

void Gizmos::drawRing(const std::string& id, glm::vec3 firstBasePosition, glm::vec3 secondBasePosition,
float outerRadius, float innerRadius, float lifespan, Space space)
{
push(std::make_shared<RingGizmo>((uint32_t)mHasher(id), firstBasePosition, secondBasePosition, outerRadius,
innerRadius, mColor, lifespan),
space);
}

void Gizmos::drawArrow(const std::string& id, glm::vec3 origin, glm::vec3 direction, float girth, float width,
float ratio, float lifespan, Space space)
{
Expand Down
102 changes: 102 additions & 0 deletions engine/src/cubos/engine/gizmos/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ void GizmosRenderer::init(RenderDevice* currentRenderDevice, glm::ivec2 size)
initLinePrimitive();
initBoxPrimitive();
initCutConePrimitive();
initRingPrimitive();
}

void GizmosRenderer::initLinePrimitive()
Expand Down Expand Up @@ -237,3 +238,104 @@ void GizmosRenderer::initCutConePrimitive()

cutConePrimitive.ib = renderDevice->createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static);
}

void GizmosRenderer::initRingPrimitive()
{
ringPrimitive.vaDesc.elementCount = 1;
ringPrimitive.vaDesc.elements[0].name = "position";
ringPrimitive.vaDesc.elements[0].type = Type::Float;
ringPrimitive.vaDesc.elements[0].size = 3;
ringPrimitive.vaDesc.elements[0].buffer.index = 0;
ringPrimitive.vaDesc.elements[0].buffer.offset = 0;
ringPrimitive.vaDesc.elements[0].buffer.stride = 3 * sizeof(float);
ringPrimitive.vaDesc.shaderPipeline = drawPipeline;

float verts[RingSections * 12];

renderDevice->setShaderPipeline(drawPipeline);
ringPrimitive.vb = renderDevice->createVertexBuffer(sizeof(verts), verts, Usage::Dynamic);
ringPrimitive.vaDesc.buffers[0] = ringPrimitive.vb;
ringPrimitive.va = renderDevice->createVertexArray(ringPrimitive.vaDesc);

unsigned int indices[3 * 8 * RingSections];

int iIndex = 0;
// Sides
for (unsigned int i = 0; i < (RingSections - 1) * 2; i += 2)
{
// TOP
indices[iIndex++] = i;
indices[iIndex++] = i + 1;
indices[iIndex++] = i + 3;

indices[iIndex++] = i;
indices[iIndex++] = i + 3;
indices[iIndex++] = i + 2;

// BOTTOM
indices[iIndex++] = i + (RingSections * 2);
indices[iIndex++] = i + (RingSections * 2) + 1;
indices[iIndex++] = i + (RingSections * 2) + 3;

indices[iIndex++] = i + (RingSections * 2);
indices[iIndex++] = i + (RingSections * 2) + 3;
indices[iIndex++] = i + (RingSections * 2) + 2;

// INNER
indices[iIndex++] = i + 1;
indices[iIndex++] = i + (RingSections * 2) + 1;
indices[iIndex++] = i + (RingSections * 2) + 3;

indices[iIndex++] = i + 1;
indices[iIndex++] = i + (RingSections * 2) + 3;
indices[iIndex++] = i + 3;

// OUTTER
indices[iIndex++] = i;
indices[iIndex++] = i + (RingSections * 2) + 2;
indices[iIndex++] = i + 2;

indices[iIndex++] = i;
indices[iIndex++] = i + (RingSections * 2);
indices[iIndex++] = i + (RingSections * 2) + 2;
}

// Last Side Faces
// TOP
indices[iIndex++] = ((RingSections - 1) * 2);
indices[iIndex++] = ((RingSections - 1) * 2) + 1;
indices[iIndex++] = 1;

indices[iIndex++] = ((RingSections - 1) * 2);
indices[iIndex++] = 1;
indices[iIndex++] = 0;

// BOTTOM
indices[iIndex++] = ((RingSections - 1) * 2) + (RingSections * 2);
indices[iIndex++] = ((RingSections - 1) * 2) + (RingSections * 2) + 1;
indices[iIndex++] = (RingSections * 2) + 1;

indices[iIndex++] = ((RingSections - 1) * 2) + (RingSections * 2);
indices[iIndex++] = (RingSections * 2) + 1;
indices[iIndex++] = (RingSections * 2);

// INNER
indices[iIndex++] = ((RingSections - 1) * 2) + 1;
indices[iIndex++] = ((RingSections - 1) * 2) + (RingSections * 2) + 1;
indices[iIndex++] = (RingSections * 2) + 1;

indices[iIndex++] = ((RingSections - 1) * 2) + 1;
indices[iIndex++] = (RingSections * 2) + 1;
indices[iIndex++] = 1;

// OUTTER
indices[iIndex++] = ((RingSections - 1) * 2);
indices[iIndex++] = (RingSections * 2);
indices[iIndex++] = 0;

indices[iIndex++] = ((RingSections - 1) * 2);
indices[iIndex++] = ((RingSections - 1) * 2) + (RingSections * 2);
indices[iIndex++] = (RingSections * 2) + 0;

ringPrimitive.ib = renderDevice->createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static);
}
3 changes: 3 additions & 0 deletions engine/src/cubos/engine/gizmos/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace cubos::engine
{
public:
static constexpr int CutConeVertsPerBase = 16; ///< Number of vertexes in each face of a cut cone gizmo.
static constexpr int RingSections = 32; ///< Number of traversal sections (i.e. quads) in a ring gizmo.

cubos::core::gl::ShaderPipeline drawPipeline; ///< Shader pipeline to be used when drawing gizmos.
cubos::core::gl::ShaderPipeline idPipeline; ///< Shader pipeline to be used when drawing gizmos.
Expand All @@ -28,6 +29,7 @@ namespace cubos::engine
Primitive linePrimitive; ///< GL line information.
Primitive boxPrimitive; ///< GL box information.
Primitive cutConePrimitive; ///< GL cut cone information.
Primitive ringPrimitive; ///< GL ring information.

glm::ivec2 textureSize; ///< Size of the id texture.
cubos::core::gl::Texture2D idTexture; ///< Texture holding the ids of the gizmo that was drawn to each pixel.
Expand Down Expand Up @@ -58,5 +60,6 @@ namespace cubos::engine
void initLinePrimitive();
void initBoxPrimitive();
void initCutConePrimitive();
void initRingPrimitive();
};
} // namespace cubos::engine
113 changes: 113 additions & 0 deletions engine/src/cubos/engine/gizmos/types/ring.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#pragma once

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/rotate_vector.hpp>

#include <cubos/engine/gizmos/gizmos.hpp>

#include "../renderer.hpp"

namespace cubos::engine
{
/// @brief A gizmo that is a ring.
class RingGizmo : public Gizmos::Gizmo
{
glm::vec3 mPointA;
glm::vec3 mPointB;
float mRadiusOuter;
float mRadiusInner;

public:
/// @brief Constructs.
/// @param id Identifier of the gizmo.
/// @param firstBasePosition Center of one of the bases.
/// @param secondBasePosition Center of the second base.
/// @param outerRadius Radius of one of the ring.
/// @param innerRadius Radius of the of the hole.
/// @param color Color for the gizmo to be drawn in.
/// @param lifespan Time the gizmo will remain on screen, in seconds.
RingGizmo(uint32_t id, glm::vec3 firstBasePosition, glm::vec3 secondBasePosition, float outerRadius,
float innerRadius, const glm::vec3& color, float lifespan)
: Gizmos::Gizmo(id, color, lifespan)
, mPointA(firstBasePosition)
, mPointB(secondBasePosition)
, mRadiusOuter(outerRadius)
, mRadiusInner(innerRadius)
{
}

/// @brief Draws the gizmo to screen.
/// @param renderer GizmosRenderer in use.
/// @param phase Current draw phase.
/// @param mvp Matrix containing projection and viewpoint transformations.
void draw(GizmosRenderer& renderer, DrawPhase phase,
const glm::mat<4, 4, float, glm::packed_highp>& mvp) override
{
auto* verts = static_cast<glm::vec3*>(renderer.ringPrimitive.vb->map());

glm::vec3 n = glm::normalize(mPointB - mPointA);
glm::vec3 p;
if (n[0] != n[1])
{
p = {n[1], -n[0], n[2]};
}
else if (n[0] != n[2])
{
p = {-n[2], n[1], n[0]};
}
else
{
p = {n[0], -n[2], n[1]};
}

glm::vec3 pA = p * mRadiusOuter;
glm::vec3 pB = p * mRadiusInner;

for (std::size_t i = 0; i < GizmosRenderer::RingSections; i++)
{
glm::vec3 vertOuter =
glm::rotate(pA, (float)i * glm::radians(360.0F / (float)GizmosRenderer::RingSections), n) + mPointA;
glm::vec3 vertInner =
glm::rotate(pB, (float)i * glm::radians(360.0F / (float)GizmosRenderer::RingSections), n) + mPointA;
verts[2 * i] = {vertOuter[0], vertOuter[1], vertOuter[2]};
verts[(2 * i) + 1] = {vertInner[0], vertInner[1], vertInner[2]};
}

for (std::size_t i = 0; i < GizmosRenderer::RingSections; i++)
{
glm::vec3 vertOuter =
glm::rotate(pA, (float)i * glm::radians(360.0F / (float)GizmosRenderer::RingSections), n) + mPointB;
glm::vec3 vertInner =
glm::rotate(pB, (float)i * glm::radians(360.0F / (float)GizmosRenderer::RingSections), n) + mPointB;
verts[(std::size_t)GizmosRenderer::RingSections * 2 + 2 * i] = {vertOuter[0], vertOuter[1],
vertOuter[2]};
verts[(std::size_t)GizmosRenderer::RingSections * 2 + (2 * i) + 1] = {vertInner[0], vertInner[1],
vertInner[2]};
}

renderer.ringPrimitive.vb->unmap();

renderer.renderDevice->setVertexArray(renderer.ringPrimitive.va);
renderer.renderDevice->setIndexBuffer(renderer.ringPrimitive.ib);

auto mvpBuffer =
renderer.renderDevice->createConstantBuffer(sizeof(glm::mat4), &mvp, cubos::core::gl::Usage::Static);

if (phase == DrawPhase::Color)
{
renderer.drawPipeline->getBindingPoint("MVP")->bind(mvpBuffer);

renderer.drawPipeline->getBindingPoint("objColor")->setConstant(mColor);
}
else
{
renderer.idPipeline->getBindingPoint("MVP")->bind(mvpBuffer);
}

renderer.renderDevice->setRasterState(
renderer.renderDevice->createRasterState(cubos::core::gl::RasterStateDesc{}));
renderer.renderDevice->drawTrianglesIndexed(0,
24 * (std::size_t)cubos::engine::GizmosRenderer::RingSections);
}
};
} // namespace cubos::engine

0 comments on commit dac8150

Please sign in to comment.