use encase::ShaderType;
use rapier::geometry::TriMesh;
use rapier::prelude::{DIM, Point};
#[derive(Copy, Clone, ShaderType)]
pub struct GpuTriMesh {
pub bvh_vtx_root_id: u32,
pub bvh_idx_root_id: u32,
pub bvh_node_len: u32,
pub num_triangles: u32,
pub num_vertices: u32,
}
pub fn convert_trimesh_to_gpu(
shape: &TriMesh,
vertices: &mut Vec<Point<f32>>,
indices: &mut Vec<u32>,
) -> GpuTriMesh {
let bvh_vtx_root_id = vertices.len();
let bvh_idx_root_id = indices.len();
struct BvhObject {
aabb: bvh::aabb::Aabb<f32, DIM>,
node_index: usize,
}
impl bvh::aabb::Bounded<f32, DIM> for BvhObject {
fn aabb(&self) -> bvh::aabb::Aabb<f32, DIM> {
self.aabb
}
}
impl bvh::bounding_hierarchy::BHShape<f32, DIM> for BvhObject {
fn set_bh_node_index(&mut self, index: usize) {
self.node_index = index;
}
fn bh_node_index(&self) -> usize {
self.node_index
}
}
let mut objects: Vec<_> = shape
.triangles()
.map(|tri| {
let aabb = tri.local_aabb();
BvhObject {
aabb: bvh::aabb::Aabb::with_bounds(aabb.mins, aabb.maxs),
node_index: 0,
}
})
.collect();
let bvh = bvh::bvh::Bvh::build(&mut objects);
let flat_bvh = bvh.flatten();
vertices.extend(flat_bvh.iter().flat_map(|n| [n.aabb.min, n.aabb.max]));
let bvh_node_len = flat_bvh.len();
indices.extend(
flat_bvh
.iter()
.flat_map(|n| [n.entry_index, n.exit_index, n.shape_index]),
);
#[cfg(feature = "dim3")]
{
let pn = shape
.pseudo_normals()
.expect("trimeshes without pseudo-normals are not supported");
vertices.extend_from_slice(shape.vertices());
vertices.extend(pn.vertices_pseudo_normal.iter().map(|n| Point::from(*n)));
assert_eq!(shape.vertices().len(), pn.vertices_pseudo_normal.len());
vertices.extend(
pn.edges_pseudo_normal
.iter()
.flat_map(|n| n.map(Point::from)),
);
}
indices.extend(shape.indices().iter().flat_map(|tri| tri.iter().copied()));
GpuTriMesh {
bvh_vtx_root_id: bvh_vtx_root_id as u32,
bvh_idx_root_id: bvh_idx_root_id as u32,
bvh_node_len: bvh_node_len as u32,
num_triangles: shape.indices().len() as u32,
num_vertices: shape.vertices().len() as u32,
}
}