hexasphere/
lib.rs

1//!
2//! Library for subdividing shapes made of triangles.
3//!
4//! This library defines [`Subdivided<T, S>`](Subdivided). This struct
5//! allows one to define a base shape using `S` and the
6//! [`BaseShape`] trait, and to subdivide it using the
7//! interpolation functions defined as part of `S`.
8//!
9//! Shapes define the starting vertices and triangles, as well as
10//! the type of interpolation used and thus the smooth shape that is approximated.
11//! These provided shapes generate **spheres**:
12//!
13//! - [`shapes::CubeSphere`] (cube)
14//! - [`shapes::IcoSphere`] (icosahedron)
15//! - [`shapes::NormIcoSphere`] (icosahedron)
16//! - [`shapes::TetraSphere`] (tetrahedron)
17//!
18//! Two flat shapes are also provided:
19//!
20//! - [`shapes::SquarePlane`]
21//! - [`shapes::TrianglePlane`]
22//!
23//! ## Example usage
24//!
25//! ```rust
26//! use hexasphere::shapes::IcoSphere;
27//!
28//! fn main() {
29//!     // Create a new sphere with 20 subdivisions
30//!     // an no data associated with the vertices.
31//!     let sphere = IcoSphere::new(20, |_| ());
32//!
33//!     let points = sphere.raw_points();
34//!     for p in points {
35//!         println!("{:?} is a point on the sphere!", p);
36//!     }
37//!     let indices = sphere.get_all_indices();
38//!     for triangle in indices.chunks(3) {
39//!         println!(
40//!             "[{}, {}, {}] is a triangle on the resulting shape",
41//!             triangle[0],
42//!             triangle[1],
43//!             triangle[2],
44//!         );
45//!     }
46//! }
47//! ```
48//!
49//! # Features
50//! - `adjacency` allows the user to create neighbour maps from
51//! the indices provided by the `Subdivided` struct.
52//!
53#![cfg_attr(not(feature = "std"), no_std)]
54
55use glam::Vec3A;
56
57#[doc(hidden)]
58#[macro_use]
59extern crate alloc;
60
61use alloc::boxed::Box;
62use alloc::vec::Vec;
63
64use slice::Slice::*;
65use slice::*;
66
67#[cfg(feature = "adjacency")]
68pub use adjacency::*;
69
70pub mod interpolation;
71mod math;
72pub mod shapes;
73mod slice;
74///
75/// Defines the geometry of the shape to be subdivided, and the functions
76/// used in interpolation.
77///
78/// If you want to use a different interpolation function,
79/// implement this trait for a new type, and carry over only
80/// the properties you'd like to keep:
81///
82/// ```rust
83/// # use hexasphere::BaseShape;
84/// use hexasphere::{Triangle, shapes::IcoSphereBase};
85/// use glam::Vec3A;
86/// // Uses linear interpolation instead of spherical.
87/// struct FlatIcosahedron;
88///
89/// impl BaseShape for FlatIcosahedron {
90///     // Keep the initial parameters.
91///     fn initial_points(&self) -> Vec<Vec3A> {
92///         IcoSphereBase.initial_points()
93///     }
94///
95///     fn triangles(&self) -> Box<[Triangle]> {
96///         IcoSphereBase.triangles()
97///     }
98///     const EDGES: usize = IcoSphereBase::EDGES;
99///
100///     // Swap out what you'd like to change.
101///     fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
102///         hexasphere::interpolation::lerp(a, b, p)
103///     }
104///
105///     fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
106///         hexasphere::interpolation::lerp_half(a, b)
107///     }
108///
109///     fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
110///         hexasphere::interpolation::lerp_multiple(a, b, indices, points);
111///     }
112/// }
113/// ```
114///
115/// Or, create your own shape, by changing the values for
116/// [`initial_points`], [`triangles`], and [`EDGES`]. Check
117/// the documentation for these members individually on how
118/// they should be implemented.
119///
120/// [`initial_points`]: #tymethod.initial_points
121/// [`triangles`]: #tymethod.triangles
122/// [`EDGES`]: #associatedconstant.EDGES
123///
124pub trait BaseShape {
125    ///
126    /// The vertices for all main triangles of the shape.
127    /// Check the source file for this
128    /// crate and look for the constants module at the bottom
129    /// for an example.
130    ///
131    /// Constraints on the points depend on the interpolation
132    /// function used:
133    /// - `slerp` requires normalized (magnitude 1) data.
134    /// - `lerp` doesn't care.
135    /// - `normalized_lerp` requires normalized (magnitude 1)
136    /// data.
137    ///
138    fn initial_points(&self) -> Vec<Vec3A>;
139
140    ///
141    /// Main triangles for the shape;
142    /// that is, the triangles which exist before subdivision.
143    ///
144    /// See [`Triangle::new()`] for details.
145    ///
146    fn triangles(&self) -> Box<[Triangle]>;
147
148    ///
149    /// Number of unique edges defined in the contents of
150    /// `triangles()`. This number is 5 for a square for
151    /// example:
152    /// ```text
153    /// a - 0 - b
154    /// |     / |
155    /// 3   4   1
156    /// | /     |
157    /// d - 2 - c
158    /// ```
159    ///
160    const EDGES: usize;
161
162    ///
163    /// Basic function used for interpolation. When `p` is
164    /// `0.0`, `a` is expected. When `p` is `1.0`, `b` is
165    /// expected. There are three options already implemented
166    /// in this crate:
167    /// - [`lerp`] implements linear interpolation.
168    /// - [`geometric_slerp`] implements spherical
169    /// interpolation. (Interpolates along an arc on a sphere)
170    /// - [`normalized_lerp`] implements cheaper
171    /// yet less accurate spherical interpolation. The accuracy
172    /// decreases as the angle between the two points on the unit
173    /// sphere increases.
174    ///
175    /// [`lerp`]: ../fn.lerp.html
176    /// [`geometric_slerp`]: ../fn.geometric_slerp.html
177    /// [`normalized_lerp`]: ../fn.normalized_lerp.html
178    ///
179    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A;
180
181    ///
182    /// If an optimization is available for the case where `p`
183    /// is `0.5`, this function should implement it. This defaults
184    /// to calling `interpolate(a, b, 0.5)` however.
185    ///
186    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
187        self.interpolate(a, b, 0.5)
188    }
189
190    ///
191    /// If an optimization is available for the case where `p`
192    /// varies but `a` and `b` don't, this function should implement
193    /// it.
194    ///
195    /// ### Parameters
196    /// - `a`: start.
197    /// - `b`: end.
198    /// - `indices`: list of indices to index into `points`. `points`
199    /// at the index should contain the result. The index (n) of an
200    /// index should correspond with the nth point in a distribution
201    /// of `indices.len()` points between (exclusive) `a` and `b`.
202    /// - `points`: list of points where the results of the calculation
203    /// should end up. To be indexed by values in `indices`.
204    ///
205    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
206        for (percent, index) in indices.iter().enumerate() {
207            let percent = (percent + 1) as f32 / (indices.len() + 1) as f32;
208
209            points[*index as usize] = self.interpolate(a, b, percent);
210        }
211    }
212}
213
214///
215/// Implemented in the case where the triangles on the shape
216/// are both equilateral and identifiable from their normal.
217///
218/// This is only used in the cases of spherical shapes.
219///
220#[cfg(feature = "shape-extras")]
221pub trait EquilateralBaseShape: BaseShape {
222    ///
223    /// Normals for each of the triangles provided by
224    /// [`BaseShape::triangles`].
225    ///
226    fn triangle_normals() -> &'static [Vec3A];
227    ///
228    /// Minimum value for the dot product which one could use
229    /// to determine that triangle being the closest.
230    ///
231    /// If the dot product between a vector and a triangle
232    /// normal is greater than this, then that vector is
233    /// guaranteed to be within that triangle.
234    ///
235    /// This is also the cosine of the angle of the cone
236    /// whose circular edge lies on a triangle.
237    ///
238    fn triangle_min_dot() -> f32;
239}
240
241///
242/// The edge between two main triangles.
243///
244#[derive(Debug, Clone)]
245struct Edge {
246    ///
247    /// Indices of the points between the endpoints.
248    ///
249    points: Vec<u32>,
250    ///
251    /// Whether this edge has already been processed
252    /// or not for point generation.
253    ///
254    done: bool,
255}
256
257impl Default for Edge {
258    fn default() -> Self {
259        Self {
260            points: Vec::new(),
261            done: true,
262        }
263    }
264}
265
266impl Edge {
267    pub fn subdivide_n_times(&mut self, n: usize, points: &mut usize) {
268        for _ in 0..n {
269            self.points.push(*points as _);
270            *points += 1;
271        }
272    }
273}
274
275///
276/// Contents of one of the main triangular faces.
277///
278/// This is *not* the entire face, it is the points which do
279/// not include the exterior edges and vertices since those are
280/// shared.
281///
282#[derive(Clone, Debug)]
283enum TriangleContents {
284    ///
285    /// Nothing inside the triangle: subdivisions 0 and 1
286    ///
287    None,
288    ///
289    /// One point inside the triangle: subdivision 2
290    ///
291    One(u32),
292    ///
293    /// Three points inside the triangle: subdivision 3
294    ///
295    Three { a: u32, b: u32, c: u32 },
296    ///
297    /// Six points inside the triangle: subdivision 4
298    ///
299    Six {
300        a: u32,
301        b: u32,
302        c: u32,
303        ab: u32,
304        bc: u32,
305        ca: u32,
306    },
307    ///
308    /// More than six points inside the triangle: subdivision > 4
309    ///
310    More {
311        a: u32,
312        b: u32,
313        c: u32,
314        // Separated into three `my_side_length` segments
315        // to save on extra allocations.
316        sides: Vec<u32>,
317        my_side_length: u32,
318        ///
319        /// Contents of the inner triangle.
320        ///
321        // Implementing this as a `Vec<TriangleContents>` would
322        // probably be a perf. improvement someday, however not
323        // something worth implementing right now.
324        contents: Box<TriangleContents>,
325    },
326}
327
328impl TriangleContents {
329    ///
330    /// Creates a `None` variant.
331    ///
332    pub fn none() -> Self {
333        Self::None
334    }
335
336    ///
337    /// Creates a `One` by interpolating two values.
338    ///
339    fn one(points: &mut usize) -> Self {
340        let index = *points as u32;
341        *points += 1;
342        TriangleContents::One(index)
343    }
344
345    fn calculate_one(
346        &self,
347        ab: Slice<u32>,
348        bc: Slice<u32>,
349        points: &mut [Vec3A],
350        shape: &impl BaseShape,
351    ) {
352        assert_eq!(ab.len(), bc.len());
353        assert_eq!(ab.len(), 2);
354        match self {
355            TriangleContents::One(idx) => {
356                let p1 = points[ab[0] as usize];
357                let p2 = points[bc[1] as usize];
358
359                points[*idx as usize] = shape.interpolate_half(p1, p2);
360            }
361            _ => panic!("Did not find One variant."),
362        }
363    }
364
365    ///
366    /// Creates a `Three` variant from a `One` variant.
367    ///
368    fn three(&mut self, points: &mut usize) {
369        use TriangleContents::*;
370
371        match self {
372            &mut One(x) => {
373                *points += 2;
374
375                *self = Three {
376                    a: x,
377                    b: *points as u32 - 2,
378                    c: *points as u32 - 1,
379                };
380            }
381            _ => panic!("Self is {:?} while it should be One", self),
382        }
383    }
384
385    fn calculate_three(
386        &self,
387        ab: Slice<u32>,
388        bc: Slice<u32>,
389        ca: Slice<u32>,
390        points: &mut [Vec3A],
391        shape: &impl BaseShape,
392    ) {
393        assert_eq!(ab.len(), bc.len());
394        assert_eq!(ab.len(), ca.len());
395        assert_eq!(ab.len(), 3);
396
397        match self {
398            &TriangleContents::Three { a, b, c } => {
399                let ab = points[ab[1] as usize];
400                let bc = points[bc[1] as usize];
401                let ca = points[ca[1] as usize];
402
403                let a_val = shape.interpolate_half(ab, ca);
404                let b_val = shape.interpolate_half(bc, ab);
405                let c_val = shape.interpolate_half(ca, bc);
406
407                points[a as usize] = a_val;
408                points[b as usize] = b_val;
409                points[c as usize] = c_val;
410            }
411            _ => panic!("Did not find Three variant."),
412        }
413    }
414
415    ///
416    /// Creates a `Six` variant from a `Three` variant.
417    ///
418    fn six(&mut self, points: &mut usize) {
419        use TriangleContents::*;
420
421        match self {
422            &mut Three {
423                a: a_index,
424                b: b_index,
425                c: c_index,
426            } => {
427                *points += 3;
428
429                *self = Six {
430                    a: a_index,
431                    b: b_index,
432                    c: c_index,
433                    ab: *points as u32 - 3,
434                    bc: *points as u32 - 2,
435                    ca: *points as u32 - 1,
436                };
437            }
438            _ => panic!("Found {:?} whereas a Three was expected", self),
439        }
440    }
441
442    fn calculate_six(
443        &self,
444        ab: Slice<u32>,
445        bc: Slice<u32>,
446        ca: Slice<u32>,
447        points: &mut [Vec3A],
448        shape: &impl BaseShape,
449    ) {
450        assert_eq!(ab.len(), bc.len());
451        assert_eq!(ab.len(), ca.len());
452        assert_eq!(ab.len(), 4);
453
454        use TriangleContents::*;
455
456        match self {
457            &Six {
458                a: a_index,
459                b: b_index,
460                c: c_index,
461                ab: ab_index,
462                bc: bc_index,
463                ca: ca_index,
464            } => {
465                let aba = points[ab[1] as usize];
466                let abb = points[ab[2] as usize];
467                let bcb = points[bc[1] as usize];
468                let bcc = points[bc[2] as usize];
469                let cac = points[ca[1] as usize];
470                let caa = points[ca[2] as usize];
471
472                let a = shape.interpolate_half(aba, caa);
473                let b = shape.interpolate_half(abb, bcb);
474                let c = shape.interpolate_half(bcc, cac);
475
476                let ab = shape.interpolate_half(a, b);
477                let bc = shape.interpolate_half(b, c);
478                let ca = shape.interpolate_half(c, a);
479
480                points[a_index as usize] = a;
481                points[b_index as usize] = b;
482                points[c_index as usize] = c;
483                points[ab_index as usize] = ab;
484                points[bc_index as usize] = bc;
485                points[ca_index as usize] = ca;
486            }
487            _ => panic!("Found {:?} whereas a Three was expected", self),
488        }
489    }
490
491    ///
492    /// Subdivides this given the surrounding points.
493    ///
494    fn subdivide(&mut self, points: &mut usize) {
495        use TriangleContents::*;
496
497        match self {
498            None => *self = Self::one(points),
499            One(_) => self.three(points),
500            Three { .. } => self.six(points),
501            &mut Six {
502                a,
503                b,
504                c,
505                ab: ab_idx,
506                bc: bc_idx,
507                ca: ca_idx,
508            } => {
509                *self = More {
510                    a,
511                    b,
512                    c,
513                    sides: vec![ab_idx, bc_idx, ca_idx],
514                    my_side_length: 1,
515                    contents: Box::new(Self::none()),
516                };
517                self.subdivide(points);
518            }
519            More {
520                sides,
521                contents,
522                my_side_length,
523                ..
524            } => {
525                *points += 3;
526                let len = *points as u32;
527                sides.extend_from_slice(&[len - 3, len - 2, len - 1]);
528                *my_side_length += 1;
529
530                contents.subdivide(points);
531            }
532        }
533    }
534
535    pub fn calculate(
536        &mut self,
537        ab: Slice<u32>,
538        bc: Slice<u32>,
539        ca: Slice<u32>,
540        points: &mut [Vec3A],
541        shape: &impl BaseShape,
542    ) {
543        assert_eq!(ab.len(), bc.len());
544        assert_eq!(ab.len(), ca.len());
545        assert!(ab.len() >= 2);
546
547        use TriangleContents::*;
548
549        match self {
550            None => panic!(),
551            One(_) => self.calculate_one(ab, bc, points, shape),
552            Three { .. } => self.calculate_three(ab, bc, ca, points, shape),
553            Six { .. } => self.calculate_six(ab, bc, ca, points, shape),
554            &mut More {
555                a: a_idx,
556                b: b_idx,
557                c: c_idx,
558                ref mut sides,
559                ref mut contents,
560                ref mut my_side_length,
561            } => {
562                let side_length = *my_side_length as usize;
563
564                let outer_len = ab.len();
565
566                let aba = points[ab[1] as usize];
567                let abb = points[ab[outer_len - 2] as usize];
568                let bcb = points[bc[1] as usize];
569                let bcc = points[bc[outer_len - 2] as usize];
570                let cac = points[ca[1] as usize];
571                let caa = points[ca[outer_len - 2] as usize];
572
573                points[a_idx as usize] = shape.interpolate_half(aba, caa);
574                points[b_idx as usize] = shape.interpolate_half(abb, bcb);
575                points[c_idx as usize] = shape.interpolate_half(bcc, cac);
576
577                let ab = &sides[0..side_length];
578                let bc = &sides[side_length..side_length * 2];
579                let ca = &sides[side_length * 2..];
580
581                shape.interpolate_multiple(
582                    points[a_idx as usize],
583                    points[b_idx as usize],
584                    ab,
585                    points,
586                );
587                shape.interpolate_multiple(
588                    points[b_idx as usize],
589                    points[c_idx as usize],
590                    bc,
591                    points,
592                );
593                shape.interpolate_multiple(
594                    points[c_idx as usize],
595                    points[a_idx as usize],
596                    ca,
597                    points,
598                );
599
600                contents.calculate(Forward(ab), Forward(bc), Forward(ca), points, shape);
601            }
602        }
603    }
604
605    ///
606    /// Indexes the AB edge.
607    ///
608    /// This is inclusive of A and B.
609    ///
610    pub fn idx_ab(&self, idx: usize) -> u32 {
611        use TriangleContents::*;
612        match self {
613            None => panic!("Invalid Index, len is 0, but got {}", idx),
614            One(x) => {
615                if idx != 0 {
616                    panic!("Invalid Index, len is 1, but got {}", idx);
617                } else {
618                    *x
619                }
620            }
621            Three { a, b, .. } => *[a, b][idx],
622            Six { a, b, ab, .. } => *[a, ab, b][idx],
623            &More {
624                a,
625                b,
626                ref sides,
627                my_side_length,
628                ..
629            } => match idx {
630                0 => a,
631                x if (1..(my_side_length as usize + 1)).contains(&x) => sides[x - 1],
632                x if x == my_side_length as usize + 1 => b,
633                _ => panic!(
634                    "Invalid Index, len is {}, but got {}",
635                    my_side_length + 2,
636                    idx
637                ),
638            },
639        }
640    }
641
642    ///
643    /// Indexes the BC edge.
644    ///
645    /// This is inclusive of B and C.
646    ///
647    pub fn idx_bc(&self, idx: usize) -> u32 {
648        use TriangleContents::*;
649        match self {
650            None => panic!("Invalid Index, len is 0, but got {}", idx),
651            One(x) => {
652                if idx != 0 {
653                    panic!("Invalid Index, len is 1, but got {}", idx);
654                } else {
655                    *x
656                }
657            }
658            Three { c, b, .. } => *[b, c][idx],
659            Six { b, c, bc, .. } => *[b, bc, c][idx],
660            &More {
661                b,
662                c,
663                ref sides,
664                my_side_length,
665                ..
666            } => match idx {
667                0 => b,
668                x if (1..(my_side_length as usize + 1)).contains(&x) => {
669                    sides[my_side_length as usize + (x - 1)]
670                }
671                x if x == my_side_length as usize + 1 => c,
672                _ => panic!(
673                    "Invalid Index, len is {}, but got {}",
674                    my_side_length + 2,
675                    idx
676                ),
677            },
678        }
679    }
680
681    ///
682    /// Indexes the CA edge.
683    ///
684    /// This is inclusive of C and A.
685    ///
686    pub fn idx_ca(&self, idx: usize) -> u32 {
687        use TriangleContents::*;
688        match self {
689            None => panic!("Invalid Index, len is 0, but got {}", idx),
690            One(x) => {
691                if idx != 0 {
692                    panic!("Invalid Index, len is 1, but got {}", idx);
693                } else {
694                    *x
695                }
696            }
697            Three { c, a, .. } => *[c, a][idx],
698            Six { c, a, ca, .. } => *[c, ca, a][idx],
699            &More {
700                c,
701                a,
702                ref sides,
703                my_side_length,
704                ..
705            } => match idx {
706                0 => c,
707                x if (1..(my_side_length as usize + 1)).contains(&x) => {
708                    sides[my_side_length as usize * 2 + x - 1]
709                }
710                x if x == my_side_length as usize + 1 => a,
711                _ => panic!(
712                    "Invalid Index, len is {}, but got {}",
713                    my_side_length + 2,
714                    idx
715                ),
716            },
717        }
718    }
719
720    ///
721    /// Adds the indices in this portion of the triangle
722    /// to the specified buffer in order.
723    ///
724    pub fn add_indices(&self, buffer: &mut Vec<u32>) {
725        use TriangleContents::*;
726        match self {
727            None | One(_) => {}
728            &Three { a, b, c } => buffer.extend_from_slice(&[a, b, c]),
729            &Six {
730                a,
731                b,
732                c,
733                ab,
734                bc,
735                ca,
736            } => {
737                buffer.extend_from_slice(&[a, ab, ca]);
738                buffer.extend_from_slice(&[ab, b, bc]);
739                buffer.extend_from_slice(&[bc, c, ca]);
740
741                buffer.extend_from_slice(&[ab, bc, ca]);
742            }
743            &More {
744                a,
745                b,
746                c,
747                ref sides,
748                my_side_length,
749                ref contents,
750            } => {
751                let my_side_length = my_side_length as usize;
752                let ab = &sides[0..my_side_length];
753                let bc = &sides[my_side_length..my_side_length * 2];
754                let ca = &sides[my_side_length * 2..];
755
756                // Contents are always stored forward.
757                add_indices_triangular(
758                    a,
759                    b,
760                    c,
761                    Forward(ab),
762                    Forward(bc),
763                    Forward(ca),
764                    &**contents,
765                    buffer,
766                );
767                contents.add_indices(buffer);
768            }
769        }
770    }
771
772    ///
773    /// Adds the indices for a wireframe of the triangles
774    /// in this portion of the triangle to the specified
775    /// buffer in order.
776    ///
777    pub fn add_line_indices(
778        &self,
779        buffer: &mut Vec<u32>,
780        delta: u32,
781        mut breaks: impl FnMut(&mut Vec<u32>),
782    ) {
783        use TriangleContents::*;
784        match self {
785            None | One(_) | Three { .. } => {}
786            Six { ab, bc, ca, .. } => {
787                let ab = core::slice::from_ref(ab);
788                let bc = core::slice::from_ref(bc);
789                let ca = core::slice::from_ref(ca);
790                // buffer.extend_from_slice(&[ab + delta, bc + delta, ca + delta]);
791                add_line_indices_triangular(
792                    delta,
793                    Forward(ab),
794                    Forward(bc),
795                    Forward(ca),
796                    &TriangleContents::None,
797                    buffer,
798                );
799                breaks(buffer);
800            }
801            &More {
802                ref sides,
803                my_side_length,
804                ref contents,
805                ..
806            } => {
807                let my_side_length = my_side_length as usize;
808                let ab = &sides[0..my_side_length];
809                let bc = &sides[my_side_length..my_side_length * 2];
810                let ca = &sides[my_side_length * 2..];
811
812                // Contents are always stored forward.
813                add_line_indices_triangular(
814                    delta,
815                    Forward(ab),
816                    Forward(bc),
817                    Forward(ca),
818                    &**contents,
819                    buffer,
820                );
821                breaks(buffer);
822                contents.add_line_indices(buffer, delta, breaks);
823            }
824        }
825    }
826}
827
828#[derive(Clone, Debug)]
829///
830/// A main triangle on the base shape of a subdivided shape.
831///
832/// Main triangles are those which are part of the definition of the base shape,
833/// rather than created by subdivision.
834///
835/// The specification of the library expects `a`, `b`, and `c`
836/// to be in a counter-clockwise winding.
837///
838pub struct Triangle {
839    pub a: u32,
840    pub b: u32,
841    pub c: u32,
842    pub ab_edge: usize,
843    pub bc_edge: usize,
844    pub ca_edge: usize,
845    pub(crate) ab_forward: bool,
846    pub(crate) bc_forward: bool,
847    pub(crate) ca_forward: bool,
848
849    pub(crate) contents: TriangleContents,
850}
851
852impl Default for Triangle {
853    fn default() -> Self {
854        Self {
855            a: 0,
856            b: 0,
857            c: 0,
858            ab_edge: 0,
859            bc_edge: 0,
860            ca_edge: 0,
861            ab_forward: false,
862            bc_forward: false,
863            ca_forward: false,
864            contents: TriangleContents::None,
865        }
866    }
867}
868
869impl Triangle {
870    ///
871    /// Creates a new `Triangle` given the necessary data.
872    ///
873    /// - The fields `a`, `b`, and `c` are the indices into
874    ///   [`BaseShape::initial_points()`] which are the vertices
875    ///   of this triangle.
876    ///   Note that this crate assumes
877    ///   points are in a counter-clockwise ordering.
878    /// - The fields `ab_edge`, `bc_edge`, `ca_edge` mark the
879    ///   index of the edge which `a`/`b`, `b`/`c`, and `c`/`a`
880    ///   border respectively. While theoretically you could give
881    ///   each triangle its own edge, sharing edges between triangles
882    ///   saves on memory footprint and performance.
883    ///
884    ///   There is no explicit list of edges; they are defined by how
885    ///   they are used here. However, the total number of edges must
886    ///   be specified in [`BaseShape::EDGES`], and all edge indices
887    ///   from 0 to `EDGES - 1` must be used.
888    ///
889    pub const fn new(
890        a: u32,
891        b: u32,
892        c: u32,
893        ab_edge: usize,
894        bc_edge: usize,
895        ca_edge: usize,
896    ) -> Self {
897        Self {
898            a,
899            b,
900            c,
901            ab_edge,
902            bc_edge,
903            ca_edge,
904
905            ab_forward: false,
906            bc_forward: false,
907            ca_forward: false,
908
909            contents: TriangleContents::None,
910        }
911    }
912
913    fn calculate_edges(
914        &mut self,
915        edges: &mut [Edge],
916        points: &mut [Vec3A],
917        shape: &impl BaseShape,
918    ) -> usize {
919        let mut divide = |p1: u32, p2: u32, edge_idx: usize, forward: &mut bool| {
920            if !edges[edge_idx].done {
921                shape.interpolate_multiple(
922                    points[p1 as usize],
923                    points[p2 as usize],
924                    &edges[edge_idx].points,
925                    points,
926                );
927
928                edges[edge_idx].done = true;
929                *forward = true;
930            } else {
931                *forward = false;
932            }
933        };
934
935        divide(self.a, self.b, self.ab_edge, &mut self.ab_forward);
936        divide(self.b, self.c, self.bc_edge, &mut self.bc_forward);
937        divide(self.c, self.a, self.ca_edge, &mut self.ca_forward);
938
939        edges[self.ab_edge].points.len()
940    }
941
942    ///
943    /// Subdivides the edges and contents of this triangle.
944    ///
945    /// If `calculate` is set to `false`, then the points are
946    /// simply added to the buffer and the indices recorded,
947    /// but no calculations are performed.
948    ///
949    fn subdivide(&mut self, points: &mut usize, subdivision_level: usize) {
950        if subdivision_level >= 1 {
951            self.contents.subdivide(points);
952        }
953    }
954
955    fn calculate(&mut self, edges: &mut [Edge], points: &mut [Vec3A], shape: &impl BaseShape) {
956        let side_length = self.calculate_edges(edges, points, shape) + 1;
957
958        if side_length > 2 {
959            let ab = if self.ab_forward {
960                Forward(&edges[self.ab_edge].points)
961            } else {
962                Backward(&edges[self.ab_edge].points)
963            };
964            let bc = if self.bc_forward {
965                Forward(&edges[self.bc_edge].points)
966            } else {
967                Backward(&edges[self.bc_edge].points)
968            };
969            let ca = if self.ca_forward {
970                Forward(&edges[self.ca_edge].points)
971            } else {
972                Backward(&edges[self.ca_edge].points)
973            };
974            self.contents.calculate(ab, bc, ca, points, shape);
975        }
976    }
977
978    ///
979    /// Appends the indices of all the subtriangles onto the
980    /// specified buffer.
981    ///
982    fn add_indices(&self, buffer: &mut Vec<u32>, edges: &[Edge]) {
983        let ab = if self.ab_forward {
984            Forward(&edges[self.ab_edge].points)
985        } else {
986            Backward(&edges[self.ab_edge].points)
987        };
988        let bc = if self.bc_forward {
989            Forward(&edges[self.bc_edge].points)
990        } else {
991            Backward(&edges[self.bc_edge].points)
992        };
993        let ca = if self.ca_forward {
994            Forward(&edges[self.ca_edge].points)
995        } else {
996            Backward(&edges[self.ca_edge].points)
997        };
998
999        add_indices_triangular(self.a, self.b, self.c, ab, bc, ca, &self.contents, buffer);
1000
1001        self.contents.add_indices(buffer);
1002    }
1003
1004    ///
1005    /// Appends the indices of all the subtriangles' wireframes
1006    /// onto the specified buffer.
1007    ///
1008    fn add_line_indices(
1009        &self,
1010        buffer: &mut Vec<u32>,
1011        edges: &[Edge],
1012        delta: u32,
1013        mut breaks: impl FnMut(&mut Vec<u32>),
1014    ) {
1015        let ab = if self.ab_forward {
1016            Forward(&edges[self.ab_edge].points)
1017        } else {
1018            Backward(&edges[self.ab_edge].points)
1019        };
1020        let bc = if self.bc_forward {
1021            Forward(&edges[self.bc_edge].points)
1022        } else {
1023            Backward(&edges[self.bc_edge].points)
1024        };
1025        let ca = if self.ca_forward {
1026            Forward(&edges[self.ca_edge].points)
1027        } else {
1028            Backward(&edges[self.ca_edge].points)
1029        };
1030
1031        add_line_indices_triangular(delta, ab, bc, ca, &self.contents, buffer);
1032
1033        breaks(buffer);
1034
1035        self.contents.add_line_indices(buffer, delta, breaks);
1036    }
1037}
1038
1039///
1040/// A subdivided shape generated from some [`BaseShape`] and a subdivision level.
1041///
1042/// The subdivided shape is defined, as is conventional in most 3D graphics systems,
1043/// as a list of vertices, and a list of indices into the vertex list which connect
1044/// the vertices into primitive shapes. [`Subdivided`] can provide triangle-list indices
1045/// indices for solid surface rendering, and line-strip indices for wireframe rendering.
1046///
1047/// All main triangles specified by `S` in [`BaseShape`]
1048/// are expected to be in counter clockwise winding.
1049///
1050/// Points are preferably stored with coordinates less
1051/// than or equal to `1.0`. This is why all default shapes
1052/// lie on the unit sphere.
1053///
1054#[derive(Clone)]
1055pub struct Subdivided<T, S: BaseShape> {
1056    points: Vec<Vec3A>,
1057    data: Vec<T>,
1058    triangles: Box<[Triangle]>,
1059    shared_edges: Box<[Edge]>,
1060    subdivisions: usize,
1061    shape: S,
1062}
1063
1064impl<T, S: BaseShape> Subdivided<T, S> {
1065    /// Creates the base shape from `S` and subdivides it.
1066    ///
1067    /// This is equivalent to
1068    /// `Subdivided::new_custom_shape(subdivisions, generator, S::default())`
1069    /// and is convenient when `S` implements [`Default`].
1070    pub fn new(subdivisions: usize, generator: impl FnMut(Vec3A) -> T) -> Self
1071    where
1072        S: Default,
1073    {
1074        Self::new_custom_shape(subdivisions, generator, S::default())
1075    }
1076    ///
1077    /// Creates the base shape from `S` and subdivides it.
1078    ///
1079    /// - `subdivisions` specifies the number of auxiliary points that will be created
1080    ///   along the edges the vertices of the base shape. For example, if `subdivisions`
1081    ///   is 0, then the base shape is unaltered; if `subdivisions` is 3, then each edge
1082    ///   of the base shape will have 3 added points, forming 4 triangle edges.
1083    ///
1084    /// - `generator` is a function run for each vertex once all the subdivisions are
1085    ///   applied, and its values are stored in an internal `Vec`,
1086    ///   accessible from [`Self::raw_data()`].
1087    ///
1088    pub fn new_custom_shape(
1089        subdivisions: usize,
1090        generator: impl FnMut(Vec3A) -> T,
1091        shape: S,
1092    ) -> Self {
1093        let mut this = Self {
1094            points: shape.initial_points(),
1095            shared_edges: {
1096                let mut edges = Vec::new();
1097                edges.resize_with(S::EDGES, Edge::default);
1098                edges.into_boxed_slice()
1099            },
1100            triangles: shape.triangles(),
1101            subdivisions: 1,
1102            data: vec![],
1103            shape,
1104        };
1105
1106        let mut new_points = this.points.len();
1107
1108        for edge in &mut *this.shared_edges {
1109            edge.subdivide_n_times(subdivisions, &mut new_points);
1110            edge.done = false;
1111        }
1112
1113        for triangle in &mut *this.triangles {
1114            for i in 0..subdivisions {
1115                triangle.subdivide(&mut new_points, i);
1116            }
1117        }
1118
1119        let diff = new_points - this.points.len();
1120        this.points
1121            .extend(core::iter::repeat(Vec3A::ZERO).take(diff));
1122
1123        for triangle in &mut *this.triangles {
1124            triangle.calculate(&mut *this.shared_edges, &mut this.points, &this.shape);
1125        }
1126
1127        this.data = this.points.iter().copied().map(generator).collect();
1128
1129        this
1130    }
1131
1132    ///
1133    /// Increases the current subdivision count by `amount`.
1134    ///
1135    /// After calling this, you must call [`Self::calculate_values()`]
1136    /// to compute new vertex data.
1137    ///
1138    pub fn subdivide(&mut self, amount: usize) {
1139        let mut new_points = self.points.len();
1140
1141        let subdivision_level = self.shared_edges[0].points.len();
1142
1143        for edge in &mut *self.shared_edges {
1144            edge.subdivide_n_times(amount, &mut new_points);
1145            edge.done = false;
1146        }
1147
1148        for triangle in &mut *self.triangles {
1149            for _ in 0..amount {
1150                triangle.subdivide(&mut new_points, subdivision_level);
1151            }
1152        }
1153
1154        let diff = new_points - self.points.len();
1155        self.points
1156            .extend(core::iter::repeat(Vec3A::ZERO).take(diff));
1157    }
1158
1159    ///
1160    /// Recalculate data after [`Self::subdivide()`].
1161    ///
1162    pub fn calculate_values(&mut self, generator: impl FnMut(Vec3A) -> T) {
1163        for triangle in &mut *self.triangles {
1164            triangle.calculate(&mut *self.shared_edges, &mut self.points, &self.shape);
1165        }
1166
1167        self.data = self.points.iter().copied().map(generator).collect();
1168    }
1169
1170    ///
1171    /// The vertex positions created by the subdivision process.
1172    ///
1173    pub fn raw_points(&self) -> &[Vec3A] {
1174        &self.points
1175    }
1176
1177    ///
1178    /// Appends the indices for the subdivided form of the specified
1179    /// main triangle into `buffer`.
1180    ///
1181    /// The specified `triangle` is a main triangle on the base
1182    /// shape. The range of this should be limited to the number
1183    /// of triangles in the base shape.
1184    ///
1185    /// Alternatively, use [`Self::get_all_indices`] to get all the
1186    /// indices.
1187    ///
1188    /// Each element put into `buffer` is an index into [`Self::raw_data`]
1189    /// or [`Self::raw_points`] specifying the position of a triangle vertex.
1190    /// The first three elements specify the three vertices of a triangle
1191    /// to be drawn, and the next three elements specify another triangle,
1192    /// and so on.
1193    ///
1194    pub fn get_indices(&self, triangle: usize, buffer: &mut Vec<u32>) {
1195        self.triangles[triangle].add_indices(buffer, &self.shared_edges);
1196    }
1197
1198    ///
1199    /// Gets the indices for the triangles making up the subdivided shape.
1200    ///
1201    /// Each element of the returned [`Vec`] is an index into [`Self::raw_data`]
1202    /// or [`Self::raw_points`] specifying the position of a triangle vertex.
1203    /// The first three elements specify the three vertices of a triangle
1204    /// to be drawn, and the next three elements specify another triangle,
1205    /// and so on.
1206    ///
1207    /// Together, these triangles cover the entire surface of the shape.
1208    ///
1209    pub fn get_all_indices(&self) -> Vec<u32> {
1210        let mut buffer = Vec::new();
1211
1212        for i in 0..self.triangles.len() {
1213            self.get_indices(i, &mut buffer);
1214        }
1215
1216        buffer
1217    }
1218
1219    ///
1220    /// Appends indices for the wireframe of the subdivided form of
1221    /// the specified main triangle to `buffer`.
1222    ///
1223    /// This is equivalent to [`Self::get_all_line_indices`] except that it
1224    /// selects a single main triangle from the base shape. See its documentation
1225    /// for the format of the result, and how to use `delta` and `breaks`.
1226    ///
1227    pub fn get_line_indices(
1228        &self,
1229        buffer: &mut Vec<u32>,
1230        triangle: usize,
1231        delta: usize,
1232        breaks: impl FnMut(&mut Vec<u32>),
1233    ) {
1234        self.triangles[triangle].add_line_indices(buffer, &self.shared_edges, delta as u32, breaks);
1235    }
1236
1237    ///
1238    /// Appends indices for the wireframe of the subdivided form of
1239    /// the specified main triangle edge to `buffer`.
1240    ///
1241    /// The valid range of `edge` is `0..(S::EDGES)`.
1242    /// See [`Self::get_line_indices`] for more on `delta`.
1243    ///
1244    #[deprecated = "Flawed. Use `get_major_edges_line_indices()` instead."]
1245    pub fn get_major_edge_line_indices(&self, edge: usize, buffer: &mut Vec<u32>, delta: usize) {
1246        buffer.extend(
1247            self.shared_edges[edge]
1248                .points
1249                .iter()
1250                .map(|x| x + delta as u32),
1251        );
1252    }
1253
1254    ///
1255    /// Appends indices for the wireframe of the subdivided form of
1256    /// the base shape's main triangles' edges to `buffer`.
1257    ///
1258    /// Compared to [`Self::get_all_line_indices`], this does not return edges of any of the
1259    /// triangles which were created by subdivision — only edges of the original triangles.
1260    /// See that method's documentation for how to use `delta` and `breaks`.
1261    ///
1262    pub fn get_major_edges_line_indices(
1263        &self,
1264        buffer: &mut Vec<u32>,
1265        delta: u32,
1266        mut breaks: impl FnMut(&mut Vec<u32>),
1267    ) {
1268        for triangle in &*self.triangles {
1269            for (p1, p2, edge, forward) in [
1270                (
1271                    triangle.a,
1272                    triangle.b,
1273                    triangle.ab_edge,
1274                    triangle.ab_forward,
1275                ),
1276                (
1277                    triangle.b,
1278                    triangle.c,
1279                    triangle.bc_edge,
1280                    triangle.bc_forward,
1281                ),
1282                (
1283                    triangle.c,
1284                    triangle.a,
1285                    triangle.ca_edge,
1286                    triangle.ca_forward,
1287                ),
1288            ] {
1289                if !forward {
1290                    continue;
1291                }
1292
1293                buffer.push(p1 + delta);
1294                buffer.extend(self.shared_edges[edge].points.iter().map(|x| x + delta));
1295                buffer.push(p2 + delta);
1296
1297                breaks(buffer);
1298            }
1299        }
1300    }
1301
1302    ///
1303    /// Returns a vector of indices for the wireframe of the subdivided mesh.
1304    ///
1305    /// Each element in the returned [`Vec`] is an index into [`Self::raw_data`]
1306    /// or [`Self::raw_points`] specifying the position of a triangle vertex.
1307    /// The indices are formatted as "line strips"; that is, each vertex
1308    /// should be connected to the previous by a line, except where a break is
1309    /// specified.
1310    ///
1311    /// The `breaks` function is run every time there is a necessary break in
1312    /// the line strip. Use this to, for example, swap out the buffer using
1313    /// [`std::mem::take`], or push a special break-marking index into the buffer.
1314    ///
1315    /// `delta` is added to all of the indices pushed into the buffer, and
1316    /// is generally intended to be used together with `breaks` to allow a
1317    /// marker index at zero.
1318    /// This marker index might be used to refer to a vertex with position
1319    /// set to NaN, or parsed in some other way by the graphics API the indices
1320    /// are fed to.
1321    ///
1322    pub fn get_all_line_indices(
1323        &self,
1324        delta: usize,
1325        mut breaks: impl FnMut(&mut Vec<u32>),
1326    ) -> Vec<u32> {
1327        let mut buffer = Vec::new();
1328
1329        // Pushes all of the subdivision-created lines that are *not* part of `self.shared_edges`.
1330        for i in 0..self.triangles.len() {
1331            self.get_line_indices(&mut buffer, i, delta, &mut breaks);
1332            breaks(&mut buffer);
1333        }
1334
1335        let delta = delta as u32;
1336        self.get_major_edges_line_indices(&mut buffer, delta, &mut breaks);
1337
1338        buffer
1339    }
1340
1341    ///
1342    /// Returns the number of subdivisions applied when this shape
1343    /// was created.
1344    ///
1345    pub fn subdivisions(&self) -> usize {
1346        self.subdivisions
1347    }
1348
1349    ///
1350    /// Returns the custom data for each vertex created by the generator function.
1351    ///
1352    /// The length of this slice is equal to the number of vertices in the subdivided shape.
1353    ///
1354    pub fn raw_data(&self) -> &[T] {
1355        &self.data
1356    }
1357
1358    ///
1359    /// Returns mutable access to the custom data created by the generator function.
1360    ///
1361    /// The length of this slice is equal to the number of vertices in the subdivided shape.
1362    ///
1363    pub fn raw_data_mut(&mut self) -> &mut [T] {
1364        &mut self.data
1365    }
1366
1367    ///
1368    /// Calculate the number of indices which each main
1369    /// triangle will add to the vertex buffer.
1370    ///
1371    /// # Equation
1372    ///
1373    /// ```text
1374    /// (subdivisions + 1)²
1375    /// ```
1376    ///
1377    pub fn indices_per_main_triangle(&self) -> usize {
1378        (self.subdivisions + 1) * (self.subdivisions + 1)
1379    }
1380
1381    ///
1382    /// Calculate the number of vertices contained within
1383    /// each main triangle including the vertices which are
1384    /// shared with another main triangle.
1385    ///
1386    /// # Equation
1387    ///
1388    /// ```text
1389    /// (subdivisions + 1) * (subdivisions + 2) / 2
1390    /// ```
1391    ///
1392    pub fn vertices_per_main_triangle_shared(&self) -> usize {
1393        (self.subdivisions + 1) * (self.subdivisions + 2) / 2
1394    }
1395
1396    ///
1397    /// Calculate the number of vertices contained within each
1398    /// main triangle excluding the ones that are shared with
1399    /// other main triangles.
1400    ///
1401    /// # Equation
1402    ///
1403    /// ```text
1404    /// {
1405    /// { subdivisions < 2  : 0
1406    /// {
1407    /// { subdivisions >= 2 : (subdivisions - 1) * subdivisions / 2
1408    /// {
1409    /// ```
1410    ///
1411    pub fn vertices_per_main_triangle_unique(&self) -> usize {
1412        if self.subdivisions < 2 {
1413            return 0;
1414        }
1415        (self.subdivisions - 1) * self.subdivisions / 2
1416    }
1417
1418    ///
1419    /// Calculate the number of vertices along the edges
1420    /// of the main triangles and the vertices of the main
1421    /// triangles.
1422    ///
1423    /// # Equation
1424    ///
1425    /// ```text
1426    /// subdivisions * EDGES + INITIAL_POINTS
1427    /// ```
1428    ///
1429    pub fn shared_vertices(&self) -> usize {
1430        self.subdivisions * S::EDGES + self.shape.initial_points().len()
1431    }
1432
1433    ///
1434    /// Linear distance between two points on this shape.
1435    ///
1436    pub fn linear_distance(&self, p1: u32, p2: u32, radius: f32) -> f32 {
1437        (self.points[p1 as usize] - self.points[p2 as usize]).length() * radius
1438    }
1439}
1440
1441#[cfg(feature = "shape-extras")]
1442impl<T, S: BaseShape + EquilateralBaseShape> Subdivided<T, S> {
1443    ///
1444    /// Closest "main" triangle.
1445    ///
1446    /// Undefined results if the point is one of the vertices
1447    /// on the original base shape.
1448    ///
1449    pub fn main_triangle_intersect(point: Vec3A) -> usize {
1450        let point = point.normalize();
1451        let mut nearest = 0;
1452        let mut near_factor = point.dot(S::triangle_normals()[0]);
1453
1454        if near_factor > S::triangle_min_dot() {
1455            return 0;
1456        }
1457
1458        for (index, normal) in S::triangle_normals().iter().enumerate().skip(1) {
1459            let factor = normal.dot(point);
1460            if factor > near_factor {
1461                if factor > S::triangle_min_dot() {
1462                    return index;
1463                }
1464                nearest = index;
1465                near_factor = factor;
1466            }
1467        }
1468
1469        nearest
1470    }
1471
1472    ///
1473    /// Distance between two points on this sphere (assuming this
1474    /// is a sphere).
1475    ///
1476    pub fn spherical_distance(&self, p1: u32, p2: u32, radius: f32) -> f32 {
1477        self.points[p1 as usize]
1478            .dot(self.points[p2 as usize])
1479            .acos()
1480            * radius
1481    }
1482}
1483
1484///
1485/// Adds the indices of the triangles in this "layer" of the triangle to
1486/// the buffer.
1487///
1488// The logic in this function has been worked out mostly on pen and paper
1489// and therefore it is difficult to read.
1490fn add_indices_triangular(
1491    a: u32,
1492    b: u32,
1493    c: u32,
1494    ab: Slice<u32>,
1495    bc: Slice<u32>,
1496    ca: Slice<u32>,
1497    contents: &TriangleContents,
1498    buffer: &mut Vec<u32>,
1499) {
1500    let subdivisions = ab.len();
1501    if subdivisions == 0 {
1502        buffer.extend_from_slice(&[a, b, c]);
1503        return;
1504    } else if subdivisions == 1 {
1505        buffer.extend_from_slice(&[a, ab[0], ca[0]]);
1506        buffer.extend_from_slice(&[b, bc[0], ab[0]]);
1507        buffer.extend_from_slice(&[c, ca[0], bc[0]]);
1508        buffer.extend_from_slice(&[ab[0], bc[0], ca[0]]);
1509        return;
1510    } else if subdivisions == 2 {
1511        buffer.extend_from_slice(&[a, ab[0], ca[1]]);
1512        buffer.extend_from_slice(&[b, bc[0], ab[1]]);
1513        buffer.extend_from_slice(&[c, ca[0], bc[1]]);
1514
1515        buffer.extend_from_slice(&[ab[1], contents.idx_ab(0), ab[0]]);
1516        buffer.extend_from_slice(&[bc[1], contents.idx_ab(0), bc[0]]);
1517        buffer.extend_from_slice(&[ca[1], contents.idx_ab(0), ca[0]]);
1518
1519        buffer.extend_from_slice(&[ab[0], contents.idx_ab(0), ca[1]]);
1520        buffer.extend_from_slice(&[bc[0], contents.idx_ab(0), ab[1]]);
1521        buffer.extend_from_slice(&[ca[0], contents.idx_ab(0), bc[1]]);
1522        return;
1523    }
1524
1525    let last_idx = ab.len() - 1;
1526
1527    buffer.extend_from_slice(&[a, ab[0], ca[last_idx]]);
1528    buffer.extend_from_slice(&[b, bc[0], ab[last_idx]]);
1529    buffer.extend_from_slice(&[c, ca[0], bc[last_idx]]);
1530
1531    buffer.extend_from_slice(&[ab[0], contents.idx_ab(0), ca[last_idx]]);
1532    buffer.extend_from_slice(&[bc[0], contents.idx_bc(0), ab[last_idx]]);
1533    buffer.extend_from_slice(&[ca[0], contents.idx_ca(0), bc[last_idx]]);
1534
1535    for i in 0..last_idx - 1 {
1536        // Exclude special case: last_idx - 1.
1537        // AB
1538        buffer.extend_from_slice(&[ab[i], ab[i + 1], contents.idx_ab(i)]);
1539        buffer.extend_from_slice(&[ab[i + 1], contents.idx_ab(i + 1), contents.idx_ab(i)]);
1540        // BC
1541        buffer.extend_from_slice(&[bc[i], bc[i + 1], contents.idx_bc(i)]);
1542        buffer.extend_from_slice(&[bc[i + 1], contents.idx_bc(i + 1), contents.idx_bc(i)]);
1543        // CA
1544        buffer.extend_from_slice(&[ca[i], ca[i + 1], contents.idx_ca(i)]);
1545        buffer.extend_from_slice(&[ca[i + 1], contents.idx_ca(i + 1), contents.idx_ca(i)]);
1546    }
1547
1548    // Deal with special case: last_idx - 1
1549    buffer.extend_from_slice(&[
1550        ab[last_idx],
1551        contents.idx_ab(last_idx - 1),
1552        ab[last_idx - 1],
1553    ]);
1554
1555    buffer.extend_from_slice(&[
1556        bc[last_idx],
1557        contents.idx_bc(last_idx - 1),
1558        bc[last_idx - 1],
1559    ]);
1560
1561    buffer.extend_from_slice(&[
1562        ca[last_idx],
1563        contents.idx_ca(last_idx - 1),
1564        ca[last_idx - 1],
1565    ]);
1566}
1567
1568/// Adds the indices of the triangles in this "layer" of the triangle to
1569/// the buffer in line strip format.
1570///
1571/// Does the zig-zag between the current one and the contents,
1572/// and also the ring of the contents. (Since the outermost
1573/// ring is dealt with separately by `get_major_edge_line_indices`.
1574///
1575/// This is used to create a wireframe look.
1576///
1577// Like the previous function, this logic has been worked out mostly on
1578// pen and paper and it is therefore difficult to read.
1579fn add_line_indices_triangular(
1580    delta: u32,
1581    ab: Slice<u32>,
1582    bc: Slice<u32>,
1583    ca: Slice<u32>,
1584    contents: &TriangleContents,
1585    buffer: &mut Vec<u32>,
1586) {
1587    // if the number of points on our edge is zero, we have
1588    // no interior, and no zigzag
1589    if ab.len() == 0 {
1590        return;
1591    }
1592
1593    // if the number of points on our edge is one, there is no
1594    // interior, and there is only the zigzag
1595    if ab.len() == 1 {
1596        #[rustfmt::skip]
1597        buffer.extend_from_slice(&[
1598            ab[0] + delta,
1599            bc[0] + delta,
1600            ca[0] + delta,
1601            ab[0] + delta,
1602        ]);
1603        return;
1604    }
1605
1606    // if the number of points on our edge is two, then `contents`
1607    // is a single point and we get a three leaf clover
1608    if ab.len() == 2 {
1609        let inner = contents.idx_ab(0);
1610        buffer.extend_from_slice(&[
1611            inner + delta,
1612            ab[1] + delta,
1613            bc[0] + delta,
1614            inner + delta,
1615            bc[1] + delta,
1616            ca[0] + delta,
1617            inner + delta,
1618            ca[1] + delta,
1619            ab[0] + delta,
1620            inner + delta,
1621        ]);
1622        return;
1623    }
1624
1625    buffer.reserve((ab.len() - 1) * 9);
1626
1627    // Add the inner loop
1628    for i in 0..ab.len() - 2 {
1629        buffer.push(contents.idx_ab(i) + delta);
1630    }
1631
1632    for i in 0..bc.len() - 2 {
1633        buffer.push(contents.idx_bc(i) + delta);
1634    }
1635
1636    for i in 0..ca.len() - 2 {
1637        buffer.push(contents.idx_ca(i) + delta);
1638    }
1639
1640    // close the inner loop
1641    buffer.push(contents.idx_ab(0) + delta);
1642
1643    // do zigzag
1644    buffer.push(ab[0] + delta);
1645
1646    for i in (1..ca.len()).rev() {
1647        buffer.push(ca[i] + delta);
1648        buffer.push(contents.idx_ca(i - 1) + delta);
1649    }
1650
1651    buffer.push(ca[0] + delta);
1652
1653    for i in (1..bc.len()).rev() {
1654        buffer.push(bc[i] + delta);
1655        buffer.push(contents.idx_bc(i - 1) + delta);
1656    }
1657
1658    buffer.push(bc[0] + delta);
1659
1660    for i in (1..ab.len()).rev() {
1661        buffer.push(ab[i] + delta);
1662        buffer.push(contents.idx_ab(i - 1) + delta);
1663    }
1664
1665    buffer.push(ab[0] + delta);
1666}
1667
1668#[cfg(feature = "adjacency")]
1669///
1670/// Implements neighbour tracking.
1671///
1672mod adjacency {
1673    use alloc::vec::Vec;
1674    use tinyvec::ArrayVec;
1675
1676    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1677    pub(crate) enum RehexState {
1678        Empty,
1679        Clear,
1680        TwoTwo,
1681        ThreeTwo,
1682        TwoTwoTwo,
1683        Complete,
1684    }
1685
1686    /// Tracks the neighbours adjacent to each vertex by only using index data.
1687    ///
1688    /// The result preserves winding: the resulting array is wound around the
1689    /// center vertex in the same way that the source triangles were wound.
1690    pub struct AdjacencyBuilder {
1691        pub(crate) state: Vec<RehexState>,
1692        pub result: Vec<ArrayVec<[usize; 6]>>,
1693    }
1694
1695    impl AdjacencyBuilder {
1696        pub fn new(points_len: usize) -> Self {
1697            let state = core::iter::repeat(RehexState::Empty)
1698                .take(points_len)
1699                .collect::<Vec<_>>();
1700            let result = core::iter::repeat(ArrayVec::new())
1701                .take(points_len)
1702                .collect::<Vec<_>>();
1703            Self { state, result }
1704        }
1705
1706        pub fn add_indices(&mut self, indices: &[u32]) {
1707            for chunk in indices.chunks_exact(3) {
1708                let &[a, b, c] = chunk else { unreachable!() };
1709
1710                self.add_triangle(a, b, c);
1711                self.add_triangle(c, a, b);
1712                self.add_triangle(b, c, a);
1713            }
1714        }
1715
1716        pub fn finish(self) -> Vec<ArrayVec<[usize; 6]>> {
1717            self.result
1718        }
1719
1720        fn add_triangle(&mut self, a: u32, b: u32, c: u32) {
1721            let (a, b, c) = (a as usize, b as usize, c as usize);
1722            let state = &mut self.state[a];
1723            if let RehexState::Complete = state {
1724                return;
1725            }
1726
1727            let result = &mut self.result[a];
1728
1729            match state {
1730                RehexState::Empty => {
1731                    result.extend([b, c]);
1732                    *state = RehexState::Clear;
1733                }
1734                RehexState::Clear => {
1735                    if result[result.len() - 1] == b {
1736                        if result[0] == c {
1737                            *state = RehexState::Complete;
1738                        } else {
1739                            result.push(c);
1740                            if result.len() == 6 {
1741                                *state = RehexState::Complete;
1742                            }
1743                        }
1744                    } else if result[0] == c {
1745                        result.insert(0, b);
1746                        if result.len() == 6 {
1747                            *state = RehexState::Complete;
1748                        }
1749                    } else {
1750                        *state = match result.len() {
1751                            2 => RehexState::TwoTwo,
1752                            3 => RehexState::ThreeTwo,
1753                            4 => RehexState::Complete,
1754                            _ => unreachable!(),
1755                        };
1756                        result.extend([b, c]);
1757                    }
1758                }
1759                RehexState::TwoTwo => {
1760                    if result[1] == b {
1761                        if result[2] == c {
1762                            *state = RehexState::Clear;
1763                        } else {
1764                            result.insert(2, c);
1765                            *state = RehexState::ThreeTwo;
1766                        }
1767                    } else if result[0] == c {
1768                        if result[3] == b {
1769                            let temp = result[2];
1770                            result.pop();
1771                            result.pop();
1772                            result.insert(0, temp);
1773                            result.insert(1, b);
1774                            *state = RehexState::Clear;
1775                        } else {
1776                            result.insert(0, b);
1777                            *state = RehexState::ThreeTwo;
1778                        }
1779                    } else if result[2] == c {
1780                        result.insert(0, b);
1781                        let t2 = result.swap_remove(2);
1782                        let t1 = result.swap_remove(1);
1783                        result.push(t1);
1784                        result.push(t2);
1785                        *state = RehexState::ThreeTwo;
1786                    } else {
1787                        result.extend([b, c]);
1788                        *state = RehexState::TwoTwoTwo;
1789                    }
1790                }
1791                RehexState::ThreeTwo => {
1792                    if result[2] == b {
1793                        if result[3] == c {
1794                            *state = RehexState::Clear;
1795                        } else {
1796                            result.insert(3, c);
1797                            *state = RehexState::Complete;
1798                        }
1799                    } else {
1800                        if result[4] == b {
1801                            result.pop();
1802                            let temp = result.pop().unwrap();
1803                            result.insert(0, b);
1804                            result.insert(0, temp);
1805                            *state = RehexState::Clear;
1806                        } else {
1807                            result.insert(0, b);
1808                            *state = RehexState::Complete;
1809                        }
1810                    }
1811                }
1812                RehexState::TwoTwoTwo => {
1813                    if (result[1] != b || result[2] != c)
1814                        && (result[3] != b || result[4] != c)
1815                        && (result[5] != b || result[0] != c)
1816                    {
1817                        let t2 = result.swap_remove(3);
1818                        let t1 = result.swap_remove(2);
1819                        result.extend([t1, t2]);
1820                    }
1821                    *state = RehexState::Complete;
1822                }
1823                RehexState::Complete => unreachable!(),
1824            }
1825        }
1826    }
1827}
1828
1829#[cfg(test)]
1830mod tests {
1831    use crate::shapes::{IcoSphere, SquarePlane};
1832    use crate::Slice::Forward;
1833    use alloc::vec::Vec;
1834    use glam::Vec3A;
1835
1836    // Starting points aren't _quite_ precise enough to use `f32::EPSILON`.
1837    const EPSILON: f32 = 0.0000002;
1838
1839    #[test]
1840    fn slerp_one() {
1841        use crate::interpolation::geometric_slerp_half;
1842        let p1 = Vec3A::new(0.360492952832, 0.932761936915, 0.0);
1843        let p2 = Vec3A::new(0.975897449331, 0.218229623081, 0.0);
1844
1845        let expected = Vec3A::new(0.757709663147, 0.652591806854, 0.0);
1846
1847        let result = geometric_slerp_half(p1, p2);
1848
1849        assert!((expected - result).length() <= EPSILON);
1850
1851        // Another test case
1852        let p1 = Vec3A::new(-0.24953852315, 0.0, 0.968364872073);
1853        let p2 = Vec3A::new(-0.948416666565, 0.0, 0.317026539239);
1854
1855        let expected = Vec3A::new(-0.681787771301, 0.0, 0.731550022148);
1856
1857        let result = geometric_slerp_half(p1, p2);
1858
1859        assert!((expected - result).length() <= EPSILON);
1860    }
1861
1862    #[test]
1863    fn slerp_many() {
1864        use crate::interpolation::geometric_slerp_multiple;
1865
1866        let p1 = Vec3A::new(0.0, -0.885330189449, 0.464962854054);
1867        let p2 = Vec3A::new(0.0, 0.946042343528, 0.324043028395);
1868
1869        let expected = Vec3A::new(0.0, 0.0767208624118, 0.997052611085);
1870
1871        let mut result = Vec3A::ZERO;
1872        geometric_slerp_multiple(p1, p2, &[0], core::slice::from_mut(&mut result));
1873
1874        assert!((expected - result).length() <= EPSILON);
1875
1876        let p1 = Vec3A::new(0.876621956288, 0.0, 0.481179743707);
1877        let p2 = Vec3A::new(-0.391617625614, 0.0, -0.920128053756);
1878
1879        let expected = [
1880            Vec3A::new(0.999975758841, 0.0, 0.00696288230076),
1881            Vec3A::new(0.883237589397, 0.0, -0.468925751774),
1882            Vec3A::new(0.554436024709, 0.0, -0.83222634812),
1883            Vec3A::new(0.0925155945469, 0.0, -0.995711235633),
1884        ];
1885
1886        let mut result = [Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO];
1887
1888        geometric_slerp_multiple(p1, p2, &[0, 1, 2, 3], &mut result);
1889
1890        for (&expected, &result) in expected.iter().zip(result.iter()) {
1891            assert!((expected - result).length() <= EPSILON);
1892        }
1893    }
1894
1895    #[test]
1896    fn new() {
1897        let x = IcoSphere::new(0, |_| ());
1898        x.get_indices(0, &mut Vec::new());
1899    }
1900
1901    #[test]
1902    fn clone() {
1903        let _x = IcoSphere::new(6, |_| ()).clone();
1904    }
1905
1906    #[test]
1907    fn one() {
1908        let x = IcoSphere::new(1, |_| ());
1909        x.get_indices(0, &mut Vec::new());
1910    }
1911
1912    #[test]
1913    fn second_layer_inner() {
1914        let x = IcoSphere::new(2, |_| ());
1915        x.get_indices(0, &mut Vec::new());
1916        let x = IcoSphere::new(3, |_| ());
1917        x.get_indices(0, &mut Vec::new());
1918        let x = IcoSphere::new(5, |_| ());
1919        x.get_indices(0, &mut Vec::new());
1920        let x = IcoSphere::new(6, |_| ());
1921        x.get_indices(0, &mut Vec::new());
1922    }
1923
1924    #[test]
1925    fn indices_zero() {
1926        use super::add_indices_triangular;
1927        use super::TriangleContents;
1928
1929        let mut buffer = Vec::new();
1930
1931        add_indices_triangular(
1932            0,
1933            1,
1934            2,
1935            Forward(&[]),
1936            Forward(&[]),
1937            Forward(&[]),
1938            &TriangleContents::none(),
1939            &mut buffer,
1940        );
1941
1942        assert_eq!(buffer, &[0, 1, 2]);
1943    }
1944
1945    #[test]
1946    fn indices_one() {
1947        use super::add_indices_triangular;
1948        use super::TriangleContents;
1949
1950        let mut buffer = Vec::new();
1951
1952        add_indices_triangular(
1953            0,
1954            1,
1955            2,
1956            Forward(&[3]),
1957            Forward(&[4]),
1958            Forward(&[5]),
1959            &TriangleContents::none(),
1960            &mut buffer,
1961        );
1962
1963        assert_eq!(buffer, &[0, 3, 5, 1, 4, 3, 2, 5, 4, 3, 4, 5,]);
1964    }
1965
1966    #[test]
1967    fn indices_two() {
1968        use super::add_indices_triangular;
1969        use super::TriangleContents;
1970
1971        let mut buffer = Vec::new();
1972
1973        add_indices_triangular(
1974            0,
1975            3,
1976            6,
1977            Forward(&[1, 2]),
1978            Forward(&[4, 5]),
1979            Forward(&[7, 8]),
1980            &TriangleContents::One(9),
1981            &mut buffer,
1982        );
1983
1984        assert_eq!(
1985            buffer,
1986            &[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,]
1987        );
1988    }
1989
1990    // Really, we're testing for the rest.
1991    #[test]
1992    fn indices_three() {
1993        use super::add_indices_triangular;
1994        use super::TriangleContents;
1995
1996        let mut buffer = Vec::new();
1997
1998        add_indices_triangular(
1999            0,
2000            4,
2001            8,
2002            Forward(&[1, 2, 3]),
2003            Forward(&[5, 6, 7]),
2004            Forward(&[9, 10, 11]),
2005            &TriangleContents::Three {
2006                a: 12,
2007                b: 13,
2008                c: 14,
2009            },
2010            &mut buffer,
2011        );
2012
2013        assert_eq!(
2014            buffer,
2015            &[
2016                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,
2017                6, 13, 6, 14, 13, 9, 10, 14, 10, 12, 14, 3, 13, 2, 7, 14, 6, 11, 12, 10,
2018            ][..]
2019        );
2020    }
2021
2022    #[test]
2023    fn precision() {
2024        let sphere = IcoSphere::new(10, |_| ());
2025
2026        for i in sphere.raw_points() {
2027            assert!(i.length() - 1.0 <= EPSILON);
2028        }
2029    }
2030
2031    #[test]
2032    fn line_one() {
2033        use super::add_line_indices_triangular;
2034        use super::TriangleContents;
2035
2036        let mut buffer = Vec::new();
2037
2038        add_line_indices_triangular(
2039            0,
2040            Forward(&[0]),
2041            Forward(&[1]),
2042            Forward(&[2]),
2043            &TriangleContents::none(),
2044            &mut buffer,
2045        );
2046
2047        assert_eq!(buffer, &[0, 1, 2, 0]);
2048    }
2049
2050    #[test]
2051    fn line_two() {
2052        use super::add_line_indices_triangular;
2053        use super::TriangleContents;
2054
2055        let mut buffer = Vec::new();
2056
2057        add_line_indices_triangular(
2058            0,
2059            Forward(&[0, 1]),
2060            Forward(&[2, 3]),
2061            Forward(&[4, 5]),
2062            &TriangleContents::One(6),
2063            &mut buffer,
2064        );
2065
2066        assert_eq!(buffer, &[6, 1, 2, 6, 3, 4, 6, 5, 0, 6]);
2067    }
2068
2069    #[test]
2070    fn line_three() {
2071        use super::add_line_indices_triangular;
2072        use super::TriangleContents;
2073
2074        let mut buffer = Vec::new();
2075
2076        add_line_indices_triangular(
2077            0,
2078            Forward(&[0, 1, 2]),
2079            Forward(&[3, 4, 5]),
2080            Forward(&[6, 7, 8]),
2081            &TriangleContents::Three { a: 9, b: 10, c: 11 },
2082            &mut buffer,
2083        );
2084
2085        assert_eq!(
2086            buffer,
2087            &[9, 10, 11, 9, 0, 8, 9, 7, 11, 6, 5, 11, 4, 10, 3, 2, 10, 1, 9, 0]
2088        );
2089    }
2090
2091    #[test]
2092    fn getting_major_edges() {
2093        // Use the square shape because it has few and simple vertices.
2094        let square = SquarePlane::new(1, |_| ());
2095
2096        let mut buffer = Vec::new();
2097        square.get_major_edges_line_indices(&mut buffer, 1, |v| v.push(0));
2098
2099        assert_eq!(
2100            buffer,
2101            vec![
2102                // Note: this is a list of five edges because the square is two triangles,
2103                // so there is a diagonal edge which counts as a major edge.
2104                // Each one has 2 original vertices and 1 interpolated vertex.
2105                1, 6, 2, 0, //
2106                2, 7, 3, 0, //
2107                3, 5, 1, 0, //
2108                3, 8, 4, 0, //
2109                4, 9, 1, 0, //
2110            ]
2111        );
2112    }
2113
2114    #[cfg(feature = "adjacency")]
2115    mod adjacency {
2116        use alloc::vec::Vec;
2117
2118        use crate::adjacency::RehexState;
2119        use crate::{adjacency::AdjacencyBuilder, shapes::IcoSphere};
2120
2121        #[test]
2122        fn creation() {
2123            let sphere = IcoSphere::new(5, |_| ());
2124
2125            let mut indices = Vec::new();
2126
2127            for i in 0..20 {
2128                sphere.get_indices(i, &mut indices);
2129            }
2130
2131            let mut builder = AdjacencyBuilder::new(sphere.raw_points().len());
2132            builder.add_indices(&indices);
2133            builder
2134                .state
2135                .iter()
2136                .for_each(|&state| assert_eq!(state, RehexState::Complete));
2137        }
2138    }
2139}