56 lines
2.0 KiB
Rust
56 lines
2.0 KiB
Rust
use super::{MeshInstance, MeshPool};
|
|
use std::collections::HashMap;
|
|
|
|
pub struct MeshCommands {
|
|
transforms: Vec<[f32; 16]>,
|
|
transform_ranges: Vec<(usize, std::ops::Range<u32>)>,
|
|
}
|
|
|
|
impl MeshCommands {
|
|
pub fn build(instances: &Vec<MeshInstance>) -> Self {
|
|
let mut sorted_meshes = HashMap::<usize, Vec<MeshInstance>>::new();
|
|
for mesh in instances.iter() {
|
|
let group_id = mesh.handle.group_id;
|
|
if let Some(by_group) = sorted_meshes.get_mut(&group_id) {
|
|
by_group.push(*mesh);
|
|
} else {
|
|
sorted_meshes.insert(group_id, vec![*mesh]);
|
|
}
|
|
}
|
|
|
|
let mut transforms = Vec::new();
|
|
let mut transform_ranges = Vec::new();
|
|
|
|
// this code assumes MeshHandle only uses group_id (which it does for now)
|
|
// TODO bucket by sub_id too before MeshHandle supports it
|
|
for (group_id, meshes) in sorted_meshes.iter() {
|
|
let start_idx = transforms.len() as u32;
|
|
let as_arrays = meshes.iter().map(|i| i.transform.to_cols_array());
|
|
transforms.extend(as_arrays);
|
|
let end_idx = transforms.len() as u32;
|
|
transform_ranges.push((*group_id, start_idx..end_idx));
|
|
}
|
|
|
|
Self {
|
|
transforms,
|
|
transform_ranges,
|
|
}
|
|
}
|
|
|
|
pub fn get_storage(&self) -> &[u8] {
|
|
bytemuck::cast_slice(&self.transforms)
|
|
}
|
|
|
|
pub fn dispatch<'a>(&self, rp: &mut wgpu::RenderPass<'a>, mesh_pool: &'a MeshPool) {
|
|
// TODO one group per mesh, still...
|
|
// TODO this could be implemented without accessing private members
|
|
for (group_id, meshes_range) in self.transform_ranges.iter() {
|
|
let group = mesh_pool.groups.get(*group_id).unwrap();
|
|
rp.set_vertex_buffer(0, group.vertices.slice(..));
|
|
rp.set_index_buffer(group.indices.slice(..), wgpu::IndexFormat::Uint32);
|
|
let indices = 0..(group.index_capacity as u32);
|
|
rp.draw_indexed(indices, 0, meshes_range.to_owned());
|
|
}
|
|
}
|
|
}
|