Oxygen Engine
Modern C++ 3D Engine using OpenGL
Loading...
Searching...
No Matches
mesh.h
1#ifndef OE_RENDER_MESH_H
2#define OE_RENDER_MESH_H
3
4#include <glue_chan/glue_chan.h>
5#include <vector>
6
7#include "../scene/mesh.h"
8#include "../core/renderer/opengl.h"
9
10namespace oe::render
11{
13 {
14 uint32_t& vertex_array;
15
22 template <typename V>
24
25 void enableVertexAttribPointer(const uint32_t index, const size_t offset, const int32_t componentCount)
26 {
27 // Hardcode float because this function is only used for glVertexAttribPointer
28 glEnableVertexArrayAttrib(vertex_array, index);
29 glVertexArrayAttribFormat(vertex_array, index, componentCount, GL_FLOAT, false, offset);
30 glVertexArrayAttribBinding(vertex_array, index, 0);
31 }
32
33 void enableVertexAttribIPointer(const uint32_t index, const size_t offset, const int32_t componentCount)
34 {
35 // Hardcode int because this function is only used for glVertexAttribIPointer
36 glEnableVertexArrayAttrib(vertex_array, index);
37 glVertexArrayAttribIFormat(vertex_array, index, componentCount, GL_INT, offset);
38 glVertexArrayAttribBinding(vertex_array, index, 0);
39 }
40
46 template <typename T>
47 int32_t getComponentSize() noexcept;
48
55 template <typename VertexType, typename T>
56 void bindVertexAttributeToPointer(const uint32_t index, const size_t offset) noexcept
57 {
58 enableVertexAttribPointer(index, offset, getComponentSize<T>());
59 }
60
67 template <typename VertexType, typename T>
68 void bindVertexAttributeToIPointer(const uint32_t index, const size_t offset) noexcept
69 {
70 enableVertexAttribIPointer(index, offset, getComponentSize<T>());
71 }
72 };
73
77 constexpr const uint8_t default_mesh_rendering_mode = 0x04;
78
79 class Mesh
80 {
81 public:
87 template <typename SceneMeshType>
88 Mesh(const SceneMeshType& scene_mesh, bool editable = false):
89 primitives(scene_mesh.primitives),
90 _index_size(sizeof(typename SceneMeshType::index_type))
91 {
93
94 const auto& vertices = scene_mesh.vertices;
95 const auto& indices = scene_mesh.indices;
96
97 _common_construct<SceneMeshType>(
98 vertices.size(), vertices.data(),
99 indices.size(), indices.data(),
100 editable
101 );
102 }
103
110 template <typename SceneMeshType>
111 Mesh(const SceneMeshType&, uint32_t max_vertices_count, uint32_t max_indices_count):
112 _index_size(sizeof(typename SceneMeshType::index_type))
113 {
115
116 _common_construct<SceneMeshType>(
117 max_vertices_count, nullptr,
118 max_indices_count, nullptr,
119 true
120 );
121 }
122
123 Mesh(const Mesh&) = delete;
124 Mesh& operator=(const Mesh&) = delete;
125
126 Mesh(Mesh&& other) noexcept:
127 primitives(other.primitives),
128 _index_type(other._index_type),
129 _index_size(other._index_size),
130 _vao(other._vao),
131 _vbo(other._vbo),
132 _ebo(other._ebo)
133 {
134 other._vao = 0;
135 other._vbo = 0;
136 other._ebo = 0;
137 }
138
139 ~Mesh()
140 {
141 if (_vao != 0)
142 {
143 const uint32_t buffers[2] = {_vbo, _ebo};
144 glDeleteBuffers(2, buffers);
145
146 glDeleteVertexArrays(1, &_vao);
147 }
148 }
149
153 void setSubBufferData(const uint32_t size, const void* data, const uint32_t offset = 0)
154 {
155 glNamedBufferSubData(_vbo, offset, size, data);
156 }
157
161 void setIndicesData(const uint32_t size, const void* data, const uint32_t offset = 0)
162 {
163 glNamedBufferSubData(_ebo, offset, size, data);
164 }
165
173 std::pair<void*, void*> getRawBuffers()
174 {
175 glBindVertexArray(_vao);
176
177 return
178 {
179 glMapNamedBuffer(_vbo, GL_WRITE_ONLY),
180 glMapNamedBuffer(_ebo, GL_WRITE_ONLY)
181 };
182 }
183
190 {
191 glUnmapNamedBuffer(_vbo);
192 glUnmapNamedBuffer(_ebo);
193 }
194
202 void renderArrays(const uint32_t count, const uint32_t offset, uint32_t mode)
203 {
204 glBindVertexArray(_vao);
205 glDrawArrays(mode, offset, count);
206 }
207
215 void renderElements(const uint32_t count, const uint32_t offset, const uint32_t mode)
216 {
217 glBindVertexArray(_vao);
218 glDrawElements(mode, count, GL_UNSIGNED_INT, reinterpret_cast<uint32_t*>(offset));
219 }
220
226 void render(const std::vector<bool>& activeprimitives, uint32_t mode = default_mesh_rendering_mode)
227 {
228 assert(primitives.size() && "If this triggers, you forgot to add primitives to mesh, maybe you meant to renderArrays instead?");
229 assert(activeprimitives.size() == primitives.size());
230
231 // Compute offsets based on "jumps" in submeshes list
232 std::vector<oe::scene::Primitive> primitive_render_calls;
233
234 oe::scene::Primitive current_packed_primitive = {0, 0};
235 bool last_primitive_active = false;
236 size_t i = 0;
237
238 for (const auto& is_active : activeprimitives)
239 {
240 const auto& primitive_data = primitives.at(i);
241
242 if (last_primitive_active)
243 {
244 if (is_active)
245 {
246 current_packed_primitive.size += primitive_data.size;
247 }
248 else
249 {
250 primitive_render_calls.push_back(current_packed_primitive);
251
252 current_packed_primitive.offset = 0;
253 current_packed_primitive.size = 0;
254 }
255 }
256 else
257 {
258 if (is_active)
259 {
260 current_packed_primitive.offset = primitive_data.offset;
261 current_packed_primitive.size = primitive_data.size;
262 }
263 }
264
265 last_primitive_active = is_active;
266
267 ++i;
268 }
269
270 if (last_primitive_active)
271 {
272 // Append the last primitive
273 primitive_render_calls.push_back(current_packed_primitive);
274 }
275
276 glBindVertexArray(_vao);
277
278 for (const auto& it : primitive_render_calls)
279 {
280 glDrawElements(mode, it.size, _index_type, reinterpret_cast<void*>(it.offset * _index_size));
281 }
282 }
283
289 {
290 assert(primitives.size() && "If this triggers, you forgot to add primitives to mesh, maybe you meant to renderArrays instead?");
291
292 glBindVertexArray(_vao);
293
294 size_t total_size = 0;
295
296 for (const auto& it : primitives)
297 {
298 total_size += it.size;
299 }
300
301 glDrawElements(mode, total_size, _index_type, nullptr);
302 }
303
307 std::vector<oe::scene::Primitive> primitives;
308
309 private:
310 uint32_t _index_type = 0;
311 uint8_t _index_size = 0;
312
313 uint32_t _vao;
314 uint32_t _vbo;
315 uint32_t _ebo;
316
317 template <typename SceneMeshType>
318 void _common_construct(
319 const size_t vertices_count, const void* vertices_data,
320 const size_t indices_count, const void* indices_data,
321 const bool editable)
322 {
323 _index_type = (_index_size == 1) ? GL_UNSIGNED_BYTE
324 : (_index_size == 2) ? GL_UNSIGNED_SHORT
325 : GL_UNSIGNED_INT
326 ;
327
328 glCreateVertexArrays(1, &_vao);
329
330 std::array<uint32_t, 2> buffers;
331
332 glCreateBuffers(2, buffers.data());
333
334 _vbo = buffers[0];
335 _ebo = buffers[1];
336
337 VertexAttributes vertex_attributes(_vao);
338 vertex_attributes.bindVertexAttributes<typename SceneMeshType::vertex_type>();
339
340 size_t vertex_size = sizeof(typename SceneMeshType::vertex_type);
341
342 if (editable)
343 {
344 glNamedBufferStorage(_vbo, vertex_size * vertices_count, vertices_data, GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT);
345 glNamedBufferStorage(_ebo, _index_size * indices_count, indices_data, GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT);
346 }
347 else
348 {
349 glNamedBufferStorage(_vbo, vertex_size * vertices_count, vertices_data, 0);
350 glNamedBufferStorage(_ebo, _index_size * indices_count, indices_data, 0);
351 }
352
353 glVertexArrayVertexBuffer(_vao, 0, _vbo, 0, vertex_size);
354 glVertexArrayElementBuffer(_vao, _ebo);
355 }
356 };
357}
358
359#include "mesh.inl"
360
361#endif
static bool hasContext()
Check if this thread has an OpenGL context.
Definition opengl.h:88
Definition mesh.h:80
void renderAll(uint32_t mode=default_mesh_rendering_mode)
Definition mesh.h:288
std::pair< void *, void * > getRawBuffers()
Get raw GPU buffers of the mesh (to write data).
Definition mesh.h:173
void setIndicesData(const uint32_t size, const void *data, const uint32_t offset=0)
Definition mesh.h:161
void setSubBufferData(const uint32_t size, const void *data, const uint32_t offset=0)
Definition mesh.h:153
Mesh(const SceneMeshType &, uint32_t max_vertices_count, uint32_t max_indices_count)
Allocate a mesh to be dynamically filled.
Definition mesh.h:111
Mesh(const SceneMeshType &scene_mesh, bool editable=false)
Construct a mesh from an existing scene mesh.
Definition mesh.h:88
void render(const std::vector< bool > &activeprimitives, uint32_t mode=default_mesh_rendering_mode)
Ask the GPU to render specific primitives of the mesh.
Definition mesh.h:226
void renderElements(const uint32_t count, const uint32_t offset, const uint32_t mode)
Definition mesh.h:215
void renderArrays(const uint32_t count, const uint32_t offset, uint32_t mode)
Definition mesh.h:202
void releaseRawBuffers()
Release raw buffers got by getRawBuffers.
Definition mesh.h:189
std::vector< oe::scene::Primitive > primitives
mesh parts
Definition mesh.h:307
Render related abstractions (Shader, Framebuffer, Cubemaps, Textures).
Definition opengl.h:12
constexpr const uint8_t default_mesh_rendering_mode
Default way to render the mesh vertices as filled triangles.
Definition mesh.h:77
Definition mesh.h:13
int32_t getComponentSize() noexcept
Return the number of components in T.
void bindVertexAttributeToIPointer(const uint32_t index, const size_t offset) noexcept
Enable and bind a vertex attribute of type T to the location, and fill value from offset in structure...
Definition mesh.h:68
void bindVertexAttributeToPointer(const uint32_t index, const size_t offset) noexcept
Enable and bind a vertex attribute of type T to the location, and fill value from offset in structure...
Definition mesh.h:56
void bindVertexAttributes()
Bind vertex array attributes to stored vertex array based on the vertex type.
Part of a mesh (used to separate mesh materials for example).
Definition mesh.h:20