bevy_hexasphere/
lib.rs

1//!
2//! Library for subdividing shapes made of triangles.
3//!
4//! This is for internal bevy use only, and is not
5//! well documented. See [`hexasphere`](crates.io/crates/hexasphere)
6//! for more information.
7//!
8
9use slice::*;
10use slice::Slice::*;
11
12pub mod interpolation;
13pub mod shapes;
14mod slice;
15
16pub trait Vec3:
17    std::ops::Add<Self, Output = Self> +
18    std::ops::Mul<f32, Output = Self> +
19    Copy
20{
21    const ZERO: Self;
22
23    fn dot(self, other: Self) -> f32;
24    fn normalize(self) -> Self;
25    fn from_arr3(data: [f32; 3]) -> Self;
26}
27
28pub trait BaseShape<V: Vec3> {
29    fn initial_points(&self) -> Vec<V>;
30
31    fn triangles(&self) -> Box<[Triangle]>;
32
33    const EDGES: usize;
34
35    fn interpolate(&self, a: V, b: V, p: f32) -> V;
36
37
38    fn interpolate_half(&self, a: V, b: V) -> V {
39        self.interpolate(a, b, 0.5)
40    }
41
42    fn interpolate_multiple(&self, a: V, b: V, indices: &[u32], points: &mut [V]) {
43        for (percent, index) in indices.iter().enumerate() {
44            let percent = (percent + 1) as f32 / (indices.len() + 1) as f32;
45
46            points[*index as usize] = self.interpolate(a, b, percent);
47        }
48    }
49}
50
51struct Edge {
52    points: Vec<u32>,
53    done: bool,
54}
55
56impl Default for Edge {
57    fn default() -> Self {
58        Self {
59            points: Vec::new(),
60            done: true,
61        }
62    }
63}
64
65#[derive(Clone, Debug)]
66enum TriangleContents {
67    None,
68    One(u32),
69    Three { a: u32, b: u32, c: u32 },
70    Six {
71        a: u32,
72        b: u32,
73        c: u32,
74        ab: u32,
75        bc: u32,
76        ca: u32,
77    },
78    More {
79        a: u32,
80        b: u32,
81        c: u32,
82        // Separated into three `my_side_length` segments
83        // to save on extra allocations.
84        sides: Vec<u32>,
85        my_side_length: u32,
86        // Implementing this as a `Vec<TriangleContents>` would
87        // probably be a perf. improvement someday, however not
88        // something worth implementing right now.
89        contents: Box<TriangleContents>,
90    },
91}
92
93impl TriangleContents {
94    pub fn none() -> Self {
95        Self::None
96    }
97
98    fn one<V: Vec3>(ab: Slice<u32>, bc: Slice<u32>, points: &mut Vec<V>, calculate: bool, shape: &impl BaseShape<V>) -> Self {
99        assert_eq!(ab.len(), bc.len());
100        assert_eq!(ab.len(), 2);
101        let p1 = points[ab[0] as usize];
102        let p2 = points[bc[1] as usize];
103        let index = points.len() as u32;
104        if calculate {
105            points.push(shape.interpolate_half(p1, p2));
106        } else {
107            points.push(V::ZERO);
108        }
109        TriangleContents::One(index)
110    }
111
112    fn three<V: Vec3>(
113        &mut self,
114        ab: Slice<u32>,
115        bc: Slice<u32>,
116        ca: Slice<u32>,
117        points: &mut Vec<V>,
118        calculate: bool,
119        shape: &impl BaseShape<V>,
120    ) {
121        use TriangleContents::*;
122
123        assert_eq!(ab.len(), bc.len());
124        assert_eq!(ab.len(), ca.len());
125        assert_eq!(ab.len(), 3);
126
127        match self {
128            &mut One(x) => {
129                let ab = points[ab[1] as usize];
130                let bc = points[bc[1] as usize];
131                let ca = points[ca[1] as usize];
132
133                if calculate {
134                    let a = shape.interpolate_half(ab, ca);
135                    let b = shape.interpolate_half(bc, ab);
136                    let c = shape.interpolate_half(ca, bc);
137
138                    points.extend_from_slice(&[b, c]);
139                    points[x as usize] = a;
140                } else {
141                    points.extend_from_slice(&[V::ZERO, V::ZERO])
142                }
143
144                *self = Three {
145                    a: x,
146                    b: points.len() as u32 - 2,
147                    c: points.len() as u32 - 1,
148                };
149            }
150            _ => panic!("Self is {:?} while it should be One", self),
151        }
152    }
153
154    fn six<V: Vec3>(
155        &mut self,
156        ab: Slice<u32>,
157        bc: Slice<u32>,
158        ca: Slice<u32>,
159        points: &mut Vec<V>,
160        calculate: bool,
161        shape: &impl BaseShape<V>,
162    ) {
163        use TriangleContents::*;
164
165        assert_eq!(ab.len(), bc.len());
166        assert_eq!(ab.len(), ca.len());
167        assert_eq!(ab.len(), 4);
168
169        match self {
170            &mut Three {
171                a: a_index,
172                b: b_index,
173                c: c_index,
174            } => {
175                let aba = points[ab[1] as usize];
176                let abb = points[ab[2] as usize];
177                let bcb = points[bc[1] as usize];
178                let bcc = points[bc[2] as usize];
179                let cac = points[ca[1] as usize];
180                let caa = points[ca[2] as usize];
181
182                if calculate {
183                    let a = shape.interpolate_half(aba, caa);
184                    let b = shape.interpolate_half(abb, bcb);
185                    let c = shape.interpolate_half(bcc, cac);
186
187                    let ab = shape.interpolate_half(a, b);
188                    let bc = shape.interpolate_half(b, c);
189                    let ca = shape.interpolate_half(c, a);
190
191                    points[a_index as usize] = a;
192                    points[b_index as usize] = b;
193                    points[c_index as usize] = c;
194                    points.extend_from_slice(&[ab, bc, ca]);
195                } else {
196                    points.extend_from_slice(&[V::ZERO, V::ZERO, V::ZERO])
197                }
198
199                *self = Six {
200                    a: a_index,
201                    b: b_index,
202                    c: c_index,
203                    ab: points.len() as u32 - 3,
204                    bc: points.len() as u32 - 2,
205                    ca: points.len() as u32 - 1,
206                };
207            }
208            _ => panic!("Found {:?} whereas a Three was expected", self),
209        }
210    }
211
212    pub fn subdivide<V: Vec3>(
213        &mut self,
214        ab: Slice<u32>,
215        bc: Slice<u32>,
216        ca: Slice<u32>,
217        points: &mut Vec<V>,
218        calculate: bool,
219        shape: &impl BaseShape<V>,
220    ) {
221        use TriangleContents::*;
222        assert_eq!(ab.len(), bc.len());
223        assert_eq!(ab.len(), ca.len());
224        assert!(ab.len() >= 2);
225        match self {
226            None => *self = Self::one(ab, bc, points, calculate, shape),
227            One(_) => self.three(ab, bc, ca, points, calculate, shape),
228            Three { .. } => self.six(ab, bc, ca, points, calculate, shape),
229            &mut Six {
230                a,
231                b,
232                c,
233                ab: ab_idx,
234                bc: bc_idx,
235                ca: ca_idx,
236            } => {
237                *self = More {
238                    a,
239                    b,
240                    c,
241                    sides: vec![ab_idx, bc_idx, ca_idx],
242                    my_side_length: 1,
243                    contents: Box::new(Self::none()),
244                };
245                self.subdivide(ab, bc, ca, points, calculate, shape);
246            }
247            &mut More {
248                a: a_idx,
249                b: b_idx,
250                c: c_idx,
251                ref mut sides,
252                ref mut contents,
253                ref mut my_side_length,
254            } => {
255                points.extend_from_slice(&[V::ZERO, V::ZERO, V::ZERO]);
256                let len = points.len() as u32;
257                sides.extend_from_slice(&[len - 3, len - 2, len - 1]);
258                *my_side_length += 1;
259                let side_length = *my_side_length as usize;
260
261                let outer_len = ab.len();
262
263                let aba = points[ab[1] as usize];
264                let abb = points[ab[outer_len - 2] as usize];
265                let bcb = points[bc[1] as usize];
266                let bcc = points[bc[outer_len - 2] as usize];
267                let cac = points[ca[1] as usize];
268                let caa = points[ca[outer_len - 2] as usize];
269
270                if calculate {
271                    points[a_idx as usize] = shape.interpolate_half(aba, caa);
272                    points[b_idx as usize] = shape.interpolate_half(abb, bcb);
273                    points[c_idx as usize] = shape.interpolate_half(bcc, cac);
274                }
275
276                let ab = &sides[0..side_length];
277                let bc = &sides[side_length..side_length * 2];
278                let ca = &sides[side_length * 2..];
279
280                if calculate {
281                    shape.interpolate_multiple(
282                        points[a_idx as usize],
283                        points[b_idx as usize],
284                        ab,
285                        points,
286                    );
287                    shape.interpolate_multiple(
288                        points[b_idx as usize],
289                        points[c_idx as usize],
290                        bc,
291                        points,
292                    );
293                    shape.interpolate_multiple(
294                        points[c_idx as usize],
295                        points[a_idx as usize],
296                        ca,
297                        points,
298                    );
299                }
300
301                contents.subdivide(Forward(ab), Forward(bc), Forward(ca), points, calculate, shape);
302            }
303        }
304    }
305
306    pub fn idx_ab(&self, idx: usize) -> u32 {
307        use TriangleContents::*;
308        match self {
309            None => panic!("Invalid Index, len is 0, but got {}", idx),
310            One(x) => {
311                if idx != 0 {
312                    panic!("Invalid Index, len is 1, but got {}", idx);
313                } else {
314                    *x
315                }
316            }
317            Three { a, b, .. } => *[a, b][idx],
318            Six { a, b, ab, .. } => *[a, ab, b][idx],
319            &More {
320                a,
321                b,
322                ref sides,
323                my_side_length,
324                ..
325            } => match idx {
326                0 => a,
327                x if (1..(my_side_length as usize + 1)).contains(&x) => sides[x - 1],
328                x if x == my_side_length as usize + 1 => b,
329                _ => panic!(
330                    "Invalid Index, len is {}, but got {}",
331                    my_side_length + 2,
332                    idx
333                ),
334            },
335        }
336    }
337
338    pub fn idx_bc(&self, idx: usize) -> u32 {
339        use TriangleContents::*;
340        match self {
341            None => panic!("Invalid Index, len is 0, but got {}", idx),
342            One(x) => {
343                if idx != 0 {
344                    panic!("Invalid Index, len is 1, but got {}", idx);
345                } else {
346                    *x
347                }
348            }
349            Three { c, b, .. } => *[b, c][idx],
350            Six { b, c, bc, .. } => *[b, bc, c][idx],
351            &More {
352                b,
353                c,
354                ref sides,
355                my_side_length,
356                ..
357            } => match idx {
358                0 => b,
359                x if (1..(my_side_length as usize + 1)).contains(&x) => {
360                    sides[my_side_length as usize + (x - 1)]
361                }
362                x if x == my_side_length as usize + 1 => c,
363                _ => panic!(
364                    "Invalid Index, len is {}, but got {}",
365                    my_side_length + 2,
366                    idx
367                ),
368            },
369        }
370    }
371
372    pub fn idx_ca(&self, idx: usize) -> u32 {
373        use TriangleContents::*;
374        match self {
375            None => panic!("Invalid Index, len is 0, but got {}", idx),
376            One(x) => {
377                if idx != 0 {
378                    panic!("Invalid Index, len is 1, but got {}", idx);
379                } else {
380                    *x
381                }
382            }
383            Three { c, a, .. } => *[c, a][idx],
384            Six { c, a, ca, .. } => *[c, ca, a][idx],
385            &More {
386                c,
387                a,
388                ref sides,
389                my_side_length,
390                ..
391            } => match idx {
392                0 => c,
393                x if (1..(my_side_length as usize + 1)).contains(&x) => {
394                    sides[my_side_length as usize * 2 + x - 1]
395                }
396                x if x == my_side_length as usize + 1 => a,
397                _ => panic!(
398                    "Invalid Index, len is {}, but got {}",
399                    my_side_length + 2,
400                    idx
401                ),
402            },
403        }
404    }
405
406    pub fn add_indices(&self, buffer: &mut Vec<u32>) {
407        use TriangleContents::*;
408        match self {
409            None | One(_) => {}
410            &Three { a, b, c } => buffer.extend_from_slice(&[a, b, c]),
411            &Six {
412                a,
413                b,
414                c,
415                ab,
416                bc,
417                ca,
418            } => {
419                buffer.extend_from_slice(&[a, ab, ca]);
420                buffer.extend_from_slice(&[ab, b, bc]);
421                buffer.extend_from_slice(&[bc, c, ca]);
422
423                buffer.extend_from_slice(&[ab, bc, ca]);
424            }
425            &More {
426                a,
427                b,
428                c,
429                ref sides,
430                my_side_length,
431                ref contents,
432            } => {
433                let my_side_length = my_side_length as usize;
434                let ab = &sides[0..my_side_length];
435                let bc = &sides[my_side_length..my_side_length * 2];
436                let ca = &sides[my_side_length * 2..];
437
438                // Contents are always stored forward.
439                add_indices_triangular(
440                    a,
441                    b,
442                    c,
443                    Forward(ab),
444                    Forward(bc),
445                    Forward(ca),
446                    &**contents,
447                    buffer,
448                );
449                contents.add_indices(buffer);
450            }
451        }
452    }
453}
454
455#[derive(Clone, Debug)]
456pub struct Triangle {
457    pub a: u32,
458    pub b: u32,
459    pub c: u32,
460    pub ab_edge: usize,
461    pub bc_edge: usize,
462    pub ca_edge: usize,
463    pub(crate) ab_forward: bool,
464    pub(crate) bc_forward: bool,
465    pub(crate) ca_forward: bool,
466
467    pub(crate) contents: TriangleContents,
468}
469
470impl Default for Triangle {
471    fn default() -> Self {
472        Self {
473            a: 0,
474            b: 0,
475            c: 0,
476            ab_edge: 0,
477            bc_edge: 0,
478            ca_edge: 0,
479            ab_forward: false,
480            bc_forward: false,
481            ca_forward: false,
482            contents: TriangleContents::None,
483        }
484    }
485}
486
487impl Triangle {
488    pub const fn new(a: u32, b: u32, c: u32, ab_edge: usize, bc_edge: usize, ca_edge: usize) -> Self {
489        Self {
490            a,
491            b,
492            c,
493            ab_edge,
494            bc_edge,
495            ca_edge,
496
497            ab_forward: false,
498            bc_forward: false,
499            ca_forward: false,
500
501            contents: TriangleContents::None,
502        }
503    }
504
505    fn subdivide_edges<V: Vec3>(
506        &mut self,
507        edges: &mut [Edge],
508        points: &mut Vec<V>,
509        calculate: bool,
510        shape: &impl BaseShape<V>,
511    ) -> usize {
512        let mut divide = |p1: u32, p2: u32, edge_idx: usize, forward: &mut bool| {
513            if !edges[edge_idx].done {
514                edges[edge_idx].points.push(points.len() as u32);
515                points.push(V::ZERO);
516
517                if calculate {
518                    shape.interpolate_multiple(
519                        points[p1 as usize],
520                        points[p2 as usize],
521                        &edges[edge_idx].points,
522                        points,
523                    );
524                }
525
526                edges[edge_idx].done = true;
527                *forward = true;
528            } else {
529                *forward = false;
530            }
531        };
532
533        divide(self.a, self.b, self.ab_edge, &mut self.ab_forward);
534        divide(self.b, self.c, self.bc_edge, &mut self.bc_forward);
535        divide(self.c, self.a, self.ca_edge, &mut self.ca_forward);
536
537        edges[self.ab_edge].points.len()
538    }
539
540    fn subdivide<V: Vec3>(
541        &mut self,
542        edges: &mut [Edge],
543        points: &mut Vec<V>,
544        calculate: bool,
545        shape: &impl BaseShape<V>,
546    ) {
547        let side_length = self.subdivide_edges(edges, points, calculate, shape) + 1;
548
549        if side_length > 2 {
550            let ab = if self.ab_forward {
551                Forward(&edges[self.ab_edge].points)
552            } else {
553                Backward(&edges[self.ab_edge].points)
554            };
555            let bc = if self.bc_forward {
556                Forward(&edges[self.bc_edge].points)
557            } else {
558                Backward(&edges[self.bc_edge].points)
559            };
560            let ca = if self.ca_forward {
561                Forward(&edges[self.ca_edge].points)
562            } else {
563                Backward(&edges[self.ca_edge].points)
564            };
565            self.contents.subdivide(ab, bc, ca, points, calculate, shape);
566        }
567    }
568
569    fn add_indices(&self, buffer: &mut Vec<u32>, edges: &[Edge]) {
570        let ab = if self.ab_forward {
571            Forward(&edges[self.ab_edge].points)
572        } else {
573            Backward(&edges[self.ab_edge].points)
574        };
575        let bc = if self.bc_forward {
576            Forward(&edges[self.bc_edge].points)
577        } else {
578            Backward(&edges[self.bc_edge].points)
579        };
580        let ca = if self.ca_forward {
581            Forward(&edges[self.ca_edge].points)
582        } else {
583            Backward(&edges[self.ca_edge].points)
584        };
585
586        add_indices_triangular(self.a, self.b, self.c, ab, bc, ca, &self.contents, buffer);
587
588        self.contents.add_indices(buffer);
589    }
590}
591
592pub struct Subdivided<T, V: Vec3, S: BaseShape<V>> {
593    points: Vec<V>,
594    data: Vec<T>,
595    triangles: Box<[Triangle]>,
596    shared_edges: Box<[Edge]>,
597    subdivisions: usize,
598    shape: S,
599}
600
601impl<T, V: Vec3, S: BaseShape<V> + Default> Subdivided<T, V, S> {
602    pub fn new(subdivisions: usize, generator: impl FnMut(V) -> T) -> Self {
603        Self::new_custom_shape(subdivisions, generator, S::default())
604    }
605}
606
607impl<T, V: Vec3, S: BaseShape<V>> Subdivided<T, V, S> {
608    pub fn new_custom_shape(subdivisions: usize, generator: impl FnMut(V) -> T, shape: S) -> Self {
609        let mut this = Self {
610            points: shape.initial_points(),
611            shared_edges: {
612                let mut edges = Vec::new();
613                edges.resize_with(S::EDGES, Edge::default);
614                edges.into_boxed_slice()
615            },
616            triangles: shape.triangles(),
617            subdivisions: 1,
618            data: vec![],
619            shape,
620        };
621
622        match subdivisions {
623            0 => {}
624            1 => this.subdivide(true),
625            x => {
626                for _ in 0..x - 1 {
627                    this.subdivide(false);
628                }
629
630                this.subdivide(true);
631            }
632        }
633
634        this.data = this.points.iter().copied().map(generator).collect();
635
636        this
637    }
638
639    fn subdivide(&mut self, calculate: bool) {
640        for Edge { done, .. } in &mut *self.shared_edges {
641            *done = false;
642        }
643
644        for triangle in &mut *self.triangles {
645            triangle.subdivide(&mut *self.shared_edges, &mut self.points, calculate, &self.shape);
646        }
647    }
648
649    pub fn raw_user_data(&self) -> &[T] {
650        &self.data
651    }
652
653    pub fn raw_points(&self) -> &[V] {
654        &self.points
655    }
656
657    pub fn get_indices(&self, triangle: usize, buffer: &mut Vec<u32>) {
658        self.triangles[triangle].add_indices(buffer, &self.shared_edges);
659    }
660
661    pub fn get_all_indices(&self) -> Vec<u32> {
662        let mut buffer = Vec::new();
663
664        for i in 0..self.triangles.len() {
665            self.get_indices(i, &mut buffer);
666        }
667
668        buffer
669    }
670
671    pub fn subdivisions(&self) -> usize {
672        self.subdivisions
673    }
674}
675
676// The logic in this function has been worked out mostly on pen and paper
677// and therefore it is difficult to read.
678fn add_indices_triangular(
679    a: u32,
680    b: u32,
681    c: u32,
682    ab: Slice<u32>,
683    bc: Slice<u32>,
684    ca: Slice<u32>,
685    contents: &TriangleContents,
686    buffer: &mut Vec<u32>,
687) {
688    let subdivisions = ab.len();
689    if subdivisions == 0 {
690        buffer.extend_from_slice(&[a, b, c]);
691        return;
692    } else if subdivisions == 1 {
693        buffer.extend_from_slice(&[a, ab[0], ca[0]]);
694        buffer.extend_from_slice(&[b, bc[0], ab[0]]);
695        buffer.extend_from_slice(&[c, ca[0], bc[0]]);
696        buffer.extend_from_slice(&[ab[0], bc[0], ca[0]]);
697        return;
698    } else if subdivisions == 2 {
699        buffer.extend_from_slice(&[a, ab[0], ca[1]]);
700        buffer.extend_from_slice(&[b, bc[0], ab[1]]);
701        buffer.extend_from_slice(&[c, ca[0], bc[1]]);
702
703        buffer.extend_from_slice(&[ab[1], contents.idx_ab(0), ab[0]]);
704        buffer.extend_from_slice(&[bc[1], contents.idx_ab(0), bc[0]]);
705        buffer.extend_from_slice(&[ca[1], contents.idx_ab(0), ca[0]]);
706
707        buffer.extend_from_slice(&[ab[0], contents.idx_ab(0), ca[1]]);
708        buffer.extend_from_slice(&[bc[0], contents.idx_ab(0), ab[1]]);
709        buffer.extend_from_slice(&[ca[0], contents.idx_ab(0), bc[1]]);
710        return;
711    }
712
713    let last_idx = ab.len() - 1;
714
715    buffer.extend_from_slice(&[a, ab[0], ca[last_idx]]);
716    buffer.extend_from_slice(&[b, bc[0], ab[last_idx]]);
717    buffer.extend_from_slice(&[c, ca[0], bc[last_idx]]);
718
719    buffer.extend_from_slice(&[ab[0], contents.idx_ab(0), ca[last_idx]]);
720    buffer.extend_from_slice(&[bc[0], contents.idx_bc(0), ab[last_idx]]);
721    buffer.extend_from_slice(&[ca[0], contents.idx_ca(0), bc[last_idx]]);
722
723    for i in 0..last_idx - 1 {
724        // Exclude special case: last_idx - 1.
725        // AB
726        buffer.extend_from_slice(&[ab[i], ab[i + 1], contents.idx_ab(i)]);
727        buffer.extend_from_slice(&[ab[i + 1], contents.idx_ab(i + 1), contents.idx_ab(i)]);
728        // BC
729        buffer.extend_from_slice(&[bc[i], bc[i + 1], contents.idx_bc(i)]);
730        buffer.extend_from_slice(&[bc[i + 1], contents.idx_bc(i + 1), contents.idx_bc(i)]);
731        // CA
732        buffer.extend_from_slice(&[ca[i], ca[i + 1], contents.idx_ca(i)]);
733        buffer.extend_from_slice(&[ca[i + 1], contents.idx_ca(i + 1), contents.idx_ca(i)]);
734    }
735
736    // Deal with special case: last_idx - 1
737    buffer.extend_from_slice(&[
738        ab[last_idx],
739        contents.idx_ab(last_idx - 1),
740        ab[last_idx - 1],
741    ]);
742
743    buffer.extend_from_slice(&[
744        bc[last_idx],
745        contents.idx_bc(last_idx - 1),
746        bc[last_idx - 1],
747    ]);
748
749    buffer.extend_from_slice(&[
750        ca[last_idx],
751        contents.idx_ca(last_idx - 1),
752        ca[last_idx - 1],
753    ]);
754}
755
756#[cfg(test)]
757mod tests {
758    use crate::shapes::IcoSphere;
759    use crate::Slice::Forward;
760    use glam::Vec3A;
761
762    impl crate::Vec3 for glam::Vec3A {
763        const ZERO: Self = Vec3A::ZERO;
764
765        fn dot(self, other: Self) -> f32 {
766            self.dot(other)
767        }
768
769        fn normalize(self) -> Self {
770            self.normalize()
771        }
772
773        fn from_arr3([x, y, z]: [f32; 3]) -> Self {
774            Self::new(x, y, z)
775        }
776    }
777
778    // Starting points aren't _quite_ precise enough to use `f32::EPSILON`.
779    const EPSILON: f32 = 0.0000002;
780
781    #[test]
782    fn slerp_one() {
783        use crate::interpolation::geometric_slerp_half;
784        let p1 = Vec3A::new(0.360492952832, 0.932761936915, 0.0);
785        let p2 = Vec3A::new(0.975897449331, 0.218229623081, 0.0);
786
787        let expected = Vec3A::new(0.757709663147, 0.652591806854, 0.0);
788
789        let result = geometric_slerp_half(p1, p2);
790
791        assert!((expected - result).length() <= EPSILON);
792
793        // Another test case
794        let p1 = Vec3A::new(-0.24953852315, 0.0, 0.968364872073);
795        let p2 = Vec3A::new(-0.948416666565, 0.0, 0.317026539239);
796
797        let expected = Vec3A::new(-0.681787771301, 0.0, 0.731550022148);
798
799        let result = geometric_slerp_half(p1, p2);
800
801        assert!((expected - result).length() <= EPSILON);
802    }
803
804    #[test]
805    fn slerp_many() {
806        use crate::interpolation::geometric_slerp_multiple;
807
808        let p1 = Vec3A::new(0.0, -0.885330189449, 0.464962854054);
809        let p2 = Vec3A::new(0.0, 0.946042343528, 0.324043028395);
810
811        let expected = Vec3A::new(0.0, 0.0767208624118, 0.997052611085);
812
813        let mut result = Vec3A::ZERO;
814        geometric_slerp_multiple(p1, p2, &[0], std::slice::from_mut(&mut result));
815
816        assert!((expected - result).length() <= EPSILON);
817
818        let p1 = Vec3A::new(0.876621956288, 0.0, 0.481179743707);
819        let p2 = Vec3A::new(-0.391617625614, 0.0, -0.920128053756);
820
821        let expected = [
822            Vec3A::new(0.999975758841, 0.0, 0.00696288230076),
823            Vec3A::new(0.883237589397, 0.0, -0.468925751774),
824            Vec3A::new(0.554436024709, 0.0, -0.83222634812),
825            Vec3A::new(0.0925155945469, 0.0, -0.995711235633),
826        ];
827
828        let mut result = [Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO];
829
830        geometric_slerp_multiple(p1, p2, &[0, 1, 2, 3], &mut result);
831
832        for (&expected, &result) in expected.iter().zip(result.iter()) {
833            assert!((expected - result).length() <= EPSILON);
834        }
835    }
836
837    #[test]
838    fn new() {
839        let x = IcoSphere::new(0, |_: Vec3A| ());
840        x.get_indices(0, &mut Vec::new());
841    }
842
843    #[test]
844    fn one() {
845        let x = IcoSphere::new(1, |_: Vec3A| ());
846        x.get_indices(0, &mut Vec::new());
847    }
848
849    #[test]
850    fn second_layer_inner() {
851        let x = IcoSphere::new(2, |_: Vec3A| ());
852        x.get_indices(0, &mut Vec::new());
853        let x = IcoSphere::new(3, |_: Vec3A| ());
854        x.get_indices(0, &mut Vec::new());
855        let x = IcoSphere::new(5, |_: Vec3A| ());
856        x.get_indices(0, &mut Vec::new());
857        let x = IcoSphere::new(6, |_: Vec3A| ());
858        x.get_indices(0, &mut Vec::new());
859    }
860
861    #[test]
862    fn indices_zero() {
863        use super::add_indices_triangular;
864        use super::TriangleContents;
865
866        let mut buffer = Vec::new();
867
868        add_indices_triangular(
869            0,
870            1,
871            2,
872            Forward(&[]),
873            Forward(&[]),
874            Forward(&[]),
875            &TriangleContents::none(),
876            &mut buffer,
877        );
878
879        assert_eq!(buffer, &[0, 1, 2]);
880    }
881
882    #[test]
883    fn indices_one() {
884        use super::add_indices_triangular;
885        use super::TriangleContents;
886
887        let mut buffer = Vec::new();
888
889        add_indices_triangular(
890            0,
891            1,
892            2,
893            Forward(&[3]),
894            Forward(&[4]),
895            Forward(&[5]),
896            &TriangleContents::none(),
897            &mut buffer,
898        );
899
900        assert_eq!(buffer, &[0, 3, 5, 1, 4, 3, 2, 5, 4, 3, 4, 5,]);
901    }
902
903    #[test]
904    fn indices_two() {
905        use super::add_indices_triangular;
906        use super::TriangleContents;
907
908        let mut buffer = Vec::new();
909
910        add_indices_triangular(
911            0,
912            3,
913            6,
914            Forward(&[1, 2]),
915            Forward(&[4, 5]),
916            Forward(&[7, 8]),
917            &TriangleContents::One(9),
918            &mut buffer,
919        );
920
921        assert_eq!(
922            buffer,
923            &[0, 1, 8, 3, 4, 2, 6, 7, 5, 2, 9, 1, 5, 9, 4, 8, 9, 7, 1, 9, 8, 4, 9, 2, 7, 9, 5,]
924        );
925    }
926
927    // Really, we're testing for the rest.
928    #[test]
929    fn indices_three() {
930        use super::add_indices_triangular;
931        use super::TriangleContents;
932
933        let mut buffer = Vec::new();
934
935        add_indices_triangular(
936            0,
937            4,
938            8,
939            Forward(&[1, 2, 3]),
940            Forward(&[5, 6, 7]),
941            Forward(&[9, 10, 11]),
942            &TriangleContents::Three {
943                a: 12,
944                b: 13,
945                c: 14,
946            },
947            &mut buffer,
948        );
949
950        assert_eq!(
951            buffer,
952            &[
953                0, 1, 11, 4, 5, 3, 8, 9, 7, 1, 12, 11, 5, 13, 3, 9, 14, 7, 1, 2, 12, 2, 13, 12, 5,
954                6, 13, 6, 14, 13, 9, 10, 14, 10, 12, 14, 3, 13, 2, 7, 14, 6, 11, 12, 10,
955            ][..]
956        );
957    }
958
959    #[test]
960    fn precision() {
961        let sphere = IcoSphere::new(10, |_: Vec3A| ());
962
963        for i in sphere.raw_points() {
964            assert!(i.length() - 1.0 <= EPSILON);
965        }
966    }
967}