use wgpu::util::DeviceExt;
pub struct Mesh {
vertex_buffer: wgpu::Buffer,
vertex_buffer_len: usize,
vertex_indices: Option<(wgpu::Buffer, usize)>,
}
impl Mesh {
pub fn new<V: bytemuck::Pod>(
device: &wgpu::Device,
label: Option<&str>,
vertices: impl IntoIterator<Item = V>,
may_indices: Option<impl IntoIterator<Item = u16>>,
) -> Self {
let vertices = vertices.into_iter().collect::<Vec<_>>();
let vertex_buffer_len = vertices.len();
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label,
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let vertex_indices = if let Some(indices) = may_indices {
let indices = indices.into_iter().collect::<Vec<_>>();
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label,
contents: bytemuck::cast_slice(&indices),
usage: wgpu::BufferUsages::INDEX,
});
Some((index_buffer, indices.len()))
} else {
None
};
Self {
vertex_buffer,
vertex_buffer_len,
vertex_indices,
}
}
pub fn from_vertices<V: bytemuck::Pod>(
device: &wgpu::Device,
label: Option<&str>,
vertices: impl IntoIterator<Item = V>,
) -> Self {
Self::new(device, label, vertices, None as Option<Vec<u16>>)
}
pub fn draw<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
match &self.vertex_indices {
Some((index_buffer, len)) => {
render_pass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.draw_indexed(0..*len as u32, 0, 0..1);
}
None => {
render_pass.draw(0..self.vertex_buffer_len as u32, 0..1);
}
}
}
pub fn update<V: bytemuck::Pod>(
&mut self,
device: &wgpu::Device,
label: Option<&str>,
vertices: impl IntoIterator<Item = V>,
may_indices: Option<impl IntoIterator<Item = u16>>,
) {
let vertices = vertices.into_iter().collect::<Vec<_>>();
self.vertex_buffer_len = vertices.len();
self.vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label,
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsages::VERTEX,
});
self.vertex_indices = if let Some(indices) = may_indices {
let indices = indices.into_iter().collect::<Vec<_>>();
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label,
contents: bytemuck::cast_slice(&indices),
usage: wgpu::BufferUsages::INDEX,
});
Some((buffer, indices.len()))
} else {
None
};
}
}