sandbox
Loading...
Searching...
No Matches
mesh.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_GRAPHICS_PIPELINE_MESH_HPP_
3#define LIBSBX_GRAPHICS_PIPELINE_MESH_HPP_
4
5#include <memory>
6#include <vector>
7#include <string>
8#include <array>
9#include <unordered_map>
10
11#include <libsbx/utility/hashed_string.hpp>
12#include <libsbx/utility/exception.hpp>
13#include <libsbx/utility/assert.hpp>
14
15#include <libsbx/math/volume.hpp>
16#include <libsbx/math/vector4.hpp>
17
18#include <libsbx/graphics/buffers/buffer.hpp>
19#include <libsbx/graphics/buffers/storage_buffer.hpp>
20
21#include <libsbx/graphics/commands/command_buffer.hpp>
22
23#include <libsbx/graphics/pipeline/vertex_input_description.hpp>
24
25#include <libsbx/graphics/resource_storage.hpp>
26
27namespace sbx::graphics {
28
29struct submesh {
30 std::uint32_t index_count;
31 std::uint32_t index_offset;
32 std::uint32_t vertex_count;
33 std::uint32_t vertex_offset;
34 math::volume bounds;
35 math::matrix4x4 local_transform;
37 std::uint32_t material_index;
38 std::uint32_t lod_level{0u};
39 std::uint32_t lod_group{0u};
40}; // struct submesh
41
42template<vertex Vertex>
43class mesh {
44
45public:
46
47 using vertex_type = Vertex;
48
49 using index_type = std::uint32_t;
50
51 struct mesh_data {
52 std::vector<vertex_type> vertices;
53 std::vector<index_type> indices;
54 std::vector<graphics::submesh> submeshes;
55 math::volume bounds;
56 std::array<std::vector<math::vector4>, 5u> streams{};
57 }; // struct mesh_data
58
59 mesh(const std::vector<vertex_type>& vertices, const std::vector<index_type>& indices, const math::volume& bounds = math::volume{});
60
61 mesh(std::vector<vertex_type>&& vertices, std::vector<index_type>&& indices, const math::volume& bounds = math::volume{});
62
63 mesh(const mesh& other) noexcept = delete;
64
65 virtual ~mesh();
66
67 auto render(graphics::command_buffer& command_buffer, std::uint32_t instance_count = 1u) const -> void;
68
69 auto render_submesh(graphics::command_buffer& command_buffer, std::uint32_t submesh_index, std::uint32_t instance_count = 1u) const -> void;
70
71 auto address() const -> std::uint64_t;
72
73 auto bind(graphics::command_buffer& command_buffer) const -> void;
74
75 auto render_submesh_indirect(graphics::storage_buffer& buffer, std::uint32_t offset, std::uint32_t submesh_index, std::uint32_t instance_count = 1u) const -> void;
76
77 auto submeshes() const noexcept -> const std::vector<graphics::submesh>&;
78
79 auto submesh_index(const utility::hashed_string& name) const -> std::uint32_t {
80 const auto entry = std::ranges::find(_submeshes, name, &graphics::submesh::name);
81
82 if (entry == _submeshes.end()) {
83 throw utility::runtime_error{"Submesh '{}' not found", name.str()};
84 }
85
86 return std::distance(_submeshes.begin(), entry);
87 }
88
89 auto submesh(std::uint32_t submesh_index) const -> const graphics::submesh& {
90 utility::assert_that(submesh_index < _submeshes.size(), fmt::format("Trying to access out of bounds submesh {} of mesh with {} submeshes", submesh_index, _submeshes.size()));
91 return _submeshes.at(submesh_index);
92 }
93
94 auto submesh(const utility::hashed_string& name) const -> const graphics::submesh& {
95 return submesh(submesh_index(name));
96 }
97
98 auto submesh_bounds(std::uint32_t submesh_index) const -> const math::volume& {
99 return submesh(submesh_index).bounds;
100 }
101
102 auto submesh_bounds(const utility::hashed_string& name) const -> const math::volume& {
103 return submesh(submesh_index(name)).bounds;
104 }
105
106 auto submesh_local_transform(std::uint32_t submesh_index) const -> const math::matrix4x4& {
107 return submesh(submesh_index).local_transform;
108 }
109
110 auto submesh_local_transform(const utility::hashed_string& name) const -> const math::matrix4x4& {
111 return submesh(submesh_index(name)).local_transform;
112 }
113
114 auto submesh_names() const -> std::unordered_map<utility::hashed_string, std::uint32_t> {
115 auto names = std::unordered_map<utility::hashed_string, std::uint32_t>{};
116
117 for (std::size_t i = 0; i < _submeshes.size(); ++i) {
118 names.emplace(_submeshes[i].name, static_cast<std::uint32_t>(i));
119 }
120
121 return names;
122 }
123
124 auto bounds() const -> const math::volume& {
125 return _bounds;
126 }
127
128 auto vertex_count() const noexcept -> std::uint32_t {
129 return _vertex_count;
130 }
131
132 auto index_count() const noexcept -> std::uint32_t {
133 return _index_count;
134 }
135
136 auto lod_count(std::uint32_t submesh_index) const -> std::uint32_t {
137 const auto group = _submeshes[submesh_index].lod_group;
138 auto count = std::uint32_t{0u};
139
140 for (const auto& submesh : _submeshes) {
141 if (submesh.lod_group == group) {
142 ++count;
143 }
144 }
145
146 return count;
147 }
148
149 auto find_base_submesh_index(std::uint32_t lod_group) const -> std::optional<std::uint32_t> {
150 for (auto i = std::uint32_t{0u}; i < static_cast<std::uint32_t>(_submeshes.size()); ++i) {
151 if (_submeshes[i].lod_group == lod_group && _submeshes[i].lod_level == 0u) {
152 return i;
153 }
154 }
155
156 return std::nullopt;
157 }
158
159protected:
160
161 mesh(mesh_data&& mesh_data);
162
163 auto _upload_vertices(const std::vector<vertex_type>& vertices, const std::vector<index_type>& indices) -> void;
164
165 auto _upload_vertices(std::vector<vertex_type>&& vertices, std::vector<index_type>&& indices) -> void;
166
167 auto _calculate_bounds_from_submeshes(math::volume&& bounds) const -> math::volume;
168
169 buffer_handle _vertex_buffer;
170 buffer_handle _index_buffer;
171
172 std::vector<graphics::submesh> _submeshes;
173 std::uint32_t _vertex_count;
174 std::uint32_t _index_count;
175
176 math::volume _bounds;
177
178}; // class mesh
179
180} // namespace sbx::graphics
181
182#include <libsbx/graphics/pipeline/mesh.ipp>
183
184#endif // LIBSBX_GRAPHICS_PIPELINE_MESH_HPP_
Definition: command_buffer.hpp:15
Definition: mesh.hpp:43
Definition: matrix4x4.hpp:26
Definition: volume.hpp:14
Definition: hashed_string.hpp:17
Definition: mesh.hpp:51
Definition: mesh.hpp:29
Definition: exception.hpp:18