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