use nalgebra::RealField;
use serde::{Deserialize, Serialize};
use crate::{
config::{
DEFAULT_INTERSECT_COST, DEFAULT_MAX_DEPTH, DEFAULT_MAX_SHAPES_PER_NODE, DEFAULT_SAH_BUCKETS, DEFAULT_TRAVERSE_COST,
},
error::{BvhConfigError, Result},
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BvhConfig<T: RealField + Copy> {
pub traverse_cost: T,
pub intersect_cost: T,
pub sah_buckets: usize,
pub max_shapes_per_node: usize,
pub max_depth: usize,
}
impl<T: RealField + Copy> BvhConfig<T> {
pub fn new(
traverse_cost: T,
intersect_cost: T,
sah_buckets: usize,
max_shapes_per_node: usize,
max_depth: usize,
) -> Result<Self> {
if traverse_cost <= T::zero() {
return Err(BvhConfigError::InvalidTraverseCost {
cost: format!("{traverse_cost:?}"),
}
.into());
}
if intersect_cost <= T::zero() {
return Err(BvhConfigError::InvalidIntersectCost {
cost: format!("{intersect_cost:?}"),
}
.into());
}
if sah_buckets == 0 {
return Err(BvhConfigError::InvalidSahBuckets { buckets: sah_buckets }.into());
}
if max_shapes_per_node <= 2 {
return Err(BvhConfigError::InvalidMaxShapesPerNode {
count: max_shapes_per_node,
}
.into());
}
if max_depth == 0 {
return Err(BvhConfigError::InvalidMaxDepth { depth: max_depth }.into());
}
Ok(Self {
traverse_cost,
intersect_cost,
sah_buckets,
max_shapes_per_node,
max_depth,
})
}
}
impl<T: RealField + Copy> Default for BvhConfig<T> {
fn default() -> Self {
Self::new(
T::from_f64(DEFAULT_TRAVERSE_COST).unwrap(),
T::from_f64(DEFAULT_INTERSECT_COST).unwrap(),
DEFAULT_SAH_BUCKETS,
DEFAULT_MAX_SHAPES_PER_NODE,
DEFAULT_MAX_DEPTH,
)
.unwrap()
}
}