summaryrefslogtreecommitdiff
path: root/src/GFX/Util
diff options
context:
space:
mode:
Diffstat (limited to 'src/GFX/Util')
-rw-r--r--src/GFX/Util/MeshBuilder.hpp13
-rw-r--r--src/GFX/Util/Primitives.cpp107
-rw-r--r--src/GFX/Util/Primitives.hpp47
3 files changed, 167 insertions, 0 deletions
diff --git a/src/GFX/Util/MeshBuilder.hpp b/src/GFX/Util/MeshBuilder.hpp
index e3caa8c..c174b8c 100644
--- a/src/GFX/Util/MeshBuilder.hpp
+++ b/src/GFX/Util/MeshBuilder.hpp
@@ -2,6 +2,7 @@
#include "../../Common/Sizes.hpp"
#include "../../Math/Common.hpp"
+#include "Primitives.hpp"
#include <vector>
namespace MC::GFX::Util {
@@ -53,6 +54,18 @@ public:
m_indices.insert(m_indices.end(), from.begin(), from.end());
}
+ template<uint PN>
+ void primitive(const Primitives::Primitive<PN>& primitive) {
+ decltype(primitive.indices) relativized_indices{};
+ for (Int i = 0; i < primitive.indices.size(); i++) {
+ relativized_indices[i] = primitive.indices[i] + m_positions.size();
+ }
+
+ positions(primitive.positions);
+ attributes<0>(primitive.normals);
+ indices(relativized_indices);
+ }
+
Mesh mesh() {
return mesh(std::make_index_sequence<AttributesN>{});
}
diff --git a/src/GFX/Util/Primitives.cpp b/src/GFX/Util/Primitives.cpp
new file mode 100644
index 0000000..d2c3690
--- /dev/null
+++ b/src/GFX/Util/Primitives.cpp
@@ -0,0 +1,107 @@
+#include "Primitives.hpp"
+
+namespace MC::GFX::Util::Primitives {
+
+PlanePrimitive plane(Math::AABB aabb, FaceSet face) {
+ decltype(PlanePrimitive::positions) positions;
+ auto [min, max] = aabb;
+
+ switch (face) {
+ case FaceSet::Front:
+ positions = {{
+ {min.x(), min.y(), min.z()}, {min.x(), max.y(), min.z()},
+ {max.x(), max.y(), min.z()}, {max.x(), min.y(), min.z()}
+ }};
+ break;
+ case FaceSet::Back:
+ positions = {{
+ {min.x(), min.y(), max.z()}, {max.x(), min.y(), max.z()},
+ {max.x(), max.y(), max.z()}, {min.x(), max.y(), max.z()}
+ }};
+ break;
+ case FaceSet::Top:
+ positions = {{
+ {min.x(), max.y(), min.z()}, {min.x(), max.y(), max.z()},
+ {max.x(), max.y(), max.z()}, {max.x(), max.y(), min.z()}
+ }};
+ break;
+ case FaceSet::Bottom:
+ positions = {{
+ {min.x(), min.y(), min.z()}, {max.x(), min.y(), min.z()},
+ {max.x(), min.y(), max.z()}, {min.x(), min.y(), max.z()}
+ }};
+ break;
+ case FaceSet::Right:
+ positions = {{
+ {max.x(), min.y(), min.z()}, {max.x(), max.y(), min.z()},
+ {max.x(), max.y(), max.z()}, {max.x(), min.y(), max.z()}
+ }};
+ break;
+ case FaceSet::Left:
+ positions = {{
+ {min.x(), min.y(), min.z()}, {min.x(), min.y(), max.z()},
+ {min.x(), max.y(), max.z()}, {min.x(), max.y(), min.z()}
+ }};
+ break;
+ }
+
+ auto is_side = [=](FaceSet f) -> I8 { return f == face; };
+ Vector<3, F32> normal = {
+ is_side(FaceSet::Right) - is_side(FaceSet::Left),
+ is_side(FaceSet::Top) - is_side(FaceSet::Bottom),
+ is_side(FaceSet::Front) - is_side(FaceSet::Back),
+ };
+
+ return {positions, {normal, normal, normal, normal}, {0, 1, 2, 2, 3, 0}};
+}
+
+BoxPrimitive box(Math::AABB aabb, FaceSet faces) {
+ BoxPrimitive box{};
+ auto [min, max] = aabb;
+
+ UInt set_faces = 0;
+ U8 face_value = 1;
+ for (UInt face_index = 0; face_index < FaceSet::Size; face_index++, face_value <<= 1) {
+ FaceSet face = (FaceSet::Value)face_value;
+ if ((faces & face) == 0) continue;
+
+ Math::AABB face_aabb;
+ switch (face) {
+ case FaceSet::Front:
+ face_aabb = {min, {max.x(), max.y(), min.z()}};
+ break;
+ case FaceSet::Back:
+ face_aabb = {{min.x(), min.y(), max.z()}, max};
+ break;
+ case FaceSet::Top:
+ face_aabb = {{min.x(), max.y(), min.z()}, {max.x(), max.y(), max.z()}};
+ break;
+ case FaceSet::Bottom:
+ face_aabb = {min, {max.x(), min.y(), max.z()}};
+ break;
+ case FaceSet::Right:
+ face_aabb = {{max.x(), min.y(), min.z()}, max};
+ break;
+ case FaceSet::Left:
+ face_aabb = {min, {min.x(), max.y(), max.z()}};
+ break;
+ }
+
+ auto p = plane(face_aabb, face);
+
+ for (UInt i = 0; i < p.positions.size(); i++) {
+ box.positions[set_faces * 4 + i] = p.positions[i];
+ }
+ for (UInt i = 0; i < p.normals.size(); i++) {
+ box.normals[set_faces * 4 + i] = p.normals[i];
+ }
+ for (UInt i = 0; i < p.indices.size(); i++) {
+ box.indices[set_faces * 6 + i] = p.indices[i] + set_faces * 4;
+ }
+ set_faces++;
+ }
+
+ return box;
+}
+
+} \ No newline at end of file
diff --git a/src/GFX/Util/Primitives.hpp b/src/GFX/Util/Primitives.hpp
new file mode 100644
index 0000000..b96bc00
--- /dev/null
+++ b/src/GFX/Util/Primitives.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "../../Common/Sizes.hpp"
+#include "../../Math/AABB.hpp"
+#include <array>
+
+namespace MC::GFX::Util::Primitives {
+
+class FaceSet {
+public:
+ enum Value : U8 {
+ Front = 1 << 0,
+ Back = 1 << 1,
+ Top = 1 << 2,
+ Bottom = 1 << 3,
+ Right = 1 << 4,
+ Left = 1 << 5,
+ };
+
+ static constexpr UInt Size = 6;
+
+ FaceSet() = default;
+ FaceSet(const Value set) : m_set(set) {}
+
+ operator Value() const { return m_set; }
+
+ static FaceSet all() {
+ return static_cast<Value>(Front | Back | Top | Bottom | Right | Left);
+ }
+private:
+ Value m_set;
+};
+
+template <uint N>
+struct Primitive {
+ std::array<Vector<3, F32>, N> positions;
+ std::array<Vector<3, F32>, N> normals;
+ std::array<U32, N + N / 2> indices;
+};
+
+using PlanePrimitive = Primitive<4>;
+PlanePrimitive plane(Math::AABB aabb, FaceSet face);
+
+using BoxPrimitive = Primitive<4 * 6>;
+BoxPrimitive box(Math::AABB aabb, FaceSet faces = FaceSet::all());
+
+}