1use super::*;
3use crate::mathtypes::*;
4use std::ops::*;
5
6#[derive(Clone, Copy, Debug)]
8pub struct Round<T, S> {
9 pub sdf: S,
10 pub radius: T,
11}
12
13impl<T, S> Round<T, S> {
14 pub fn new(sdf: S, radius: T) -> Self {
15 Round { sdf, radius }
16 }
17}
18
19impl<T, V, S> SDF<T, V> for Round<T, S>
20where
21 T: Copy + Sub<T, Output = T>,
22 V: Vec<T>,
23 S: SDF<T, V>,
24{
25 #[inline]
26 fn dist(&self, p: V) -> T {
27 self.sdf.dist(p) - self.radius
28 }
29}
30
31#[derive(Clone, Copy, Debug)]
34pub struct Elongate<T, S, D> {
35 pub sdf: S,
36 pub axis: Axis,
37 pub elongation: T,
38 _pd: std::marker::PhantomData<D>,
39}
40
41impl<T, S, D> Elongate<T, S, D> {
42 pub fn new(sdf: S, axis: Axis, elongation: T) -> Self {
44 Elongate {
45 sdf,
46 axis,
47 elongation,
48 _pd: std::marker::PhantomData,
49 }
50 }
51}
52
53impl<T, V, S> SDF<T, V> for Elongate<T, S, Dim3D>
54where
55 T: Copy + Add<T, Output = T> + Sub<T, Output = T> + Zero,
56 V: Vec3<T>,
57 S: SDF<T, V>,
58{
59 #[inline]
60 fn dist(&self, p: V) -> T {
61 let h = match self.axis {
62 Axis::X => V::new(self.elongation, T::zero(), T::zero()),
63 Axis::Y => V::new(T::zero(), self.elongation, T::zero()),
64 Axis::Z => V::new(T::zero(), T::zero(), self.elongation),
65 };
66 let q = p - p.clamp(-h, h);
67 self.sdf.dist(q)
68 }
69}
70
71impl<T, V, S> SDF<T, V> for Elongate<T, S, Dim2D>
72where
73 T: Copy + Add<T, Output = T> + Sub<T, Output = T> + Zero,
74 V: Vec2<T>,
75 S: SDF<T, V>,
76{
77 #[inline]
78 fn dist(&self, p: V) -> T {
79 let h = match self.axis {
80 Axis::X => V::new(self.elongation, T::zero()),
81 Axis::Y => V::new(T::zero(), self.elongation),
82 Axis::Z => panic!("Attempting to use Z axis to elongate 2d SDF"),
83 };
84 let q = p - p.clamp(-h, h);
85 self.sdf.dist(q)
86 }
87}
88
89#[derive(Clone, Copy, Debug)]
91pub struct ElongateMulti<V, S, D> {
92 pub sdf: S,
93 pub elongation: V,
94 _pd: std::marker::PhantomData<D>,
95}
96
97impl<V, S, D> ElongateMulti<V, S, D> {
98 pub fn new(sdf: S, elongation: V) -> Self {
99 ElongateMulti {
100 sdf,
101 elongation,
102 _pd: std::marker::PhantomData,
103 }
104 }
105}
106
107impl<T, V, S> SDF<T, V> for ElongateMulti<V, S, Dim3D>
108where
109 T: Copy + Add<T, Output = T> + Sub<T, Output = T> + Zero + MaxMin,
110 V: Vec3<T>,
111 S: SDF<T, V>,
112{
113 #[inline]
114 fn dist(&self, p: V) -> T {
115 let q = p.abs() - self.elongation;
116 let t = q.y().max(q.z()).max(q.x()).min(T::zero());
117 self.sdf.dist(q.max(V::zero())) + t
118 }
119}
120
121impl<T, V, S> SDF<T, V> for ElongateMulti<V, S, Dim2D>
122where
123 T: Copy + Add<T, Output = T> + Sub<T, Output = T> + Zero + MaxMin,
124 V: Vec2<T>,
125 S: SDF<T, V>,
126{
127 #[inline]
128 fn dist(&self, p: V) -> T {
129 let q = p.abs() - self.elongation;
130 let t = q.x().max(q.y()).min(T::zero());
131 self.sdf.dist(q.max(V::zero())) + t
132 }
133}
134
135#[derive(Clone, Copy, Debug)]
137pub struct Translate<V, S> {
138 pub sdf: S,
139 pub translation: V,
140}
141
142impl<V, S> Translate<V, S> {
143 pub fn new(sdf: S, translation: V) -> Self {
144 Translate { sdf, translation }
145 }
146}
147
148impl<T, V, S> SDF<T, V> for Translate<V, S>
149where
150 T: Copy,
151 V: Vec<T>,
152 S: SDF<T, V>,
153{
154 #[inline]
155 fn dist(&self, p: V) -> T {
156 self.sdf.dist(p - self.translation)
157 }
158}
159
160#[derive(Clone, Copy, Debug)]
162pub struct Rotate<R, S> {
163 pub sdf: S,
164 pub rotation: R,
165}
166
167impl<R, S> Rotate<R, S> {
168 pub fn new(sdf: S, rotation: R) -> Self {
169 Rotate { sdf, rotation }
170 }
171}
172
173impl<T, V, R, S> SDF<T, V> for Rotate<R, S>
174where
175 T: Copy,
176 V: Vec<T>,
177 S: SDF<T, V>,
178 R: Rotation<V> + Copy,
179{
180 #[inline]
181 fn dist(&self, p: V) -> T {
182 self.sdf.dist(self.rotation.rotate_vec(p))
183 }
184}
185
186#[derive(Clone, Copy, Debug)]
188pub struct Scale<T, S> {
189 pub sdf: S,
190 pub scaling: T,
191}
192
193impl<T, S> Scale<T, S> {
194 pub fn new(sdf: S, scaling: T) -> Self {
195 Scale { sdf, scaling }
196 }
197}
198
199impl<T, V, S> SDF<T, V> for Scale<T, S>
200where
201 T: Copy + Mul<T, Output = T>,
202 V: Vec<T>,
203 S: SDF<T, V>,
204{
205 #[inline]
206 fn dist(&self, p: V) -> T {
207 self.sdf.dist(p / self.scaling) * self.scaling
208 }
209}