1use super::*;
4use std::ops::*;
5
6#[cfg(feature = "ultraviolet")]
7use ultraviolet::f32x4;
8
9pub type EstimateNormalDefault<T, V, S> =
10 EstimateNormal<T, V, S, CentralDifferenceEstimator<T, V, <V as Vec<T>>::Dimension>>;
11
12pub type EstimateNormalFast<T, V, S> = EstimateNormal<T, V, S, TetrahedralEstimator<T, V>>;
13
14pub struct EstimateNormal<T, V, S, E> {
20 pub sdf: S,
21 pub estimator: E,
22 _pd: std::marker::PhantomData<(T, V)>,
23}
24
25impl<T, V, S, E> EstimateNormal<T, V, S, E>
26where
27 E: NormalEstimator<T, V>,
28 S: SDF<T, V>,
29 V: Vec<T>,
30{
31 pub fn new(sdf: S, estimator: E) -> Self {
33 EstimateNormal {
34 sdf,
35 estimator,
36 _pd: std::marker::PhantomData,
37 }
38 }
39
40 #[inline]
42 pub fn normal_at(&self, p: V) -> V {
43 self.estimator.estimate_normal(self.sdf, p)
44 }
45}
46
47pub trait NormalEstimator<T, V: Vec<T>> {
49 fn estimate_normal<S: SDF<T, V>>(&self, sdf: S, p: V) -> V;
50}
51
52pub struct CentralDifferenceEstimator<T, V, D> {
64 pub eps: T,
65 _pdv: std::marker::PhantomData<V>,
66 _pdd: std::marker::PhantomData<D>,
67}
68
69impl<T, V: Vec<T>> CentralDifferenceEstimator<T, V, <V as Vec<T>>::Dimension> {
70 pub fn new(eps: T) -> Self {
72 CentralDifferenceEstimator {
73 eps,
74 _pdv: std::marker::PhantomData,
75 _pdd: std::marker::PhantomData,
76 }
77 }
78}
79
80impl<T, V> NormalEstimator<T, V> for CentralDifferenceEstimator<T, V, Dim3D>
81where
82 T: Add<T, Output = T> + Sub<T, Output = T> + Copy,
83 V: Vec3<T>,
84{
85 #[inline]
86 fn estimate_normal<S: SDF<T, V>>(&self, sdf: S, p: V) -> V {
87 let eps = self.eps;
88 V::new(
89 sdf.dist(V::new(p.x() + eps, p.y(), p.z()))
90 - sdf.dist(V::new(p.x() - eps, p.y(), p.z())),
91 sdf.dist(V::new(p.x(), p.y() + eps, p.z()))
92 - sdf.dist(V::new(p.x(), p.y() - eps, p.z())),
93 sdf.dist(V::new(p.x(), p.y(), p.z() + eps))
94 - sdf.dist(V::new(p.x(), p.y(), p.z() - eps)),
95 )
96 .normalized()
97 }
98}
99
100impl<T, V> NormalEstimator<T, V> for CentralDifferenceEstimator<T, V, Dim2D>
101where
102 T: Add<T, Output = T> + Sub<T, Output = T> + Copy,
103 V: Vec2<T>,
104{
105 #[inline]
106 fn estimate_normal<S: SDF<T, V>>(&self, sdf: S, p: V) -> V {
107 let eps = self.eps;
108 V::new(
109 sdf.dist(V::new(p.x() + eps, p.y())) - sdf.dist(V::new(p.x() - eps, p.y())),
110 sdf.dist(V::new(p.x(), p.y() + eps)) - sdf.dist(V::new(p.x(), p.y() - eps)),
111 )
112 .normalized()
113 }
114}
115
116#[cfg(feature = "ultraviolet")]
117impl<V: Vec<f32x4>> Default for CentralDifferenceEstimator<f32x4, V, <V as Vec<f32x4>>::Dimension> {
118 fn default() -> Self {
119 Self::new(f32x4::from(0.000))
120 }
121}
122
123impl<V: Vec<f32>> Default for CentralDifferenceEstimator<f32, V, <V as Vec<f32>>::Dimension> {
124 fn default() -> Self {
125 Self::new(0.001)
126 }
127}
128
129impl<V: Vec<f64>> Default for CentralDifferenceEstimator<f64, V, <V as Vec<f64>>::Dimension> {
130 fn default() -> Self {
131 Self::new(0.001)
132 }
133}
134
135pub struct TetrahedralEstimator<T, V> {
145 pub eps: T,
146 _pdv: std::marker::PhantomData<V>,
147}
148
149impl<T, V: Vec<T>> TetrahedralEstimator<T, V> {
150 pub fn new(eps: T) -> Self {
152 TetrahedralEstimator {
153 eps,
154 _pdv: std::marker::PhantomData,
155 }
156 }
157}
158
159impl<T, V> NormalEstimator<T, V> for TetrahedralEstimator<T, V>
160where
161 T: Add<T, Output = T> + Sub<T, Output = T> + Neg<Output = T> + One + Copy + std::fmt::Display,
162 V: Vec3<T>,
163{
164 #[inline]
165 fn estimate_normal<S: SDF<T, V>>(&self, sdf: S, p: V) -> V {
166 let xyy = V::new(T::one(), -T::one(), -T::one());
167 let yyx = V::new(-T::one(), -T::one(), T::one());
168 let yxy = V::new(-T::one(), T::one(), -T::one());
169 let xxx = V::one();
170
171 let d1 = sdf.dist(p + xyy * self.eps);
172 let d2 = sdf.dist(p + yyx * self.eps);
173 let d3 = sdf.dist(p + yxy * self.eps);
174 let d4 = sdf.dist(p + xxx * self.eps);
175
176 (xyy * d1 + yyx * d2 + yxy * d3 + xxx * d4).normalized()
177 }
178}
179
180#[cfg(feature = "ultraviolet")]
181impl<V: Vec<f32x4>> Default for TetrahedralEstimator<f32x4, V> {
182 fn default() -> Self {
183 Self::new(f32x4::from(0.001))
184 }
185}
186
187impl<V: Vec<f32>> Default for TetrahedralEstimator<f32, V> {
188 fn default() -> Self {
189 Self::new(0.001)
190 }
191}
192
193impl<V: Vec<f64>> Default for TetrahedralEstimator<f64, V> {
194 fn default() -> Self {
195 Self::new(0.001)
196 }
197}