#![allow(clippy::needless_range_loop)]
use std::time::Duration;
use aabb::Aabb;
use glam::Mat4;
use ploc::{PlocSearchDistance, SortPrecision};
use triangle::Triangle;
pub mod aabb;
pub mod bvh2;
pub mod cwbvh;
pub mod faststack;
pub mod ploc;
pub mod ray;
pub mod rt_triangle;
pub mod splits;
pub mod test_util;
pub mod triangle;
#[doc(hidden)]
pub const INVALID: u32 = u32::MAX;
#[cfg(feature = "parallel")]
pub trait Boundable: Send + Sync {
fn aabb(&self) -> Aabb;
}
#[cfg(not(feature = "parallel"))]
pub trait Boundable {
fn aabb(&self) -> Aabb;
}
pub trait Transformable {
fn transform(&mut self, matrix: &Mat4);
}
#[doc(hidden)]
pub trait PerComponent<C1, C2 = C1, Output = Self> {
fn per_comp(self, f: impl Fn(C1) -> C2) -> Output;
}
impl<Input, C1, C2, Output> PerComponent<C1, C2, Output> for Input
where
Input: Into<[C1; 3]>,
Output: From<[C2; 3]>,
{
fn per_comp(self, f: impl Fn(C1) -> C2) -> Output {
let [x, y, z] = self.into();
Output::from([f(x), f(y), f(z)])
}
}
#[allow(unused)]
fn as_slice_of_atomic_u32(slice: &mut [u32]) -> &mut [core::sync::atomic::AtomicU32] {
assert_eq!(size_of::<AtomicU32>(), size_of::<u32>());
assert_eq!(align_of::<AtomicU32>(), align_of::<u32>());
use core::sync::atomic::AtomicU32;
let parents: &mut [AtomicU32] = unsafe {
core::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut AtomicU32, slice.len())
};
parents
}
#[macro_export]
#[doc(hidden)]
macro_rules! timeit {
[$label:expr, $($code:tt)*] => {
#[cfg(feature = "timeit")]
let timeit_start = std::time::Instant::now();
$($code)*
#[cfg(feature = "timeit")]
println!("{:>8} {}", format!("{}", $crate::PrettyDuration(timeit_start.elapsed())), $label);
};
}
#[doc(hidden)]
pub struct PrettyDuration(pub Duration);
impl std::fmt::Display for PrettyDuration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let duration = self.0;
if duration.as_secs() > 0 {
let seconds =
duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) / 1_000_000_000.0;
write!(f, "{seconds:.2}s ")
} else if duration.subsec_millis() > 0 {
let milliseconds =
duration.as_millis() as f64 + f64::from(duration.subsec_micros() % 1_000) / 1_000.0;
write!(f, "{milliseconds:.2}ms")
} else {
let microseconds = duration.as_micros();
write!(f, "{microseconds}µs")
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! scope {
[$label:expr] => {
#[cfg(feature = "profile")]
profiling::scope!($label);
};
}
#[derive(Clone, Copy, Debug)]
pub struct BvhBuildParams {
pub pre_split: bool,
pub ploc_search_distance: PlocSearchDistance,
pub search_depth_threshold: usize,
pub reinsertion_batch_ratio: f32,
pub post_collapse_reinsertion_batch_ratio_multiplier: f32,
pub sort_precision: SortPrecision,
pub max_prims_per_leaf: u32,
pub collapse_traversal_cost: f32,
}
impl BvhBuildParams {
pub const fn fastest_build() -> Self {
BvhBuildParams {
pre_split: false,
ploc_search_distance: PlocSearchDistance::Minimum,
search_depth_threshold: 0,
reinsertion_batch_ratio: 0.0,
post_collapse_reinsertion_batch_ratio_multiplier: 0.0,
sort_precision: SortPrecision::U64,
max_prims_per_leaf: 1,
collapse_traversal_cost: 1.0,
}
}
pub const fn very_fast_build() -> Self {
BvhBuildParams {
pre_split: false,
ploc_search_distance: PlocSearchDistance::Minimum,
search_depth_threshold: 0,
reinsertion_batch_ratio: 0.01,
post_collapse_reinsertion_batch_ratio_multiplier: 0.0,
sort_precision: SortPrecision::U64,
max_prims_per_leaf: 8,
collapse_traversal_cost: 3.0,
}
}
pub const fn fast_build() -> Self {
BvhBuildParams {
pre_split: false,
ploc_search_distance: PlocSearchDistance::Low,
search_depth_threshold: 2,
reinsertion_batch_ratio: 0.02,
post_collapse_reinsertion_batch_ratio_multiplier: 0.0,
sort_precision: SortPrecision::U64,
max_prims_per_leaf: 8,
collapse_traversal_cost: 3.0,
}
}
pub const fn medium_build() -> Self {
BvhBuildParams {
pre_split: false,
ploc_search_distance: PlocSearchDistance::Medium,
search_depth_threshold: 3,
reinsertion_batch_ratio: 0.05,
post_collapse_reinsertion_batch_ratio_multiplier: 2.0,
sort_precision: SortPrecision::U64,
max_prims_per_leaf: 8,
collapse_traversal_cost: 3.0,
}
}
pub const fn slow_build() -> Self {
BvhBuildParams {
pre_split: true,
ploc_search_distance: PlocSearchDistance::High,
search_depth_threshold: 2,
reinsertion_batch_ratio: 0.2,
post_collapse_reinsertion_batch_ratio_multiplier: 2.0,
sort_precision: SortPrecision::U128,
max_prims_per_leaf: 8,
collapse_traversal_cost: 3.0,
}
}
pub const fn very_slow_build() -> Self {
BvhBuildParams {
pre_split: true,
ploc_search_distance: PlocSearchDistance::Medium,
search_depth_threshold: 1,
reinsertion_batch_ratio: 1.0,
post_collapse_reinsertion_batch_ratio_multiplier: 1.0,
sort_precision: SortPrecision::U128,
max_prims_per_leaf: 8,
collapse_traversal_cost: 3.0,
}
}
}