From f09e5791837bb003f7c5db8c0e3162636bc9a9c2 Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 12 Jul 2023 03:39:01 +0200 Subject: 3D Clouds --- src/GFX/Util/MeshBuilder.hpp | 13 ++++++ src/GFX/Util/Primitives.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++ src/GFX/Util/Primitives.hpp | 47 +++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 src/GFX/Util/Primitives.cpp create mode 100644 src/GFX/Util/Primitives.hpp (limited to 'src/GFX/Util') 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 namespace MC::GFX::Util { @@ -53,6 +54,18 @@ public: m_indices.insert(m_indices.end(), from.begin(), from.end()); } + template + void primitive(const Primitives::Primitive& 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{}); } 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 + +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(Front | Back | Top | Bottom | Right | Left); + } +private: + Value m_set; +}; + +template +struct Primitive { + std::array, N> positions; + std::array, N> normals; + std::array 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()); + +} -- cgit 1.4.1