summary refs log tree commit diff
path: root/src/GFX/Util
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-07-12 03:39:01 +0200
committerMel <einebeere@gmail.com>2023-07-12 03:39:01 +0200
commitf09e5791837bb003f7c5db8c0e3162636bc9a9c2 (patch)
tree36b9a007f119388bb7943489e8d203de04269483 /src/GFX/Util
parent0ce26f2a49fd6d64a690b84b1932126edfbfbee6 (diff)
downloadmeowcraft-f09e5791837bb003f7c5db8c0e3162636bc9a9c2.tar.zst
meowcraft-f09e5791837bb003f7c5db8c0e3162636bc9a9c2.zip
3D Clouds
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());
+
+}