vox_geometry_rust/
custom_implicit_surface3.rs1use crate::transform3::Transform3;
10use crate::vector3::Vector3D;
11use crate::bounding_box3::BoundingBox3D;
12use crate::ray3::Ray3D;
13use crate::surface3::*;
14use crate::implicit_surface3::ImplicitSurface3;
15use std::sync::{RwLock, Arc};
16
17pub struct CustomImplicitSurface3 {
19 _func: fn(&Vector3D) -> f64,
20 _domain: BoundingBox3D,
21 _resolution: f64,
22 _ray_marching_resolution: f64,
23 _max_num_of_iterations: usize,
24
25 pub surface_data: Surface3Data,
27}
28
29impl CustomImplicitSurface3 {
30 pub fn new(func: fn(&Vector3D) -> f64,
42 domain: Option<BoundingBox3D>,
43 resolution: Option<f64>,
44 ray_marching_resolution: Option<f64>,
45 number_of_iterations: Option<usize>,
46 transform: Option<Transform3>,
47 is_normal_flipped: Option<bool>) -> CustomImplicitSurface3 {
48 return CustomImplicitSurface3 {
49 _func: func,
50 _domain: domain.unwrap_or(BoundingBox3D::new_default()),
51 _resolution: resolution.unwrap_or(1.0e-3),
52 _ray_marching_resolution: ray_marching_resolution.unwrap_or(1.0e-6),
53 _max_num_of_iterations: number_of_iterations.unwrap_or(5),
54 surface_data: Surface3Data::new(transform, is_normal_flipped),
55 };
56 }
57
58 pub fn builder() -> Builder {
60 return Builder::new();
61 }
62
63 pub fn gradient_local(&self, x: &Vector3D) -> Vector3D {
64 let left = (self._func)(&(*x - Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
65 let right = (self._func)(&(*x + Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
66 let bottom = (self._func)(&(*x - Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
67 let top = (self._func)(&(*x + Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
68 let back = (self._func)(&(*x - Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));
69 let front = (self._func)(&(*x + Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));
70
71 return Vector3D::new((right - left) / self._resolution, (top - bottom) / self._resolution,
72 (front - back) / self._resolution);
73 }
74}
75
76impl Surface3 for CustomImplicitSurface3 {
77 fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D {
78 let mut pt = crate::vector3::clamp(other_point, &self._domain.lower_corner, &self._domain.upper_corner);
79 for _ in 0..self._max_num_of_iterations {
80 let sdf = self.signed_distance_local(&pt);
81 if f64::abs(sdf) < f64::EPSILON {
82 break;
83 }
84 let g = self.gradient_local(&pt);
85 pt = pt - g * sdf;
86 }
87 return pt;
88 }
89 fn bounding_box_local(&self) -> BoundingBox3D {
90 return self._domain.clone();
91 }
92
93 fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
94 let mut result = SurfaceRayIntersection3::new();
95
96 let intersection = self._domain.closest_intersection(ray);
97
98 if intersection.is_intersecting {
99 let t_start;
100 let t_end;
101 if intersection.t_far == f64::MAX {
102 t_start = 0.0;
103 t_end = intersection.t_near;
104 } else {
105 t_start = intersection.t_near;
106 t_end = intersection.t_far;
107 }
108
109 let mut t = t_start;
110 let mut t_prev = t;
111 let mut pt = ray.point_at(t);
112 let mut prev_phi = (self._func)(&pt);
113
114 while t <= t_end {
115 pt = ray.point_at(t);
116 let new_phi = (self._func)(&pt);
117 let new_phi_abs = f64::abs(new_phi);
118
119 if new_phi * prev_phi < 0.0 {
120 let frac = prev_phi / (prev_phi - new_phi);
121 let t_sub = t_prev + self._ray_marching_resolution * frac;
122
123 result.is_intersecting = true;
124 result.distance = t_sub;
125 result.point = ray.point_at(t_sub);
126 result.normal = self.gradient_local(&result.point);
127 if result.normal.length() > 0.0 {
128 result.normal.normalize();
129 }
130
131 return result;
132 }
133
134 t_prev = t;
135 t += f64::max(new_phi_abs, self._ray_marching_resolution);
136 prev_phi = new_phi;
137 }
138 }
139
140 return result;
141 }
142
143 fn closest_normal_local(&self, other_point: &Vector3D) -> Vector3D {
144 let pt = self.closest_point_local(other_point);
145 let g = self.gradient_local(&pt);
146 return if g.length_squared() > 0.0 {
147 g.normalized()
148 } else {
149 g
150 };
151 }
152
153 fn intersects_local(&self, ray: &Ray3D) -> bool {
154 let intersection = self._domain.closest_intersection(ray);
155
156 if intersection.is_intersecting {
157 let t_start;
158 let t_end;
159 if intersection.t_far == f64::MAX {
160 t_start = 0.0;
161 t_end = intersection.t_near;
162 } else {
163 t_start = intersection.t_near;
164 t_end = intersection.t_far;
165 }
166
167 let mut t = t_start;
168 let mut pt = ray.point_at(t);
169 let mut prev_phi = (self._func)(&pt);
170 while t <= t_end {
171 pt = ray.point_at(t);
172 let new_phi = (self._func)(&pt);
173 let new_phi_abs = f64::abs(new_phi);
174
175 if new_phi * prev_phi < 0.0 {
176 return true;
177 }
178
179 t += f64::max(new_phi_abs, self._ray_marching_resolution);
180 prev_phi = new_phi;
181 }
182 }
183
184 return false;
185 }
186
187 fn view(&self) -> &Surface3Data {
188 return &self.surface_data;
189 }
190}
191
192impl ImplicitSurface3 for CustomImplicitSurface3 {
193 fn signed_distance_local(&self, other_point: &Vector3D) -> f64 {
194 return (self._func)(other_point);
195 }
196}
197
198pub type CustomImplicitSurface3Ptr = Arc<RwLock<CustomImplicitSurface3>>;
200
201pub struct Builder {
205 _func: Option<fn(&Vector3D) -> f64>,
206 _domain: BoundingBox3D,
207 _resolution: f64,
208 _ray_marching_resolution: f64,
209 _max_num_of_iterations: usize,
210
211 _surface_data: Surface3Data,
212}
213
214impl Builder {
215 pub fn with_signed_distance_function(&mut self, func: fn(&Vector3D) -> f64) -> &mut Self {
217 self._func = Some(func);
218 return self;
219 }
220
221 pub fn with_domain(&mut self, domain: BoundingBox3D) -> &mut Self {
223 self._domain = domain;
224 return self;
225 }
226
227 pub fn with_resolution(&mut self, resolution: f64) -> &mut Self {
229 self._resolution = resolution;
230 return self;
231 }
232
233 pub fn with_ray_marching_resolution(&mut self, ray_marching_resolution: f64) -> &mut Self {
236 self._ray_marching_resolution = ray_marching_resolution;
237 return self;
238 }
239
240 pub fn with_max_number_of_iterations(&mut self, num_iter: usize) -> &mut Self {
243 self._max_num_of_iterations = num_iter;
244 return self;
245 }
246
247 pub fn build(&mut self) -> CustomImplicitSurface3 {
249 return CustomImplicitSurface3::new(self._func.unwrap(),
250 Some(self._domain.clone()),
251 Some(self._resolution),
252 Some(self._ray_marching_resolution),
253 Some(self._max_num_of_iterations),
254 Some(self._surface_data.transform.clone()),
255 Some(self._surface_data.is_normal_flipped));
256 }
257
258 pub fn make_shared(&mut self) -> CustomImplicitSurface3Ptr {
260 return CustomImplicitSurface3Ptr::new(RwLock::new(self.build()));
261 }
262
263 pub fn new() -> Builder {
265 return Builder {
266 _func: None,
267 _domain: BoundingBox3D::new_default(),
268 _resolution: 1.0e-3,
269 _ray_marching_resolution: 1.0e-6,
270 _max_num_of_iterations: 5,
271 _surface_data: Surface3Data::new(None, None),
272 };
273 }
274}
275
276impl SurfaceBuilderBase3 for Builder {
277 fn view(&mut self) -> &mut Surface3Data {
278 return &mut self._surface_data;
279 }
280}