-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from LimpingPebble/feat/debug-shape
Feat/debug shape
- Loading branch information
Showing
9 changed files
with
416 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright 2024 Stone-Engine | ||
|
||
#pragma once | ||
|
||
#include "Scene/Geometry.hpp" | ||
#include "Scene/Node/RenderableNode.hpp" | ||
|
||
namespace Stone::Scene { | ||
|
||
/** | ||
* @class WireframeShape | ||
* @brief Represents a wireframe shape that can be rendered in a scene. | ||
* | ||
* The WireframeShape class is a subclass of RenderableNode and provides functionality for creating and manipulating | ||
* wireframe shapes. Wireframe shapes are represented by a collection of vertices and can be rendered as lines or dots. | ||
* The color, line thickness, and lifespan of the wireframe shape can be customized. | ||
*/ | ||
class WireframeShape : public RenderableNode { | ||
STONE_NODE(WireframeShape); | ||
|
||
public: | ||
/** | ||
* @brief Constructs a WireframeShape object. | ||
* | ||
* @param name The name of the WireframeShape (optional). | ||
*/ | ||
explicit WireframeShape(const std::string &name = "debug_shape"); | ||
/** | ||
* @brief Constructs a new WireframeShape by copying another WireframeShape object. | ||
* | ||
* @param other The WireframeShape object to be copied. | ||
*/ | ||
WireframeShape(const WireframeShape &other) = default; | ||
|
||
/** | ||
* @brief Destructor for the WireframeShape class. | ||
*/ | ||
~WireframeShape() override = default; | ||
|
||
/** | ||
* Writes the wireframe shape to the output stream. | ||
* | ||
* @param stream The output stream to write to. | ||
* @param closing_bracer Flag indicating whether to write a closing bracer. | ||
* @return The output stream after writing the wireframe shape. | ||
*/ | ||
std::ostream &writeToStream(std::ostream &stream, bool closing_bracer) const override; | ||
|
||
/** | ||
* @brief Retrieves the color | ||
* | ||
* @return The color of the wireframe shape as a glm::vec3. | ||
*/ | ||
[[nodiscard]] glm::vec3 getColor() const; | ||
/** | ||
* Sets the color of the wireframe shape. | ||
* | ||
* @param color The color to set, specified as a glm::vec3. | ||
*/ | ||
void setColor(const glm::vec3 &color); | ||
|
||
/** | ||
* @brief Retrieves the thickness of the wireframe shape. | ||
* | ||
* @return The thickness of the wireframe shape. | ||
*/ | ||
[[nodiscard]] float getThickness() const; | ||
/** | ||
* @brief Sets the thickness of the wireframe shape. | ||
* | ||
* @param thickness The thickness of the wireframe shape. | ||
*/ | ||
void setThickness(float thickness); | ||
|
||
/** | ||
* @brief Retrieves the points of the wireframe shape. | ||
* | ||
* @return A constant reference to a vector of vectors of glm::vec3 representing the points of the wireframe shape. | ||
*/ | ||
[[nodiscard]] const std::vector<std::vector<glm::vec3>> &getPoints() const; | ||
/** | ||
* @brief Returns a reference to the vector of vector of glm::vec3 points. | ||
* | ||
* @return std::vector<std::vector<glm::vec3>>& A reference to the vector of vector of glm::vec3 points. | ||
*/ | ||
std::vector<std::vector<glm::vec3>> &pointsRef(); | ||
|
||
/** | ||
* @brief Checks if the wireframe shape should be drawn as a line. | ||
* | ||
* @return true if the wireframe shape should be drawn as a line, false otherwise. | ||
*/ | ||
[[nodiscard]] bool isDrawLine() const; | ||
/** | ||
* @brief Sets whether to draw the wireframe shape as a line. | ||
* | ||
* @param drawLine True to draw the wireframe shape as a line, false otherwise. | ||
*/ | ||
void setDrawLine(bool drawLine); | ||
|
||
/** | ||
* @brief Creates a new instance of WireframeShape with the specified shape and arguments. | ||
* | ||
* @tparam ShapeType The type of shape to generate. | ||
* @tparam Args The types of arguments to pass to the shape generator. | ||
* @param shape The shape to generate. | ||
* @param args The arguments to pass to the shape generator. | ||
* @return A shared pointer to the newly created WireframeShape. | ||
*/ | ||
template <typename ShapeType, typename... Args> | ||
static std::shared_ptr<WireframeShape> create(const ShapeType &shape, Args &&...args) { | ||
auto wireframeShape = std::make_shared<WireframeShape>(); | ||
|
||
auto [indices, vertices] = generateGeometryMesh(shape, std::forward<Args>(args)...); | ||
|
||
auto &points = wireframeShape->pointsRef().emplace_back(); | ||
points.reserve(indices.size()); | ||
for (auto &index : indices) { | ||
points.push_back(vertices[index]); | ||
} | ||
|
||
return wireframeShape; | ||
} | ||
|
||
protected: | ||
glm::vec3 _color; /** The color of the debug shape. */ | ||
float _thickness; /** The line thickness of the debug shape. */ | ||
|
||
std::vector<std::vector<glm::vec3>> _points; /** The vertices of the debug shape. */ | ||
|
||
bool _drawLine; /** Whether to draw the debug shape as a line or as dots. */ | ||
}; | ||
|
||
} // namespace Stone::Scene |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// Copyright 2024 Stone-Engine | ||
|
||
#include "Scene/Geometry.hpp" | ||
|
||
namespace Stone::Scene { | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Plane &plane, float size) { | ||
std::vector<uint32_t> indices = {0, 1, 2, 0, 2, 3}; | ||
std::vector<glm::vec3> vertices = { | ||
plane.normal * size + glm::vec3(0.0f, 0.0f, plane.distance), | ||
plane.normal * size + glm::vec3(size, 0.0f, plane.distance), | ||
plane.normal * size + glm::vec3(size, size, plane.distance), | ||
plane.normal * size + glm::vec3(0.0f, size, plane.distance), | ||
}; | ||
return {indices, vertices}; | ||
} | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Sphere &sphere, int rings) { | ||
std::vector<uint32_t> indices; | ||
std::vector<glm::vec3> vertices; | ||
|
||
const float phiStep = M_PIf32 / (float)rings; | ||
const float thetaStep = 2 * M_PIf32 / (float)rings; | ||
|
||
for (int i = 0; i <= rings; i++) { | ||
const float phi = (float)i * phiStep; | ||
for (int j = 0; j <= rings; j++) { | ||
const float theta = (float)j * thetaStep; | ||
|
||
const float x = sphere.radius * std::sin(phi) * std::cos(theta); | ||
const float y = sphere.radius * std::cos(phi); | ||
const float z = sphere.radius * std::sin(phi) * std::sin(theta); | ||
|
||
vertices.push_back(sphere.center + glm::vec3(x, y, z)); | ||
} | ||
} | ||
|
||
for (int i = 0; i < rings; i++) { | ||
for (int j = 0; j < rings; j++) { | ||
const int i0 = i * (rings + 1) + j; | ||
const int i1 = i0 + 1; | ||
const int i2 = i0 + rings + 1; | ||
const int i3 = i2 + 1; | ||
|
||
indices.push_back(i0); | ||
indices.push_back(i1); | ||
indices.push_back(i2); | ||
|
||
indices.push_back(i2); | ||
indices.push_back(i1); | ||
indices.push_back(i3); | ||
} | ||
} | ||
|
||
return {indices, vertices}; | ||
} | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Box &box) { | ||
std::vector<uint32_t> indices = { | ||
0, 1, 2, 2, 3, 0, // Front | ||
4, 5, 6, 6, 7, 4, // Back | ||
0, 4, 7, 7, 3, 0, // Left | ||
1, 5, 6, 6, 2, 1, // Right | ||
0, 1, 5, 5, 4, 0, // Top | ||
3, 2, 6, 6, 7, 3, // Bottom | ||
}; | ||
std::vector<glm::vec3> vertices = { | ||
box.min, | ||
glm::vec3(box.max.x, box.min.y, box.min.z), | ||
glm::vec3(box.max.x, box.max.y, box.min.z), | ||
glm::vec3(box.min.x, box.max.y, box.min.z), | ||
glm::vec3(box.min.x, box.min.y, box.max.z), | ||
glm::vec3(box.max.x, box.min.y, box.max.z), | ||
box.max, | ||
glm::vec3(box.min.x, box.max.y, box.max.z), | ||
}; | ||
return {indices, vertices}; | ||
} | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Line &line) { | ||
std::vector<uint32_t> indices = {0, 1}; | ||
std::vector<glm::vec3> vertices = {line.origin, line.origin + line.direction}; | ||
return {indices, vertices}; | ||
} | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Cone &cone, int segments) { | ||
std::vector<uint32_t> indices; | ||
std::vector<glm::vec3> vertices; | ||
|
||
const float angleStep = cone.angle / (float)segments; | ||
const float halfLength = cone.length / 2.0f; | ||
|
||
for (int i = 0; i <= segments; i++) { | ||
const float angle = (float)i * angleStep; | ||
const float x = cone.length * std::cos(angle); | ||
const float y = cone.length * std::sin(angle); | ||
|
||
vertices.push_back(cone.origin + glm::vec3(x, y, -halfLength)); | ||
vertices.push_back(cone.origin + glm::vec3(x, y, halfLength)); | ||
} | ||
|
||
for (int i = 0; i < segments; i++) { | ||
const int i0 = i * 2; | ||
const int i1 = i0 + 1; | ||
const int i2 = i0 + 2; | ||
const int i3 = i2 + 1; | ||
|
||
indices.push_back(i0); | ||
indices.push_back(i1); | ||
indices.push_back(i2); | ||
|
||
indices.push_back(i2); | ||
indices.push_back(i1); | ||
indices.push_back(i3); | ||
} | ||
|
||
return {indices, vertices}; | ||
} | ||
|
||
std::pair<std::vector<uint32_t>, std::vector<glm::vec3>> generateGeometryMesh(const Frustum &frustum) { | ||
std::vector<uint32_t> indices; | ||
std::vector<glm::vec3> vertices; | ||
|
||
for (auto plane : frustum.planes) { | ||
auto [planeIndices, planeVertices] = generateGeometryMesh(plane, 1.0f); | ||
const auto offset = static_cast<uint32_t>(vertices.size()); | ||
for (const auto &index : planeIndices) { | ||
indices.push_back(index + offset); | ||
} | ||
for (const auto &vertex : planeVertices) { | ||
vertices.push_back(vertex); | ||
} | ||
} | ||
|
||
return {indices, vertices}; | ||
} | ||
|
||
} // namespace Stone::Scene |
Oops, something went wrong.