#include "Primitives.hpp" #include "../../Math/Grid.hpp" namespace MC::GFX::Util::Primitives { PlanePrimitive plane(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(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; 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; } LineBoxPrimitive line_box(AABB aabb) { auto [min, max] = aabb; auto cube = Math::cube_cell_from_point(min, max - min); using P = Vector<3, F32>; decltype(LineBoxPrimitive::positions) positions = {{ P(cube.front_top_left()), P(cube.front_top_right()), P(cube.front_bottom_left()), P(cube.front_bottom_right()), P(cube.back_top_left()), P(cube.back_top_right()), P(cube.back_bottom_left()), P(cube.back_bottom_right()), }}; decltype(LineBoxPrimitive::indices) indices = {{ 0, 1, 1, 3, 3, 2, 2, 0, // Front 4, 5, 5, 7, 7, 6, 6, 4, // Back 0, 4, 1, 5, 2, 6, 3, 7, // Sides }}; // TODO: Allow Primitives to not have normals. return {positions, {{}}, indices}; } }