use embree3::{
Allocator, BuildConfig, BuildPrimitive, BuildQuality, BvhBuilder, BvhNode, ChildBounds,
Children, Device, Error,
};
#[derive(Clone, Copy)]
struct Scalar(u32);
unsafe impl BvhNode for Scalar {}
#[derive(Clone, Copy)]
struct ZstNode;
unsafe impl BvhNode for ZstNode {}
struct Wide;
impl BvhBuilder for Wide {
type Node<'id> = Scalar;
const MAX_CHILDREN: usize = 17;
fn create_node<'id>(&self, a: &Allocator<'id>, _n: usize) -> &'id mut Scalar {
a.alloc(Scalar(0))
}
fn set_children<'id>(&self, _n: &mut Scalar, _c: Children<'id, Scalar>) {}
fn set_bounds<'id>(&self, _n: &mut Scalar, _b: ChildBounds<'_>) {}
fn create_leaf<'id>(&self, a: &Allocator<'id>, _p: &[BuildPrimitive]) -> &'id mut Scalar {
a.alloc(Scalar(0))
}
}
struct Narrow;
impl BvhBuilder for Narrow {
type Node<'id> = Scalar;
const MAX_CHILDREN: usize = 2;
fn create_node<'id>(&self, a: &Allocator<'id>, _n: usize) -> &'id mut Scalar {
a.alloc(Scalar(0))
}
fn set_children<'id>(&self, _n: &mut Scalar, _c: Children<'id, Scalar>) {}
fn set_bounds<'id>(&self, _n: &mut Scalar, _b: ChildBounds<'_>) {}
fn create_leaf<'id>(&self, a: &Allocator<'id>, _p: &[BuildPrimitive]) -> &'id mut Scalar {
a.alloc(Scalar(0))
}
}
struct Zst;
impl BvhBuilder for Zst {
type Node<'id> = ZstNode;
const MAX_CHILDREN: usize = 2;
fn create_node<'id>(&self, a: &Allocator<'id>, _n: usize) -> &'id mut ZstNode {
a.alloc(ZstNode)
}
fn set_children<'id>(&self, _n: &mut ZstNode, _c: Children<'id, ZstNode>) {}
fn set_bounds<'id>(&self, _n: &mut ZstNode, _b: ChildBounds<'_>) {}
fn create_leaf<'id>(&self, a: &Allocator<'id>, _p: &[BuildPrimitive]) -> &'id mut ZstNode {
a.alloc(ZstNode)
}
}
fn prims(n: u32) -> Vec<BuildPrimitive> {
(0..n)
.map(|i| BuildPrimitive {
lower_x: i as f32,
lower_y: 0.0,
lower_z: 0.0,
geomID: 0,
upper_x: i as f32 + 1.0,
upper_y: 1.0,
upper_z: 1.0,
primID: i,
})
.collect()
}
#[test]
fn rejects_invalid_configs_with_wide_builder() {
let device = Device::new().unwrap();
let mut bvh = device.create_bvh().unwrap();
let d = BuildConfig::default();
macro_rules! rejects {
($cfg:expr) => {{
let mut p = prims(8);
assert_eq!(
bvh.build_scoped(&$cfg, &mut p, &Wide, |_r| ()),
Err(Error::INVALID_ARGUMENT),
);
}};
}
rejects!(BuildConfig {
quality: BuildQuality::REFIT,
..d.clone()
});
rejects!(BuildConfig {
max_branching_factor: 1,
..d.clone()
}); rejects!(BuildConfig {
max_branching_factor: 17,
..d.clone()
}); rejects!(BuildConfig {
quality: BuildQuality::LOW,
max_branching_factor: 9,
..d.clone()
}); rejects!(BuildConfig {
max_leaf_size: 0,
..d.clone()
});
rejects!(BuildConfig {
max_leaf_size: 33,
..d.clone()
}); rejects!(BuildConfig {
min_leaf_size: 5,
max_leaf_size: 4,
..d.clone()
});
rejects!(BuildConfig {
sah_block_size: 0,
..d.clone()
});
rejects!(BuildConfig {
max_depth: 0,
..d.clone()
});
rejects!(BuildConfig {
traversal_cost: f32::NAN,
..d.clone()
});
rejects!(BuildConfig {
traversal_cost: 0.0,
..d.clone()
});
rejects!(BuildConfig {
intersection_cost: -1.0,
..d.clone()
});
}
#[test]
fn rejects_branching_above_max_children() {
let device = Device::new().unwrap();
let mut bvh = device.create_bvh().unwrap();
let mut p = prims(8);
let cfg = BuildConfig {
max_branching_factor: 3,
..Default::default()
};
assert_eq!(
bvh.build_scoped(&cfg, &mut p, &Narrow, |_r| ()),
Err(Error::INVALID_ARGUMENT),
);
}
#[test]
fn rejects_zero_sized_node_type() {
let device = Device::new().unwrap();
let mut bvh = device.create_bvh().unwrap();
let mut p = prims(8);
let cfg = BuildConfig::default();
assert_eq!(
bvh.build_scoped(&cfg, &mut p, &Zst, |_r| ()),
Err(Error::INVALID_ARGUMENT),
);
}