1use super::{
2 buffer::{Buffer, BufferType, MappedBuffer, Usage},
3 vertex::{Vertex, VertexFormat},
4 Context,
5};
6
7fn to_bytes<'a, V>(data: &'a [V]) -> &'a [u8]
11where
12 V: Sized,
13{
14 unsafe {
15 std::slice::from_raw_parts::<'a, u8>(
16 data.as_ptr() as *const _,
17 data.len() * std::mem::size_of::<V>(),
18 )
19 }
20}
21
22fn from_bytes<'a, V>(data: &'a [u8]) -> &'a [V]
23where
24 V: Sized,
25{
26 unsafe {
27 std::slice::from_raw_parts::<'a, V>(
28 data.as_ptr() as *const _,
29 data.len() / std::mem::size_of::<V>(),
30 )
31 }
32}
33
34fn set_buffer<T>(buffer: &mut MappedBuffer, data: &[T], offset: usize)
35where
36 T: Sized,
37{
38 buffer.write(to_bytes(data), offset * std::mem::size_of::<T>());
39}
40
41fn get_buffer<T>(buffer: &MappedBuffer) -> &[T]
42where
43 T: Sized,
44{
45 from_bytes(buffer.memory_map())
46}
47
48pub type BindingInfo<'a> = (&'a VertexFormat, usize, u32, super::BufferKey, BufferType);
49
50#[derive(Debug, PartialEq, Clone)]
111pub struct VertexMesh<V> {
112 vbo: Buffer,
113 draw_range: Option<std::ops::Range<usize>>,
114 draw_mode: super::DrawMode,
115 type_marker: std::marker::PhantomData<V>,
116}
117
118impl<V> VertexMesh<V>
119where
120 V: Vertex,
121{
122 pub fn new(ctx: &mut Context, size: usize) -> Result<Self, super::GraphicsError> {
124 let vbo = Buffer::new(
125 ctx,
126 size * std::mem::size_of::<V>(),
127 BufferType::Vertex,
128 Usage::Dynamic,
129 )?;
130 Ok(Self::with_buffer(vbo))
131 }
132
133 pub fn with_data(ctx: &mut Context, vertices: &[V]) -> Result<Self, super::GraphicsError> {
134 let vbo = Buffer::with_data(ctx, to_bytes(vertices), BufferType::Vertex, Usage::Dynamic)?;
135 Ok(Self::with_buffer(vbo))
136 }
137
138 pub fn with_buffer(buffer: Buffer) -> Self {
139 Self {
140 vbo: buffer,
141 draw_range: None,
142 draw_mode: super::DrawMode::Triangles,
143 type_marker: std::marker::PhantomData,
144 }
145 }
146
147 pub fn set_vertices(&self, ctx: &mut super::Context, vertices: &[V], offset: usize) {
149 ctx.bind_buffer(self.vbo.handle(), self.vbo.buffer_type());
150 ctx.buffer_static_draw(
151 &self.vbo,
152 to_bytes(vertices),
153 offset * std::mem::size_of::<V>(),
154 )
155 }
156
157 pub fn set_draw_range(&mut self, draw_range: Option<std::ops::Range<usize>>) {
159 self.draw_range = draw_range;
160 }
161
162 pub fn set_draw_mode(&mut self, draw_mode: super::DrawMode) {
164 self.draw_mode = draw_mode;
165 }
166
167 pub fn draw_range(&self) -> std::ops::Range<usize> {
168 self.draw_range.clone().unwrap_or(0..(self.len()))
169 }
170
171 pub fn draw_mode(&self) -> super::DrawMode {
172 self.draw_mode
173 }
174
175 pub fn len(&self) -> usize {
176 self.vbo.size() / std::mem::size_of::<V>()
177 }
178}
179
180#[derive(Debug, PartialEq)]
181pub struct MappedVertexMesh<V> {
182 inner: VertexMesh<V>,
183 memory_map: MappedBuffer,
184}
185
186impl<V> MappedVertexMesh<V>
187where
188 V: Vertex,
189{
190 pub fn new(ctx: &mut super::Context, size: usize) -> Result<Self, super::GraphicsError> {
191 let inner = VertexMesh::new(ctx, size)?;
192 let memory_map =
193 MappedBuffer::with_shape(inner.vbo.clone(), [size * std::mem::size_of::<V>()]);
194 Ok(Self { inner, memory_map })
195 }
196
197 pub fn set_vertices(&mut self, vertices: &[V], offset: usize) {
198 set_buffer(&mut self.memory_map, vertices, offset)
199 }
200
201 pub fn get_vertices(&self) -> &[V] {
202 get_buffer(&self.memory_map)
203 }
204
205 pub fn unmap(&mut self, ctx: &mut super::Context) -> &VertexMesh<V> {
206 self.memory_map.unmap(ctx);
207 self.inner()
208 }
209
210 pub fn inner(&self) -> &VertexMesh<V> {
211 &self.inner
212 }
213}
214
215#[derive(Debug, PartialEq, Clone)]
220pub struct IndexedMesh<V, I> {
221 mesh: VertexMesh<V>,
222 ibo: Buffer,
223 type_marker: std::marker::PhantomData<I>,
224}
225
226impl<V, I> IndexedMesh<V, I>
227where
228 V: Vertex,
229 I: Index,
230{
231 pub fn new(
233 ctx: &mut Context,
234 vertex_count: usize,
235 index_count: usize,
236 ) -> Result<Self, super::GraphicsError> {
237 let ibo = Buffer::new(
238 ctx,
239 index_count * std::mem::size_of::<I>(),
240 BufferType::Index,
241 Usage::Dynamic,
242 )?;
243 let mesh = VertexMesh::new(ctx, vertex_count)?;
244 Ok(Self {
245 mesh,
246 ibo,
247 type_marker: std::marker::PhantomData,
248 })
249 }
250
251 pub fn with_data(
252 ctx: &mut Context,
253 vertices: &[V],
254 indices: &[I],
255 ) -> Result<Self, super::GraphicsError> {
256 let ibo = Buffer::with_data(ctx, to_bytes(indices), BufferType::Index, Usage::Dynamic)?;
257 let mesh = VertexMesh::with_data(ctx, vertices)?;
258 Ok(Self {
259 mesh,
260 ibo,
261 type_marker: std::marker::PhantomData,
262 })
263 }
264
265 pub fn with_mesh(
267 ctx: &mut Context,
268 mesh: VertexMesh<V>,
269 index_count: usize,
270 ) -> Result<Self, super::GraphicsError> {
271 let ibo = Buffer::new(
272 ctx,
273 index_count * std::mem::size_of::<I>(),
274 BufferType::Index,
275 mesh.vbo.usage(),
276 )?;
277 Ok(Self {
278 mesh,
279 ibo,
280 type_marker: std::marker::PhantomData,
281 })
282 }
283
284 pub fn set_vertices(&self, ctx: &mut Context, vertices: &[V], offset: usize) {
286 self.mesh.set_vertices(ctx, vertices, offset)
287 }
288
289 pub fn set_indices(&self, ctx: &mut Context, indices: &[I], offset: usize) {
291 ctx.bind_buffer(self.ibo.handle(), self.ibo.buffer_type());
292 ctx.buffer_static_draw(
293 &self.ibo,
294 to_bytes(indices),
295 offset * std::mem::size_of::<I>(),
296 )
297 }
298
299 pub fn set_draw_range(&mut self, draw_range: Option<std::ops::Range<usize>>) {
300 self.mesh.set_draw_range(draw_range)
301 }
302
303 pub fn draw_range(&self) -> std::ops::Range<usize> {
304 self.mesh
305 .draw_range
306 .clone()
307 .unwrap_or(0..(self.ibo.size() / std::mem::size_of::<I>()))
308 }
309
310 pub fn set_draw_mode(&mut self, draw_mode: super::DrawMode) {
311 self.mesh.set_draw_mode(draw_mode)
312 }
313
314 pub fn len(&self) -> usize {
315 self.ibo.size() / std::mem::size_of::<I>()
316 }
317}
318
319#[derive(Debug, PartialEq)]
320pub struct MappedIndexedMesh<V, I> {
321 inner: IndexedMesh<V, I>,
322 vbo: MappedBuffer,
323 ibo: MappedBuffer,
324}
325
326impl<V, I> MappedIndexedMesh<V, I>
327where
328 V: Vertex,
329 I: Index,
330{
331 pub fn new(
332 gl: &mut Context,
333 vertex_count: usize,
334 index_count: usize,
335 ) -> Result<Self, super::GraphicsError> {
336 let inner = IndexedMesh::new(gl, vertex_count, index_count)?;
337 let vbo = MappedBuffer::with_shape(inner.mesh.vbo.clone(), inner.mesh.vbo.size());
338 let ibo = MappedBuffer::with_shape(inner.ibo.clone(), inner.ibo.size());
339 Ok(Self { inner, vbo, ibo })
340 }
341
342 pub fn with_data(
343 ctx: &mut Context,
344 vertices: Vec<V>,
345 indices: Vec<I>,
346 ) -> Result<Self, super::GraphicsError> {
347 let inner = IndexedMesh::with_data(ctx, &vertices, &indices)?;
348 let vbo = MappedBuffer::from_vec(inner.mesh.vbo.clone(), unsafe {
349 let mut vertices = std::mem::ManuallyDrop::new(vertices);
350 Vec::from_raw_parts(
351 vertices.as_mut_ptr() as *mut _,
352 vertices.len() * std::mem::size_of::<V>(),
353 vertices.capacity() * std::mem::size_of::<V>(),
354 )
355 });
356 let ibo = MappedBuffer::from_vec(inner.ibo.clone(), unsafe {
357 let mut indices = std::mem::ManuallyDrop::new(indices);
358 Vec::from_raw_parts(
359 indices.as_mut_ptr() as *mut _,
360 indices.len() * std::mem::size_of::<I>(),
361 indices.capacity() * std::mem::size_of::<I>(),
362 )
363 });
364 Ok(Self { inner, vbo, ibo })
365 }
366
367 pub fn vertex_capacity(&self) -> usize {
368 self.vbo.memory_map.len() / std::mem::size_of::<V>()
369 }
370
371 pub fn index_capacity(&self) -> usize {
372 self.ibo.memory_map.len() / std::mem::size_of::<I>()
373 }
374
375 pub fn set_draw_range(&mut self, draw_range: Option<std::ops::Range<usize>>) {
376 self.inner.set_draw_range(draw_range)
377 }
378
379 pub fn draw_range(&self) -> std::ops::Range<usize> {
380 self.inner.draw_range()
381 }
382
383 pub fn set_vertices(&mut self, vertices: &[V], offset: usize) {
384 set_buffer(&mut self.vbo, vertices, offset)
385 }
386
387 pub fn get_vertices(&self) -> &[V] {
388 get_buffer(&self.vbo)
389 }
390
391 pub fn set_indices(&mut self, indices: &[I], offset: usize) {
392 set_buffer(&mut self.ibo, indices, offset)
393 }
394
395 pub fn get_indices(&self) -> &[I] {
396 get_buffer(&self.ibo)
397 }
398
399 pub fn unmap(&mut self, ctx: &mut Context) -> &IndexedMesh<V, I> {
400 self.vbo.unmap(ctx);
401 self.ibo.unmap(ctx);
402 self.inner()
403 }
404
405 pub fn inner(&self) -> &IndexedMesh<V, I> {
406 &self.inner
407 }
408}
409
410#[derive(Clone, Debug, PartialEq, Eq)]
411pub struct AttachedAttributes<'a> {
412 pub buffer: &'a Buffer,
413 pub formats: &'a [VertexFormat],
414 pub step: u32,
415 pub stride: usize,
416}
417
418pub trait Mesh {
419 fn attachments(&self) -> Vec<AttachedAttributes>;
420 fn draw(
421 &self,
422 ctx: &mut super::Context,
423 draw_range: std::ops::Range<usize>,
424 draw_mode: super::DrawMode,
425 instance_count: usize,
426 );
427}
428
429impl<V: Vertex> Mesh for VertexMesh<V> {
430 fn attachments(&self) -> Vec<AttachedAttributes> {
431 vec![AttachedAttributes {
432 buffer: &self.vbo,
433 formats: V::build_bindings(),
434 step: 0,
435 stride: std::mem::size_of::<V>(),
436 }]
437 }
438
439 fn draw(
440 &self,
441 ctx: &mut super::Context,
442 draw_range: std::ops::Range<usize>,
443 draw_mode: super::DrawMode,
444 instance_count: usize,
445 ) {
446 if draw_range.start >= draw_range.end {
447 return;
448 }
449
450 let (count, offset) = (
451 (draw_range.end - draw_range.start) as i32,
452 draw_range.start as i32,
453 );
454 if instance_count > 1 {
455 ctx.draw_arrays_instanced(draw_mode, offset, count, instance_count as i32);
456 } else {
457 ctx.draw_arrays(draw_mode, offset, count);
458 }
459 }
460}
461
462impl<V: Vertex> Mesh for &VertexMesh<V> {
463 fn attachments(&self) -> Vec<AttachedAttributes> {
464 VertexMesh::attachments(self)
465 }
466
467 fn draw(
468 &self,
469 ctx: &mut super::Context,
470 draw_range: std::ops::Range<usize>,
471 draw_mode: super::DrawMode,
472 instance_count: usize,
473 ) {
474 VertexMesh::draw(self, ctx, draw_range, draw_mode, instance_count)
475 }
476}
477
478impl<V: Vertex, I: Index> Mesh for IndexedMesh<V, I> {
479 fn attachments(&self) -> Vec<AttachedAttributes> {
480 self.mesh.attachments()
481 }
482
483 fn draw(
484 &self,
485 ctx: &mut super::Context,
486 draw_range: std::ops::Range<usize>,
487 draw_mode: super::DrawMode,
488 instance_count: usize,
489 ) {
490 if draw_range.start >= draw_range.end {
491 return;
492 }
493
494 let (count, offset) = (
495 (draw_range.end - draw_range.start) as i32,
496 draw_range.start as i32,
497 );
498
499 let ibo = &self.ibo;
500 ctx.bind_buffer(ibo.handle(), ibo.buffer_type());
501 if instance_count > 1 {
502 ctx.draw_elements_instanced(
503 draw_mode,
504 count,
505 I::GL_TYPE,
506 offset,
507 instance_count as i32,
508 );
509 } else {
510 ctx.draw_elements(draw_mode, count, I::GL_TYPE, offset);
511 }
512 }
513}
514
515impl<V: Vertex, I: Index> Mesh for &IndexedMesh<V, I> {
516 fn attachments(&self) -> Vec<AttachedAttributes> {
517 IndexedMesh::attachments(self)
518 }
519
520 fn draw(
521 &self,
522 ctx: &mut super::Context,
523 draw_range: std::ops::Range<usize>,
524 draw_mode: super::DrawMode,
525 instance_count: usize,
526 ) {
527 IndexedMesh::draw(self, ctx, draw_range, draw_mode, instance_count)
528 }
529}
530
531#[derive(Debug, Clone, PartialEq, Eq)]
532pub struct MultiMesh<'a> {
533 ibo: Option<(&'a Buffer, u32)>,
534 attachments: Vec<AttachedAttributes<'a>>,
535}
536
537impl<'a> Mesh for MultiMesh<'a> {
538 fn attachments(&self) -> Vec<AttachedAttributes> {
539 self.attachments.clone()
540 }
541
542 fn draw(
543 &self,
544 ctx: &mut Context,
545 draw_range: std::ops::Range<usize>,
546 draw_mode: super::DrawMode,
547 instance_count: usize,
548 ) {
549 match self.ibo {
550 None => {
551 if draw_range.start >= draw_range.end {
552 return;
553 }
554
555 let (count, offset) = (
556 (draw_range.end - draw_range.start) as i32,
557 draw_range.start as i32,
558 );
559 if instance_count > 1 {
560 ctx.draw_arrays_instanced(draw_mode, offset, count, instance_count as i32);
561 } else {
562 ctx.draw_arrays(draw_mode, offset, count);
563 }
564 }
565 Some((ibo, element_type)) => {
566 if draw_range.start >= draw_range.end {
567 return;
568 }
569
570 let (count, offset) = (
571 (draw_range.end - draw_range.start) as i32,
572 draw_range.start as i32,
573 );
574
575 ctx.bind_buffer(ibo.handle(), ibo.buffer_type());
576 if instance_count > 1 {
577 ctx.draw_elements_instanced(
578 draw_mode,
579 count,
580 element_type,
581 offset,
582 instance_count as i32,
583 );
584 } else {
585 ctx.draw_elements(draw_mode, count, element_type, offset);
586 }
587 }
588 }
589 }
590}
591
592impl Mesh for &MultiMesh<'_> {
593 fn attachments(&self) -> Vec<AttachedAttributes> {
594 MultiMesh::attachments(self)
595 }
596
597 fn draw(
598 &self,
599 ctx: &mut Context,
600 draw_range: std::ops::Range<usize>,
601 draw_mode: crate::DrawMode,
602 instance_count: usize,
603 ) {
604 MultiMesh::draw(self, ctx, draw_range, draw_mode, instance_count)
605 }
606}
607
608pub trait MeshAttacher: Mesh {
609 fn attach<'a, T: Mesh>(&'a self, other: &'a T) -> MultiMesh<'a> {
610 Self::attach_with_step(self, other, 0)
611 }
612
613 fn attach_with_step<'a, T: Mesh>(&'a self, other: &'a T, step: u32) -> MultiMesh<'a>;
614}
615
616impl<V: Vertex> MeshAttacher for VertexMesh<V> {
617 fn attach_with_step<'a, T: Mesh>(&'a self, other: &'a T, step: u32) -> MultiMesh<'a> {
618 let mut attachments = self.attachments();
619 attachments.extend(other.attachments().into_iter().map(|mut a| {
620 a.step = step;
621 a
622 }));
623 MultiMesh {
624 ibo: None,
625 attachments,
626 }
627 }
628}
629impl<V: Vertex, I: Index> MeshAttacher for IndexedMesh<V, I> {
630 fn attach_with_step<'a, T: Mesh>(&'a self, other: &'a T, step: u32) -> MultiMesh<'a> {
631 let mut attachments = self.attachments();
632 attachments.extend(other.attachments().into_iter().map(|mut a| {
633 a.step = step;
634 a
635 }));
636 MultiMesh {
637 ibo: Some((&self.ibo, I::GL_TYPE)),
638 attachments,
639 }
640 }
641}
642
643pub trait Index {
644 const GL_TYPE: u32;
645}
646
647impl Index for u32 {
648 const GL_TYPE: u32 = glow::UNSIGNED_INT;
649}
650
651impl Index for u16 {
652 const GL_TYPE: u32 = glow::UNSIGNED_SHORT;
653}