Skip to content

Commit

Permalink
feat(engine): add cut cone gizmo
Browse files Browse the repository at this point in the history
  • Loading branch information
DiogoMendonc-a committed Oct 30, 2023
1 parent 33d8f8c commit 8f7db14
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 60 deletions.
32 changes: 25 additions & 7 deletions engine/include/cubos/engine/gizmos/gizmos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ namespace cubos::engine
/// @param from One of the ends of the line to be drawn.
/// @param to The other end of the line to be drawn.
/// @param lifespan How long the line will be on screen for, in seconds. Defaults to 0, which means a single
/// @param space Space to draw the gizmo in
/// frame.
/// @param space Space to draw the gizmo in.
void drawLine(const std::string& id, glm::vec3 from, glm::vec3 to, float lifespan = 0.0F,
Space space = Space::World);

Expand All @@ -50,17 +50,30 @@ namespace cubos::engine
/// @param oppositeCorner The opposite corner of the box to be drawn.
/// @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
/// @param space Space to draw the gizmo in.
void drawBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan = 0.0F,
Space space = Space::World);

/// @brief Draws a cut cone gizmo.
/// @param id Identifier of the gizmo.
/// @param firstBaseCenter Center of one of the bases.
/// @param firstBaseRadius Radius of one of the bases.
/// @param secondBaseCenter Center of the second base.
/// @param secondBaseRadius Radius of the second base.
/// @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 drawCutCone(const std::string& id, glm::vec3 firstBaseCenter, float firstBaseRadius,
glm::vec3 secondBaseCenter, float secondBaseRadius, float lifespan = 0.0F,
Space space = Space::World);

/// @brief Draws a wireframe box gizmo.
/// @param id Identifier of the gizmo.
/// @param corner One of the corners of the box to be drawn.
/// @param oppositeCorner The opposite corner of the box to be drawn.
/// @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
/// @param space Space to draw the gizmo in.
void drawWireBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan = 0.0F,
Space space = Space::World);

Expand All @@ -82,17 +95,22 @@ namespace cubos::engine
bool decreaseLifespan(float delta);

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
const std::string& mId; ///< Gizmo identifier.
glm::vec3 mColor; ///< Color of the gizmo.
float mLifespan; ///< Time in seconds the gizmo has left to live.
};

std::vector<std::shared_ptr<Gizmo>> worldGizmos; ///< Queued gizmos to be drawn in world space.
std::vector<std::shared_ptr<Gizmo>> viewGizmos; ///< Queued gizmos to be drawn in viewport space.
std::vector<std::shared_ptr<Gizmo>> screenGizmos; ///< Queued gizmos to be drawn in screen space.

private:
glm::vec3 mColor; ///< Currently set color
/// @brief Adds a gizmo into the corresponding vector.
/// @param gizmo Gizmo to be added.
/// @param space Space in which the gizmo will be drawn.
void push(const std::shared_ptr<Gizmo>& gizmo, const Space& space);

glm::vec3 mColor; ///< Currently set color.
};

} // namespace cubos::engine
30 changes: 18 additions & 12 deletions engine/samples/gizmos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,30 @@ static void settingsSystem(Write<Settings> settings)

static void setCameraSystem(Write<ActiveCameras> camera, Commands cmds)
{
camera->entities[0] = cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F})
.add(LocalToWorld{})
.add(Position{{5.0F, 5.0F, -10.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{0.0F, 0.0F, 1.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
camera->entities[0] =
cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F})
.add(LocalToWorld{})
.add(Position{{5.0F, 5.0F, 0.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
camera->entities[1] = cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F})
.add(LocalToWorld{})
.add(Position{{-5.0F, 5.0F, -10.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{0.0F, 0.0F, 1.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.add(Position{{-25.0F, 25.0F, 0.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
camera->entities[2] = cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F})
.add(LocalToWorld{})
.add(Position{{-5.0F, -5.0F, -10.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{0.5F, 0.5F, 0.5F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.add(Position{{-25.0F, -25.0F, 0.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
camera->entities[3] = cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F})
.add(LocalToWorld{})
.add(Position{{5.0F, -5.0F, -10.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{0.5F, 0.5F, 0.5F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.add(Position{{25.0F, -25.0F, 0.0F}})
.add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
}

Expand All @@ -62,6 +63,11 @@ static void drawSystem(Write<Gizmos> gizmos)
gizmos->color({0.5F, 1, 1});
gizmos->drawWireBox("test box", {0.5F, 0.5F, 0.5F}, {-1, -1, -1}, 0, Gizmos::Space::World);
/// [Box]

///[Cut Cone]
gizmos->color({0.5F, 0.3F, 1});
gizmos->drawCutCone("test cut cone", {0.7F, 0.7F, 0.7F}, 5.0F, {-3, -3, -3}, 3.0F, 0, Gizmos::Space::World);
///[Cut Cone]
}
/// [System]

Expand Down
6 changes: 5 additions & 1 deletion engine/samples/gizmos/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ Let's now add a wireboxe. We want to know were exactly is the centre of each cam

@snippet gizmos/main.cpp WireBox

Finally, let's add a box. This box will be in World space, as it's the last space left to cover. It will be drawn by any camera that is looking at it, much like if it was an object in the world.
Let's add a box. This box will be in World space, as it's the last space left to cover. It will be drawn by any camera that is looking at it, much like if it was an object in the world.

@snippet gizmos/main.cpp Box

Finally let's add a cut cone. A cut cone is cylinder with faces that can have different radiuses. If you set one of the bases to have a radius of 0, you'll have a simple cone. If you set them both to have the same radius, you'll have a cylinder. Our cut cone will have different radiuses:

@snippet gizmos/main.cpp Cut Cone

The whole system looks like this:

@snippet gizmos/main.cpp System
31 changes: 16 additions & 15 deletions engine/src/cubos/engine/gizmos/gizmos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "renderer.hpp"
#include "types/box.hpp"
#include "types/cut_cone.hpp"
#include "types/line.hpp"

using cubos::engine::DeltaTime;
Expand All @@ -33,9 +34,8 @@ void Gizmos::color(const glm::vec3& color)
mColor = color;
}

void Gizmos::drawLine(const std::string& id, glm::vec3 from, glm::vec3 to, float lifespan, Space space)
void Gizmos::push(const std::shared_ptr<Gizmo>& gizmo, const Space& space)
{
auto gizmo = std::make_shared<LineGizmo>(id, from, to, mColor, lifespan);
if (space == Space::World)
{
worldGizmos.push_back(gizmo);
Expand All @@ -50,21 +50,14 @@ void Gizmos::drawLine(const std::string& id, glm::vec3 from, glm::vec3 to, float
}
}

void Gizmos::drawLine(const std::string& id, glm::vec3 from, glm::vec3 to, float lifespan, Space space)
{
push(std::make_shared<LineGizmo>(id, from, to, mColor, lifespan), space);
}

void Gizmos::drawBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan, Space space)
{
auto gizmo = std::make_shared<BoxGizmo>(id, corner, oppositeCorner, mColor, lifespan);
if (space == Space::World)
{
worldGizmos.push_back(gizmo);
}
else if (space == Space::View)
{
viewGizmos.push_back(gizmo);
}
else if (space == Space::Screen)
{
screenGizmos.push_back(gizmo);
}
push(std::make_shared<BoxGizmo>(id, corner, oppositeCorner, mColor, lifespan), space);
}

void Gizmos::drawWireBox(const std::string& id, glm::vec3 corner, glm::vec3 oppositeCorner, float lifespan, Space space)
Expand Down Expand Up @@ -93,3 +86,11 @@ void Gizmos::drawWireBox(const std::string& id, glm::vec3 corner, glm::vec3 oppo
glm::vec3{oppositeCorner[0], corner[1], oppositeCorner[2]}, lifespan, space);
drawLine(id, glm::vec3{oppositeCorner[0], oppositeCorner[1], corner[2]}, oppositeCorner, lifespan, space);
}

void Gizmos::drawCutCone(const std::string& id, glm::vec3 firstBaseCenter, float firstBaseRadius,
glm::vec3 secondBaseCenter, float secondBaseRadius, float lifespan, Space space)
{
push(std::make_shared<CutConeGizmo>(id, firstBaseCenter, firstBaseRadius, secondBaseCenter, secondBaseRadius,
mColor, lifespan),
space);
}
60 changes: 60 additions & 0 deletions engine/src/cubos/engine/gizmos/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void GizmosRenderer::init(RenderDevice* currentRenderDevice)
pipeline = renderDevice->createShaderPipeline(vs, ps);
initLinePrimitive();
initBoxPrimitive();
initCutConePrimitive();
}

void GizmosRenderer::initLinePrimitive()
Expand Down Expand Up @@ -90,3 +91,62 @@ void GizmosRenderer::initBoxPrimitive()
5, 7, 6, 5, 4, 7};
boxPrimitive.ib = renderDevice->createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static);
}

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

float verts[CutConeVertsPerBase * 6];

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

unsigned int indices[12 * CutConeVertsPerBase - 12];

int iIndex = 0;
// Sides
for (unsigned int i = 0; i < CutConeVertsPerBase - 1; i += 1)
{
indices[iIndex++] = i;
indices[iIndex++] = i + 1;
indices[iIndex++] = i + CutConeVertsPerBase;
indices[iIndex++] = i + 1;
indices[iIndex++] = i + CutConeVertsPerBase + 1;
indices[iIndex++] = i + CutConeVertsPerBase;
}

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

// Base A
for (unsigned int i = 0; i < CutConeVertsPerBase - 2; i += 1)
{
indices[iIndex++] = 0;
indices[iIndex++] = i + 1;
indices[iIndex++] = i + 2;
}

// Base B
for (unsigned int i = CutConeVertsPerBase; i < (2 * CutConeVertsPerBase) - 2; i += 1)
{
indices[iIndex++] = CutConeVertsPerBase;
indices[iIndex++] = i + 1;
indices[iIndex++] = i + 2;
}

cutConePrimitive.ib = renderDevice->createIndexBuffer(sizeof(indices), indices, IndexFormat::UInt, Usage::Static);
}
18 changes: 11 additions & 7 deletions engine/src/cubos/engine/gizmos/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ namespace cubos::engine
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
static constexpr int CutConeVertsPerBase = 16; ///< Number of vertexes in each face of a cut cone gizmo.

/// @brief Set of buffers and structs that hold te information needed to draw a specific type of mesh
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;
Expand All @@ -20,15 +22,17 @@ namespace cubos::engine
cubos::core::gl::VertexArrayDesc vaDesc;
};

Primitive linePrimitive; ///< GL line information
Primitive boxPrimitive; ///< GL box information
Primitive linePrimitive; ///< GL line information.
Primitive boxPrimitive; ///< GL box information.
Primitive cutConePrimitive; ///< GL cut cone information.

/// @brief Sets up the GizmosRenderer to be used
/// @param renderDevice the current RenderDevice being used
/// @brief Sets up the render device to be used.
/// @param renderDevice the current Render device being used.
void init(cubos::core::gl::RenderDevice* currentRenderDevice);

private:
void initLinePrimitive();
void initBoxPrimitive();
void initCutConePrimitive();
};
} // namespace cubos::engine
19 changes: 10 additions & 9 deletions engine/src/cubos/engine/gizmos/types/box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@

namespace cubos::engine
{
/// @brief A gizmo that is a filled box
/// @brief A gizmo that is a filled box.
class BoxGizmo : public cubos::engine::Gizmos::Gizmo
{
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
/// @brief Constructs.
/// @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::Gizmo(id, color, lifespan)
Expand All @@ -29,8 +29,9 @@ namespace cubos::engine
{
}

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

0 comments on commit 8f7db14

Please sign in to comment.