theon/integration/
ultraviolet.rs

1#![cfg(feature = "ultraviolet")]
2
3use decorum::R64;
4use typenum::consts::{U2, U3, U4};
5use ultraviolet::interp::Lerp;
6use ultraviolet::vec::{Vec2, Vec3, Vec4};
7
8use crate::adjunct::{Adjunct, Converged, Extend, Fold, Map, Truncate, ZipMap};
9use crate::ops::{Cross, Dot, Interpolate};
10use crate::space::{
11    AffineSpace, Basis, DualSpace, EuclideanSpace, FiniteDimensional, Homogeneous, InnerSpace,
12    VectorSpace,
13};
14use crate::{AsPosition, AsPositionMut};
15
16impl Adjunct for Vec2 {
17    type Item = f32;
18}
19
20impl Adjunct for Vec3 {
21    type Item = f32;
22}
23
24impl Adjunct for Vec4 {
25    type Item = f32;
26}
27
28impl AffineSpace for Vec2 {
29    type Translation = Self;
30}
31
32impl AffineSpace for Vec3 {
33    type Translation = Self;
34}
35
36impl AsPosition for Vec2 {
37    type Position = Self;
38
39    fn as_position(&self) -> &Self::Position {
40        self
41    }
42}
43
44impl AsPosition for Vec3 {
45    type Position = Self;
46
47    fn as_position(&self) -> &Self::Position {
48        self
49    }
50}
51
52impl AsPositionMut for Vec2 {
53    fn as_position_mut(&mut self) -> &mut Self::Position {
54        self
55    }
56}
57
58impl AsPositionMut for Vec3 {
59    fn as_position_mut(&mut self) -> &mut Self::Position {
60        self
61    }
62}
63
64impl Basis for Vec2 {
65    type Bases = [Self; 2];
66
67    fn canonical_basis() -> Self::Bases {
68        [
69            Self::canonical_basis_component(0).unwrap(),
70            Self::canonical_basis_component(1).unwrap(),
71        ]
72    }
73
74    fn canonical_basis_component(index: usize) -> Option<Self> {
75        match index {
76            0 => Some(Self::unit_x()),
77            1 => Some(Self::unit_y()),
78            _ => None,
79        }
80    }
81}
82
83impl Basis for Vec3 {
84    type Bases = [Self; 3];
85
86    fn canonical_basis() -> Self::Bases {
87        [
88            Self::canonical_basis_component(0).unwrap(),
89            Self::canonical_basis_component(1).unwrap(),
90            Self::canonical_basis_component(2).unwrap(),
91        ]
92    }
93
94    fn canonical_basis_component(index: usize) -> Option<Self> {
95        match index {
96            0 => Some(Self::unit_x()),
97            1 => Some(Self::unit_y()),
98            2 => Some(Self::unit_z()),
99            _ => None,
100        }
101    }
102}
103
104impl Basis for Vec4 {
105    type Bases = [Self; 4];
106
107    fn canonical_basis() -> Self::Bases {
108        [
109            Self::canonical_basis_component(0).unwrap(),
110            Self::canonical_basis_component(1).unwrap(),
111            Self::canonical_basis_component(2).unwrap(),
112            Self::canonical_basis_component(3).unwrap(),
113        ]
114    }
115
116    fn canonical_basis_component(index: usize) -> Option<Self> {
117        match index {
118            0 => Some(Self::unit_x()),
119            1 => Some(Self::unit_y()),
120            2 => Some(Self::unit_z()),
121            3 => Some(Self::unit_w()),
122            _ => None,
123        }
124    }
125}
126
127impl Converged for Vec2 {
128    fn converged(value: Self::Item) -> Self {
129        Self::broadcast(value)
130    }
131}
132
133impl Converged for Vec3 {
134    fn converged(value: Self::Item) -> Self {
135        Self::broadcast(value)
136    }
137}
138
139impl Converged for Vec4 {
140    fn converged(value: Self::Item) -> Self {
141        Self::broadcast(value)
142    }
143}
144
145impl Cross for Vec3 {
146    type Output = Self;
147
148    fn cross(self, other: Self) -> Self::Output {
149        Self::cross(&self, other)
150    }
151}
152
153impl Dot for Vec2 {
154    type Output = f32;
155
156    fn dot(self, other: Self) -> Self::Output {
157        Self::dot(&self, other)
158    }
159}
160
161impl Dot for Vec3 {
162    type Output = f32;
163
164    fn dot(self, other: Self) -> Self::Output {
165        Self::dot(&self, other)
166    }
167}
168
169impl Dot for Vec4 {
170    type Output = f32;
171
172    fn dot(self, other: Self) -> Self::Output {
173        Self::dot(&self, other)
174    }
175}
176
177impl DualSpace for Vec2 {
178    type Dual = Self;
179
180    fn transpose(self) -> Self::Dual {
181        self
182    }
183}
184
185impl DualSpace for Vec3 {
186    type Dual = Self;
187
188    fn transpose(self) -> Self::Dual {
189        self
190    }
191}
192
193impl DualSpace for Vec4 {
194    type Dual = Self;
195
196    fn transpose(self) -> Self::Dual {
197        self
198    }
199}
200
201impl Extend<Vec3> for Vec2 {
202    fn extend(self, z: Self::Item) -> Vec3 {
203        let (x, y) = self.into();
204        [x, y, z].into()
205    }
206}
207
208impl Extend<Vec4> for Vec3 {
209    fn extend(self, w: Self::Item) -> Vec4 {
210        let (x, y, z) = self.into();
211        [x, y, z, w].into()
212    }
213}
214
215impl EuclideanSpace for Vec2 {
216    type CoordinateSpace = Self;
217
218    fn origin() -> Self {
219        Self::zero()
220    }
221}
222
223impl EuclideanSpace for Vec3 {
224    type CoordinateSpace = Self;
225
226    fn origin() -> Self {
227        Self::zero()
228    }
229}
230
231impl FiniteDimensional for Vec2 {
232    type N = U2;
233}
234
235impl FiniteDimensional for Vec3 {
236    type N = U3;
237}
238
239impl FiniteDimensional for Vec4 {
240    type N = U4;
241}
242
243impl Fold for Vec2 {
244    fn fold<T, F>(self, seed: T, f: F) -> T
245    where
246        F: FnMut(T, Self::Item) -> T,
247    {
248        self.as_slice().iter().cloned().fold(seed, f)
249    }
250}
251
252impl Fold for Vec3 {
253    fn fold<T, F>(self, seed: T, f: F) -> T
254    where
255        F: FnMut(T, Self::Item) -> T,
256    {
257        self.as_slice().iter().cloned().fold(seed, f)
258    }
259}
260
261impl Fold for Vec4 {
262    fn fold<T, F>(self, seed: T, f: F) -> T
263    where
264        F: FnMut(T, Self::Item) -> T,
265    {
266        self.as_slice().iter().cloned().fold(seed, f)
267    }
268}
269
270impl Homogeneous for Vec2 {
271    type ProjectiveSpace = Vec3;
272}
273
274impl Homogeneous for Vec3 {
275    type ProjectiveSpace = Vec4;
276}
277
278impl InnerSpace for Vec2 {}
279
280impl InnerSpace for Vec3 {}
281
282impl InnerSpace for Vec4 {}
283
284impl Interpolate for Vec2 {
285    type Output = Self;
286
287    fn lerp(self, other: Self, f: R64) -> Self::Output {
288        <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
289    }
290}
291
292impl Interpolate for Vec3 {
293    type Output = Self;
294
295    fn lerp(self, other: Self, f: R64) -> Self::Output {
296        <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
297    }
298}
299
300impl Interpolate for Vec4 {
301    type Output = Self;
302
303    fn lerp(self, other: Self, f: R64) -> Self::Output {
304        <Self as Lerp<f32>>::lerp(&self, other, f64::from(f) as f32)
305    }
306}
307
308impl Map<f32> for Vec2 {
309    type Output = Self;
310
311    fn map<F>(self, mut f: F) -> Self::Output
312    where
313        F: FnMut(Self::Item) -> f32,
314    {
315        let (x, y) = self.into();
316        [f(x), f(y)].into()
317    }
318}
319
320impl Map<f32> for Vec3 {
321    type Output = Self;
322
323    fn map<F>(self, mut f: F) -> Self::Output
324    where
325        F: FnMut(Self::Item) -> f32,
326    {
327        let (x, y, z) = self.into();
328        [f(x), f(y), f(z)].into()
329    }
330}
331
332impl Map<f32> for Vec4 {
333    type Output = Self;
334
335    #[allow(clippy::many_single_char_names)]
336    fn map<F>(self, mut f: F) -> Self::Output
337    where
338        F: FnMut(Self::Item) -> f32,
339    {
340        let (x, y, z, w) = self.into();
341        [f(x), f(y), f(z), f(w)].into()
342    }
343}
344
345impl Truncate<Vec2> for Vec3 {
346    fn truncate(self) -> (Vec2, Self::Item) {
347        let z = self.z;
348        (self.into(), z)
349    }
350}
351
352impl Truncate<Vec3> for Vec4 {
353    fn truncate(self) -> (Vec3, Self::Item) {
354        let w = self.w;
355        (self.into(), w)
356    }
357}
358
359impl VectorSpace for Vec2 {
360    type Scalar = f32;
361
362    fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
363        match index {
364            0 => Some(self.x),
365            1 => Some(self.y),
366            _ => None,
367        }
368    }
369
370    fn into_xy(self) -> (Self::Scalar, Self::Scalar) {
371        self.into()
372    }
373
374    fn zero() -> Self {
375        Self::zero()
376    }
377}
378
379impl VectorSpace for Vec3 {
380    type Scalar = f32;
381
382    fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
383        match index {
384            0 => Some(self.x),
385            1 => Some(self.y),
386            2 => Some(self.z),
387            _ => None,
388        }
389    }
390
391    fn into_xyz(self) -> (Self::Scalar, Self::Scalar, Self::Scalar) {
392        self.into()
393    }
394
395    fn zero() -> Self {
396        Self::zero()
397    }
398}
399
400impl VectorSpace for Vec4 {
401    type Scalar = f32;
402
403    fn scalar_component(&self, index: usize) -> Option<Self::Scalar> {
404        match index {
405            0 => Some(self.x),
406            1 => Some(self.y),
407            2 => Some(self.z),
408            3 => Some(self.w),
409            _ => None,
410        }
411    }
412
413    fn zero() -> Self {
414        Self::zero()
415    }
416}
417
418impl ZipMap<f32> for Vec2 {
419    type Output = Self;
420
421    fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
422    where
423        F: FnMut(Self::Item, Self::Item) -> f32,
424    {
425        let (x1, y1) = self.into();
426        let (x2, y2) = other.into();
427        [f(x1, x2), f(y1, y2)].into()
428    }
429}
430
431impl ZipMap<f32> for Vec3 {
432    type Output = Self;
433
434    fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
435    where
436        F: FnMut(Self::Item, Self::Item) -> f32,
437    {
438        let (x1, y1, z1) = self.into();
439        let (x2, y2, z2) = other.into();
440        [f(x1, x2), f(y1, y2), f(z1, z2)].into()
441    }
442}
443
444impl ZipMap<f32> for Vec4 {
445    type Output = Self;
446
447    fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
448    where
449        F: FnMut(Self::Item, Self::Item) -> f32,
450    {
451        let (x1, y1, z1, w1) = self.into();
452        let (x2, y2, z2, w2) = other.into();
453        [f(x1, x2), f(y1, y2), f(z1, z2), f(w1, w2)].into()
454    }
455}