1use crate::{BvhError, Result};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Quality {
6 Sah,
8 Fast,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq)]
14pub struct BuildOptions {
15 pub quality: Quality,
16 pub max_leaf_size: u32,
18 pub sah_bins: u32,
20 pub treelet_size: u32,
22}
23
24impl Default for BuildOptions {
25 fn default() -> Self {
26 Self {
27 quality: Quality::Sah,
28 max_leaf_size: 8,
29 sah_bins: 16,
30 treelet_size: 4096,
31 }
32 }
33}
34
35impl BuildOptions {
36 pub(crate) fn validate(&self) -> Result<()> {
37 if !(1..=16).contains(&self.max_leaf_size) {
38 return Err(BvhError::InvalidOptions("max_leaf_size must be 1 to 16"));
39 }
40 if !(4..=64).contains(&self.sah_bins) {
41 return Err(BvhError::InvalidOptions("sah_bins must be 4 to 64"));
42 }
43 if self.treelet_size < self.max_leaf_size {
44 return Err(BvhError::InvalidOptions(
45 "treelet_size must be at least max_leaf_size",
46 ));
47 }
48 Ok(())
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq)]
54pub struct UpdatePolicy {
55 pub full_rebuild_fraction: f32,
58 pub degradation_factor: f32,
61}
62
63impl Default for UpdatePolicy {
64 fn default() -> Self {
65 Self {
66 full_rebuild_fraction: 0.30,
67 degradation_factor: 1.5,
68 }
69 }
70}
71
72impl UpdatePolicy {
73 pub fn validate(&self) -> Result<()> {
80 if !(0.0..=1.0).contains(&self.full_rebuild_fraction) {
81 return Err(BvhError::InvalidOptions(
82 "full_rebuild_fraction must be 0 to 1",
83 ));
84 }
85 if self.degradation_factor.is_nan() || self.degradation_factor < 1.0 {
86 return Err(BvhError::InvalidOptions(
87 "degradation_factor must be at least 1",
88 ));
89 }
90 Ok(())
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn defaults_are_valid() {
100 assert!(BuildOptions::default().validate().is_ok());
101 assert!(UpdatePolicy::default().validate().is_ok());
102 }
103
104 #[test]
105 fn out_of_range_options_are_rejected() {
106 let bad_leaf = BuildOptions {
107 max_leaf_size: 0,
108 ..Default::default()
109 };
110 assert!(matches!(
111 bad_leaf.validate(),
112 Err(BvhError::InvalidOptions(_))
113 ));
114 let bad_bins = BuildOptions {
115 sah_bins: 65,
116 ..Default::default()
117 };
118 assert!(bad_bins.validate().is_err());
119 let bad_treelet = BuildOptions {
120 treelet_size: 4,
121 ..Default::default()
122 };
123 assert!(bad_treelet.validate().is_err());
124 let nan = UpdatePolicy {
125 degradation_factor: f32::NAN,
126 ..Default::default()
127 };
128 assert!(nan.validate().is_err());
129 let fraction = UpdatePolicy {
130 full_rebuild_fraction: 1.5,
131 ..Default::default()
132 };
133 assert!(fraction.validate().is_err());
134 }
135}