1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
use opengl_bindings::buffer::{Buffer as GlBuffer, Usage as GlBufferUsage};
use opengl_bindings::vertex_array::{
DataType as GlVertexArrayDataType,
VertexArray as GlVertexArray,
};
use opengl_bindings::CurrentContextWithFns as GlCurrentContextWithFns;
use crate::mesh::Mesh;
use crate::renderer::opengl::vertex::{
AttributeComponentType as VertexAttributeComponentType,
Vertex as RendererVertex,
};
#[derive(Debug)]
pub struct GraphicsMesh
{
/// Vertex and index buffer has to live as long as the vertex array
_vertex_buffer: GlBuffer<RendererVertex>,
pub index_buffer: Option<GlBuffer<u32>>,
pub element_cnt: u32,
pub vertex_arr: GlVertexArray,
}
impl GraphicsMesh
{
#[tracing::instrument(skip_all)]
pub fn new(
current_context: &GlCurrentContextWithFns<'_>,
mesh: &Mesh,
) -> Result<Self, Error>
{
tracing::trace!(
"Creating vertex array, vertex buffer{}",
if mesh.indices().is_some() {
" and index buffer"
} else {
""
}
);
let vertex_arr = GlVertexArray::new(current_context);
let vertex_buffer = GlBuffer::new(current_context);
vertex_buffer
.store_mapped(
current_context,
mesh.vertices(),
GlBufferUsage::Static,
|vertex| RendererVertex {
pos: vertex.pos.into(),
texture_coords: vertex.texture_coords.into(),
normal: vertex.normal.into(),
},
)
.map_err(Error::StoreVerticesFailed)?;
vertex_arr.bind_vertex_buffer(current_context, 0, &vertex_buffer, 0);
let mut offset = 0u32;
for attrib in RendererVertex::attrs() {
vertex_arr.enable_attrib(current_context, attrib.index);
vertex_arr.set_attrib_format(
current_context,
attrib.index,
match attrib.component_type {
VertexAttributeComponentType::Float => GlVertexArrayDataType::Float,
},
false,
offset,
);
vertex_arr.set_attrib_vertex_buf_binding(current_context, attrib.index, 0);
offset += attrib.component_size * attrib.component_cnt as u32;
}
if let Some(indices) = mesh.indices() {
let index_buffer = GlBuffer::new(current_context);
index_buffer
.store(current_context, indices, GlBufferUsage::Static)
.map_err(Error::StoreIndicesFailed)?;
vertex_arr.bind_element_buffer(current_context, &index_buffer);
return Ok(Self {
_vertex_buffer: vertex_buffer,
index_buffer: Some(index_buffer),
element_cnt: indices
.len()
.try_into()
.expect("Mesh index count does not fit into a 32-bit unsigned int"),
vertex_arr,
});
}
Ok(Self {
_vertex_buffer: vertex_buffer,
index_buffer: None,
element_cnt: mesh
.vertices()
.len()
.try_into()
.expect("Mesh vertex count does not fit into a 32-bit unsigned int"),
vertex_arr,
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error
{
#[error("Failed to store vertices in vertex buffer")]
StoreVerticesFailed(#[source] opengl_bindings::buffer::Error),
#[error("Failed to store indices in index buffer")]
StoreIndicesFailed(#[source] opengl_bindings::buffer::Error),
}
|