use crate::{ffi, mbvh, Error};
use std::fmt::Debug;
pub struct PrimitiveIter {
primitive_base_index: u32,
child_meta: [u8; 8],
curr_meta_idx: u8,
curr_tri_count: u8,
}
impl PrimitiveIter {
fn new(base_index: u32, meta: [u8; 8]) -> Self {
Self {
primitive_base_index: base_index,
child_meta: meta,
curr_meta_idx: 0,
curr_tri_count: 0,
}
}
}
impl Iterator for PrimitiveIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.curr_meta_idx as usize >= self.child_meta.len() {
return None;
}
while self.curr_meta_idx < self.child_meta.len() as u8 {
let meta = self.child_meta[self.curr_meta_idx as usize];
let triangles_count = (meta & 0b11100000).count_ones() as u8;
let current_tri_count = self.curr_tri_count;
self.curr_tri_count += 1;
if current_tri_count < triangles_count {
let start = meta & 0b00011111;
return Some(self.primitive_base_index + start as u32 + current_tri_count as u32);
}
self.curr_meta_idx += 1;
self.curr_tri_count = 0;
}
None
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Node {
pub min: [f32; 3],
pub exyz: [u8; 3],
pub imask: u8,
pub child_base_idx: u32,
pub primitive_base_idx: u32,
pub child_meta: [u8; 8],
pub qlo_x: [u8; 8],
pub qlo_y: [u8; 8],
pub qlo_z: [u8; 8],
pub qhi_x: [u8; 8],
pub qhi_y: [u8; 8],
pub qhi_z: [u8; 8],
}
impl Node {
pub fn is_leaf(&self) -> bool {
self.imask == 0
}
pub fn primitives(&self) -> PrimitiveIter {
if !self.is_leaf() {
return PrimitiveIter::new(0, [0, 0, 0, 0, 0, 0, 0, 0]);
}
PrimitiveIter::new(self.primitive_base_idx, self.child_meta)
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Primitive {
pub edge_1: [f32; 3],
pub padding_0: u32,
pub edge_2: [f32; 3],
pub padding_1: u32,
pub vertex_0: [f32; 3],
pub original_primitive: u32,
}
impl Debug for Primitive {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("cwbvh::Primitive")
.field("vertex_0", &self.vertex_0)
.field("edge_1", &self.edge_1)
.field("edge_2", &self.edge_2)
.field("original_primitive", &self.original_primitive)
.finish()
}
}
pub struct BVH {
inner: cxx::UniquePtr<ffi::BVH8_CWBVH>,
}
impl BVH {
pub fn new(original: &mbvh::BVH) -> Result<Self, Error> {
let bvh = BVH {
inner: ffi::CWBVH_new(),
};
bvh.convert(original)
}
pub fn convert(mut self, original: &mbvh::BVH) -> Result<Self, Error> {
Error::validate_leaf_count(3, original.max_primitives_per_leaf)?;
self.inner
.pin_mut()
.ConvertFrom(original.inner.as_ref().unwrap(), true);
Ok(self)
}
pub fn nodes(&self) -> &[Node] {
let ptr = ffi::CWBVH_nodes(&self.inner) as *const Node;
let count = ffi::CWBVH_nodes_count(&self.inner);
unsafe { std::slice::from_raw_parts(ptr, count as usize) }
}
pub fn primitives(&self) -> &[Primitive] {
let ptr = ffi::CWBVH_primitives(&self.inner) as *const Primitive;
let count = ffi::CWBVH_primitives_count(&self.inner);
unsafe { std::slice::from_raw_parts(ptr, count as usize) }
}
}