hexasphere/
shapes.rs

1#[cfg(feature = "shape-extras")]
2use super::EquilateralBaseShape;
3use super::{interpolation, BaseShape, Subdivided, Triangle};
4use alloc::{boxed::Box, vec::Vec};
5use glam::Vec3A;
6
7///
8/// Implements an icosahedron as the base shape.
9///
10/// - 12 vertices
11/// - 20 faces
12/// - 30 edges
13///
14/// This shape has the best results for a sphere.
15///
16/// The resulting smaller triangles are close to being
17/// equilateral, so if one draws lines from the center
18/// of the each triangle to the middle of the each edge
19/// then the result will be 12 pentagons and many hexagons.
20///
21#[derive(Default, Copy, Clone, Debug)]
22pub struct IcoSphereBase;
23
24impl BaseShape for IcoSphereBase {
25    #[inline]
26    fn initial_points(&self) -> Vec<Vec3A> {
27        consts::icosphere::INITIAL_POINTS.to_vec()
28    }
29
30    #[inline]
31    fn triangles(&self) -> Box<[Triangle]> {
32        Box::new(consts::icosphere::TRIANGLES)
33    }
34    const EDGES: usize = consts::icosphere::EDGES;
35
36    #[inline]
37    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
38        interpolation::geometric_slerp(a, b, p)
39    }
40
41    #[inline]
42    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
43        interpolation::geometric_slerp_half(a, b)
44    }
45
46    #[inline]
47    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
48        interpolation::geometric_slerp_multiple(a, b, indices, points);
49    }
50}
51
52#[cfg(feature = "shape-extras")]
53impl EquilateralBaseShape for IcoSphereBase {
54    #[inline]
55    fn triangle_normals() -> &'static [Vec3A] {
56        &consts::icosphere::TRIANGLE_NORMALS
57    }
58
59    #[inline]
60    fn triangle_min_dot() -> f32 {
61        consts::icosphere::MIN_NORMAL_DOT
62    }
63}
64
65///
66/// Icosphere.
67///
68/// See [`IcoSphereBase`].
69///
70pub type IcoSphere<T> = Subdivided<T, IcoSphereBase>;
71
72impl<T> IcoSphere<T> {
73    ///
74    /// Calculate distance from the center of a shape (pentagon or hexagon)
75    /// to one of the vertices of the shape.
76    ///
77    /// In other words, the radius of the circumscribed circle.
78    ///
79    pub fn radius_shapes(&self) -> f32 {
80        let subdivisions = self.subdivisions as f32 + 1.0;
81        const DEFAULT_ANGLE: f32 = 1.10714871779409085306;
82        let angle = DEFAULT_ANGLE / subdivisions;
83        crate::math::sin(angle * 0.5) * 2.0
84    }
85}
86
87///
88/// Implements the same shape as [`IcoSphereBase`], however
89/// it uses normalized linear interpolation, rather than
90/// geometric spherical linear interpolation. (`nlerp` over `slerp`).
91///
92#[derive(Default, Copy, Clone, Debug)]
93pub struct NormIcoSphereBase;
94
95impl BaseShape for NormIcoSphereBase {
96    #[inline]
97    fn initial_points(&self) -> Vec<Vec3A> {
98        consts::icosphere::INITIAL_POINTS.to_vec()
99    }
100
101    #[inline]
102    fn triangles(&self) -> Box<[Triangle]> {
103        Box::new(consts::icosphere::TRIANGLES)
104    }
105    const EDGES: usize = consts::icosphere::EDGES;
106
107    #[inline]
108    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
109        interpolation::normalized_lerp(a, b, p)
110    }
111
112    #[inline]
113    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
114        interpolation::normalized_lerp_half(a, b)
115    }
116
117    #[inline]
118    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
119        interpolation::normalized_lerp_multiple(a, b, indices, points);
120    }
121}
122
123#[cfg(feature = "shape-extras")]
124impl EquilateralBaseShape for NormIcoSphereBase {
125    #[inline]
126    fn triangle_normals() -> &'static [Vec3A] {
127        &consts::icosphere::TRIANGLE_NORMALS
128    }
129
130    #[inline]
131    fn triangle_min_dot() -> f32 {
132        consts::icosphere::MIN_NORMAL_DOT
133    }
134}
135
136///
137/// Normalized Icosphere.
138///
139/// See [`NormIcoSphereBase`].
140///
141pub type NormIcoSphere<T> = Subdivided<T, NormIcoSphereBase>;
142
143///
144/// Implements a tetrahedron as the base shape.
145///
146/// - 4 vertices
147/// - 4 faces
148/// - 6 edges
149///
150/// This shape provides somewhat skewed results for a
151/// sphere, especially at lower subdivisions.
152/// I recommend that subdivisions of higher than 10
153/// be used for acceptable results.
154///
155#[derive(Default, Copy, Clone, Debug)]
156pub struct TetraSphereBase;
157
158impl BaseShape for TetraSphereBase {
159    #[inline]
160    fn initial_points(&self) -> Vec<Vec3A> {
161        consts::tetrasphere::INITIAL_POINTS.to_vec()
162    }
163
164    #[inline]
165    fn triangles(&self) -> Box<[Triangle]> {
166        Box::new(consts::tetrasphere::TRIANGLES)
167    }
168    const EDGES: usize = consts::tetrasphere::EDGES;
169
170    #[inline]
171    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
172        interpolation::geometric_slerp(a, b, p)
173    }
174
175    #[inline]
176    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
177        interpolation::geometric_slerp_half(a, b)
178    }
179
180    #[inline]
181    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
182        interpolation::geometric_slerp_multiple(a, b, indices, points);
183    }
184}
185
186#[cfg(feature = "shape-extras")]
187impl EquilateralBaseShape for TetraSphereBase {
188    #[inline]
189    fn triangle_normals() -> &'static [Vec3A] {
190        &consts::tetrasphere::TRIANGLE_NORMALS
191    }
192
193    #[inline]
194    fn triangle_min_dot() -> f32 {
195        consts::tetrasphere::MIN_NORMAL_DOT
196    }
197}
198
199///
200/// Tetrasphere (Sphere from tetrahedron).
201///
202/// See [`TetraSphereBase`].
203///
204pub type TetraSphere<T> = Subdivided<T, TetraSphereBase>;
205
206///
207/// Implements a single triangle as the base shape.
208///
209/// - 3 vertices
210/// - 1 face
211/// - 3 edges
212///
213/// This is a triangle on the XZ plane. The circumscribed
214/// circle on the triangle has radius 1.0.
215///
216#[derive(Default, Copy, Clone, Debug)]
217pub struct TriangleBase;
218
219impl BaseShape for TriangleBase {
220    #[inline]
221    fn initial_points(&self) -> Vec<Vec3A> {
222        consts::triangle::INITIAL_POINTS.to_vec()
223    }
224
225    #[inline]
226    fn triangles(&self) -> Box<[Triangle]> {
227        core::slice::from_ref(&consts::triangle::TRIANGLE)
228            .to_vec()
229            .into()
230    }
231    const EDGES: usize = consts::triangle::EDGES;
232
233    #[inline]
234    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
235        interpolation::lerp(a, b, p)
236    }
237
238    #[inline]
239    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
240        interpolation::lerp_half(a, b)
241    }
242
243    #[inline]
244    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
245        interpolation::lerp_multiple(a, b, indices, points);
246    }
247}
248
249#[cfg(feature = "shape-extras")]
250impl EquilateralBaseShape for TriangleBase {
251    #[inline]
252    fn triangle_normals() -> &'static [Vec3A] {
253        core::slice::from_ref(&consts::triangle::TRIANGLE_NORMAL)
254    }
255
256    #[inline]
257    fn triangle_min_dot() -> f32 {
258        -1.0
259    }
260}
261
262///
263/// A triangle.
264///
265/// See [`TriangleBase`].
266///
267pub type TrianglePlane<T> = Subdivided<T, TriangleBase>;
268
269///
270/// Implements a square as the base shape.
271///
272/// - 4 vertices
273/// - 2 faces
274/// - 5 edges
275///
276/// This is a square on the XZ plane.
277///
278#[derive(Default, Copy, Clone, Debug)]
279pub struct SquareBase;
280
281impl BaseShape for SquareBase {
282    #[inline]
283    fn initial_points(&self) -> Vec<Vec3A> {
284        consts::square::INITIAL_POINTS.to_vec()
285    }
286
287    #[inline]
288    fn triangles(&self) -> Box<[Triangle]> {
289        consts::square::TRIANGLES.to_vec().into()
290    }
291    const EDGES: usize = consts::square::EDGES;
292
293    #[inline]
294    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
295        interpolation::lerp(a, b, p)
296    }
297
298    #[inline]
299    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
300        interpolation::lerp_half(a, b)
301    }
302
303    #[inline]
304    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
305        interpolation::lerp_multiple(a, b, indices, points);
306    }
307}
308
309///
310/// A square.
311///
312/// See [`SquareBase`].
313///
314pub type SquarePlane<T> = Subdivided<T, SquareBase>;
315
316///
317/// Implements a cube as the base shape.
318///
319/// - 8 vertices
320/// - 12 faces (2 triangles per face makes 12 technically)
321/// - 18 edges
322///
323/// This is a cube where half the diagonal is 1.0. This is to
324/// enable this to be used in making a sphere.
325///
326#[derive(Default, Copy, Clone, Debug)]
327pub struct CubeBase;
328
329impl BaseShape for CubeBase {
330    #[inline]
331    fn initial_points(&self) -> Vec<Vec3A> {
332        consts::cube::INITIAL_POINTS.to_vec()
333    }
334
335    #[inline]
336    fn triangles(&self) -> Box<[Triangle]> {
337        consts::cube::TRIANGLES.to_vec().into()
338    }
339    const EDGES: usize = consts::cube::EDGES;
340
341    #[inline]
342    fn interpolate(&self, a: Vec3A, b: Vec3A, p: f32) -> Vec3A {
343        interpolation::geometric_slerp(a, b, p)
344    }
345
346    #[inline]
347    fn interpolate_half(&self, a: Vec3A, b: Vec3A) -> Vec3A {
348        interpolation::geometric_slerp_half(a, b)
349    }
350
351    #[inline]
352    fn interpolate_multiple(&self, a: Vec3A, b: Vec3A, indices: &[u32], points: &mut [Vec3A]) {
353        interpolation::geometric_slerp_multiple(a, b, indices, points);
354    }
355}
356
357///
358/// A cube sphere.
359///
360/// See [`CubeBase`].
361///
362pub type CubeSphere<T> = Subdivided<T, CubeBase>;
363
364///
365/// Constant values for the shapes provided by this library.
366///
367mod consts {
368    pub mod square {
369        use crate::{Triangle, TriangleContents};
370        use glam::Vec3A;
371
372        #[rustfmt::skip]
373        pub(crate) const INITIAL_POINTS: [Vec3A; 4] = [
374            Vec3A::new( 1.0, 0.0,  1.0),
375            Vec3A::new( 1.0, 0.0, -1.0),
376            Vec3A::new(-1.0, 0.0, -1.0),
377            Vec3A::new(-1.0, 0.0,  1.0),
378        ];
379
380        pub const TRIANGLES: [Triangle; 2] = [
381            Triangle {
382                a: 0,
383                b: 1,
384                c: 2,
385
386                ab_edge: 1,
387                bc_edge: 2,
388                ca_edge: 0,
389                ab_forward: true,
390                bc_forward: true,
391                ca_forward: true,
392                contents: TriangleContents::None,
393            },
394            Triangle {
395                a: 0,
396                b: 2,
397                c: 3,
398
399                ab_edge: 0,
400                bc_edge: 3,
401                ca_edge: 4,
402                ab_forward: true,
403                bc_forward: true,
404                ca_forward: true,
405                contents: TriangleContents::None,
406            },
407        ];
408
409        pub const EDGES: usize = 5;
410    }
411    pub mod triangle {
412        use crate::{Triangle, TriangleContents};
413        use constgebra::const_soft_float::soft_f32::SoftF32;
414        use glam::Vec3A;
415
416        pub(crate) static INITIAL_POINTS: [Vec3A; 3] = [
417            Vec3A::new(
418                -SoftF32(3.0f32).sqrt().div(SoftF32(2.0)).to_f32(),
419                0.0,
420                -0.5,
421            ),
422            Vec3A::new(SoftF32(3.0f32).sqrt().div(SoftF32(2.0)).to_f32(), 0.0, -0.5),
423            Vec3A::new(0.0, 0.0, 1.0),
424        ];
425
426        #[cfg(feature = "shape-extras")]
427        pub(crate) const TRIANGLE_NORMAL: Vec3A = Vec3A::Y;
428
429        pub const TRIANGLE: Triangle = Triangle {
430            a: 2,
431            b: 1,
432            c: 0,
433
434            ab_edge: 0,
435            bc_edge: 1,
436            ca_edge: 2,
437            ab_forward: true,
438            bc_forward: true,
439            ca_forward: true,
440            contents: TriangleContents::None,
441        };
442
443        pub const EDGES: usize = 3;
444    }
445    pub mod tetrasphere {
446        use crate::{Triangle, TriangleContents};
447        use constgebra::const_soft_float::soft_f32::SoftF32;
448        #[cfg(feature = "shape-extras")]
449        use constgebra::{const_soft_float::soft_f64::SoftF64, CVector, Operation};
450        use glam::Vec3A;
451
452        pub const TRIANGLES: [Triangle; 4] = [
453            Triangle {
454                a: 0,
455                b: 1,
456                c: 2,
457
458                ab_edge: 0,
459                bc_edge: 1,
460                ca_edge: 2,
461                ab_forward: false,
462                bc_forward: false,
463                ca_forward: false,
464                contents: TriangleContents::None,
465            },
466            Triangle {
467                a: 0,
468                b: 3,
469                c: 1,
470
471                ab_edge: 3,
472                bc_edge: 4,
473                ca_edge: 0,
474                ab_forward: false,
475                bc_forward: false,
476                ca_forward: false,
477                contents: TriangleContents::None,
478            },
479            Triangle {
480                a: 1,
481                b: 3,
482                c: 2,
483
484                ab_edge: 4,
485                bc_edge: 5,
486                ca_edge: 1,
487                ab_forward: false,
488                bc_forward: false,
489                ca_forward: false,
490                contents: TriangleContents::None,
491            },
492            Triangle {
493                a: 0,
494                b: 2,
495                c: 3,
496
497                ab_edge: 2,
498                bc_edge: 5,
499                ca_edge: 3,
500                ab_forward: false,
501                bc_forward: false,
502                ca_forward: false,
503                contents: TriangleContents::None,
504            },
505        ];
506        pub const EDGES: usize = 6;
507
508        #[cfg(feature = "shape-extras")]
509        pub(super) const fn normal<const I: usize>(
510            triangles: &[Triangle],
511            initial_points: &[Vec3A],
512        ) -> Vec3A {
513            const fn f32_arr_to_f64<const N: usize>(arr: [f32; N]) -> [f64; N] {
514                let mut ret = [0.0_f64; N];
515                let mut i = 0;
516                while i < N {
517                    ret[i] = arr[i] as f64;
518                    i += 1;
519                }
520                ret
521            }
522            const fn f64_arr_to_f32<const N: usize>(arr: [f64; N]) -> [f32; N] {
523                let mut ret = [0.0_f32; N];
524                let mut i = 0;
525                while i < N {
526                    ret[i] = arr[i] as f32;
527                    i += 1;
528                }
529                ret
530            }
531
532            let triangle = &triangles[I];
533
534            let p1 = CVector::new_vector(f32_arr_to_f64(
535                initial_points[triangle.a as usize].to_array(),
536            ));
537            let p2 = CVector::new_vector(f32_arr_to_f64(
538                initial_points[triangle.b as usize].to_array(),
539            ));
540            let p3 = CVector::new_vector(f32_arr_to_f64(
541                initial_points[triangle.c as usize].to_array(),
542            ));
543
544            let normal = p1.add(p2).add(p3);
545            let len = {
546                let [x, y, z] = normal.finish_vector();
547                let x = SoftF64(x);
548                let y = SoftF64(y);
549                let z = SoftF64(z);
550
551                x.mul(x).add(y.mul(y)).add(z.mul(z)).sqrt()
552            };
553            let normal = normal.apply_each(Operation::Div(len.0));
554
555            return Vec3A::from_array(f64_arr_to_f32(normal.finish_vector()));
556        }
557
558        pub(crate) const INITIAL_POINTS: [Vec3A; 4] = [
559            Vec3A::new(
560                SoftF32(8.0f32).sqrt().div(SoftF32(3.0)).to_f32(),
561                SoftF32(-1.0).div(SoftF32(3.0)).to_f32(),
562                0.0,
563            ),
564            Vec3A::new(
565                -SoftF32(2.0f32).sqrt().div(SoftF32(3.0)).to_f32(),
566                SoftF32(-1.0).div(SoftF32(3.0)).to_f32(),
567                SoftF32(2.0f32).div(SoftF32(3.0)).sqrt().to_f32(),
568            ),
569            Vec3A::new(
570                -SoftF32(2.0f32).sqrt().div(SoftF32(3.0)).to_f32(),
571                SoftF32(-1.0).div(SoftF32(3.0)).to_f32(),
572                SoftF32(2.0f32).div(SoftF32(3.0)).sqrt().neg().to_f32(),
573            ),
574            Vec3A::new(0.0, 1.0, 0.0),
575        ];
576
577        #[cfg(feature = "shape-extras")]
578        pub(crate) const MIN_NORMAL_DOT: f32 = SoftF32(7.0f32).sqrt().div(SoftF32(3.0)).to_f32();
579
580        #[cfg(feature = "shape-extras")]
581        pub(crate) const TRIANGLE_NORMALS: [Vec3A; 4] = [
582            normal::<0>(&TRIANGLES, &INITIAL_POINTS),
583            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
584            normal::<2>(&TRIANGLES, &INITIAL_POINTS),
585            normal::<3>(&TRIANGLES, &INITIAL_POINTS),
586        ];
587    }
588    pub mod cube {
589        use crate::{Triangle, TriangleContents};
590        use constgebra::const_soft_float::soft_f32::SoftF32;
591        use glam::Vec3A;
592
593        #[rustfmt::skip]
594        pub(crate) static INITIAL_POINTS: [Vec3A; 8] = {
595            let val = SoftF32(1.0).div(SoftF32(3.0f32).sqrt()).to_f32();
596            [
597                Vec3A::new(-val, -val, -val),
598                Vec3A::new( val, -val, -val),
599                Vec3A::new(-val,  val, -val),
600                Vec3A::new( val,  val, -val),
601
602                Vec3A::new(-val, -val,  val),
603                Vec3A::new( val, -val,  val),
604                Vec3A::new(-val,  val,  val),
605                Vec3A::new( val,  val,  val),
606            ]
607        };
608
609        pub const TRIANGLES: &[Triangle; 12] = &[
610            // Back
611            Triangle {
612                a: 0,
613                b: 2,
614                c: 3,
615
616                ab_edge: 1,
617                bc_edge: 2,
618                ca_edge: 12,
619                ab_forward: false,
620                bc_forward: false,
621                ca_forward: false,
622                contents: TriangleContents::None,
623            },
624            Triangle {
625                a: 0,
626                b: 3,
627                c: 1,
628
629                ab_edge: 12,
630                bc_edge: 3,
631                ca_edge: 0,
632                ab_forward: false,
633                bc_forward: false,
634                ca_forward: false,
635                contents: TriangleContents::None,
636            },
637            // Top
638            Triangle {
639                a: 2,
640                b: 7,
641                c: 3,
642
643                ab_edge: 14,
644                bc_edge: 6,
645                ca_edge: 2,
646                ab_forward: false,
647                bc_forward: false,
648                ca_forward: false,
649                contents: TriangleContents::None,
650            },
651            Triangle {
652                a: 2,
653                b: 6,
654                c: 7,
655
656                ab_edge: 5,
657                bc_edge: 10,
658                ca_edge: 14,
659                ab_forward: false,
660                bc_forward: false,
661                ca_forward: false,
662                contents: TriangleContents::None,
663            },
664            // Left
665            Triangle {
666                a: 4,
667                b: 2,
668                c: 0,
669
670                ab_edge: 13,
671                bc_edge: 1,
672                ca_edge: 4,
673                ab_forward: false,
674                bc_forward: false,
675                ca_forward: false,
676                contents: TriangleContents::None,
677            },
678            Triangle {
679                a: 4,
680                b: 6,
681                c: 2,
682
683                ab_edge: 9,
684                bc_edge: 5,
685                ca_edge: 13,
686                ab_forward: false,
687                bc_forward: false,
688                ca_forward: false,
689                contents: TriangleContents::None,
690            },
691            // Bottom
692            Triangle {
693                a: 1,
694                b: 5,
695                c: 4,
696
697                ab_edge: 7,
698                bc_edge: 8,
699                ca_edge: 16,
700                ab_forward: false,
701                bc_forward: false,
702                ca_forward: false,
703                contents: TriangleContents::None,
704            },
705            Triangle {
706                a: 1,
707                b: 4,
708                c: 0,
709
710                ab_edge: 16,
711                bc_edge: 4,
712                ca_edge: 0,
713                ab_forward: false,
714                bc_forward: false,
715                ca_forward: false,
716                contents: TriangleContents::None,
717            },
718            // Right
719            Triangle {
720                a: 1,
721                b: 7,
722                c: 5,
723
724                ab_edge: 15,
725                bc_edge: 11,
726                ca_edge: 7,
727                ab_forward: false,
728                bc_forward: false,
729                ca_forward: false,
730                contents: TriangleContents::None,
731            },
732            Triangle {
733                a: 1,
734                b: 3,
735                c: 7,
736
737                ab_edge: 3,
738                bc_edge: 6,
739                ca_edge: 15,
740                ab_forward: false,
741                bc_forward: false,
742                ca_forward: false,
743                contents: TriangleContents::None,
744            },
745            // Front
746            Triangle {
747                a: 5,
748                b: 6,
749                c: 4,
750
751                ab_edge: 17,
752                bc_edge: 9,
753                ca_edge: 8,
754                ab_forward: false,
755                bc_forward: false,
756                ca_forward: false,
757                contents: TriangleContents::None,
758            },
759            Triangle {
760                a: 5,
761                b: 7,
762                c: 6,
763
764                ab_edge: 11,
765                bc_edge: 10,
766                ca_edge: 17,
767                ab_forward: false,
768                bc_forward: false,
769                ca_forward: false,
770                contents: TriangleContents::None,
771            },
772        ];
773
774        pub const EDGES: usize = 18;
775    }
776    pub mod icosphere {
777        use crate::{Triangle, TriangleContents};
778        #[cfg(feature = "shape-extras")]
779        use constgebra::const_soft_float::soft_f32::SoftF32;
780        use glam::Vec3A;
781
782        #[cfg(feature = "shape-extras")]
783        use super::tetrasphere::normal;
784
785        pub(crate) const INITIAL_POINTS: [Vec3A; 12] = [
786            // North Pole
787            Vec3A::Y,
788            // Top Ring
789            Vec3A::new(
790                0.89442719099991585541,
791                0.44721359549995792770,
792                0.00000000000000000000,
793            ),
794            Vec3A::new(
795                0.27639320225002106390,
796                0.44721359549995792770,
797                0.85065080835203987775,
798            ),
799            Vec3A::new(
800                -0.72360679774997882507,
801                0.44721359549995792770,
802                0.52573111211913370333,
803            ),
804            Vec3A::new(
805                -0.72360679774997904712,
806                0.44721359549995792770,
807                -0.52573111211913348129,
808            ),
809            Vec3A::new(
810                0.27639320225002084186,
811                0.44721359549995792770,
812                -0.85065080835203998877,
813            ),
814            // Bottom Ring
815            Vec3A::new(
816                0.72360679774997871405,
817                -0.44721359549995792770,
818                -0.52573111211913392538,
819            ),
820            Vec3A::new(
821                0.72360679774997904712,
822                -0.44721359549995792770,
823                0.52573111211913337026,
824            ),
825            Vec3A::new(
826                -0.27639320225002073084,
827                -0.44721359549995792770,
828                0.85065080835203998877,
829            ),
830            Vec3A::new(
831                -0.89442719099991585541,
832                -0.44721359549995792770,
833                0.00000000000000000000,
834            ),
835            Vec3A::new(
836                -0.27639320225002139697,
837                -0.44721359549995792770,
838                -0.85065080835203976672,
839            ),
840            // South Pole
841            Vec3A::NEG_Y,
842        ];
843
844        #[cfg(feature = "shape-extras")]
845        pub(crate) static TRIANGLE_NORMALS: [Vec3A; 20] = [
846            normal::<0>(&TRIANGLES, &INITIAL_POINTS),
847            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
848            normal::<2>(&TRIANGLES, &INITIAL_POINTS),
849            normal::<3>(&TRIANGLES, &INITIAL_POINTS),
850            normal::<4>(&TRIANGLES, &INITIAL_POINTS),
851            normal::<5>(&TRIANGLES, &INITIAL_POINTS),
852            normal::<6>(&TRIANGLES, &INITIAL_POINTS),
853            normal::<7>(&TRIANGLES, &INITIAL_POINTS),
854            normal::<8>(&TRIANGLES, &INITIAL_POINTS),
855            normal::<9>(&TRIANGLES, &INITIAL_POINTS),
856            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
857            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
858            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
859            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
860            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
861            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
862            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
863            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
864            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
865            normal::<1>(&TRIANGLES, &INITIAL_POINTS),
866        ];
867
868        #[cfg(feature = "shape-extras")]
869        pub(crate) static MIN_NORMAL_DOT: f32 = ((SoftF32(1.0f32).div(SoftF32(30.0)))
870            .mul(SoftF32(25.0).add(SoftF32(5.0_f32)).sqrt()))
871        .sqrt()
872        .to_f32();
873
874        pub const TRIANGLES: [Triangle; 20] = [
875            // Top
876            Triangle {
877                a: 0,
878                b: 2,
879                c: 1,
880
881                ab_edge: 0,
882                bc_edge: 5,
883                ca_edge: 4,
884                ab_forward: false,
885                bc_forward: false,
886                ca_forward: false,
887                contents: TriangleContents::None,
888            }, //0
889            Triangle {
890                a: 0,
891                b: 3,
892                c: 2,
893
894                ab_edge: 1,
895                bc_edge: 6,
896                ca_edge: 0,
897                ab_forward: false,
898                bc_forward: false,
899                ca_forward: false,
900                contents: TriangleContents::None,
901            }, //1
902            Triangle {
903                a: 0,
904                b: 4,
905                c: 3,
906
907                ab_edge: 2,
908                bc_edge: 7,
909                ca_edge: 1,
910                ab_forward: false,
911                bc_forward: false,
912                ca_forward: false,
913                contents: TriangleContents::None,
914            }, //2
915            Triangle {
916                a: 0,
917                b: 5,
918                c: 4,
919
920                ab_edge: 3,
921                bc_edge: 8,
922                ca_edge: 2,
923                ab_forward: false,
924                bc_forward: false,
925                ca_forward: false,
926                contents: TriangleContents::None,
927            }, //3
928            Triangle {
929                a: 0,
930                b: 1,
931                c: 5,
932
933                ab_edge: 4,
934                bc_edge: 9,
935                ca_edge: 3,
936                ab_forward: false,
937                bc_forward: false,
938                ca_forward: false,
939                contents: TriangleContents::None,
940            }, //4
941            // First ring
942            Triangle {
943                a: 5,
944                b: 1,
945                c: 6,
946
947                ab_edge: 9,
948                bc_edge: 10,
949                ca_edge: 15,
950                ab_forward: false,
951                bc_forward: false,
952                ca_forward: false,
953                contents: TriangleContents::None,
954            }, //5
955            Triangle {
956                a: 1,
957                b: 2,
958                c: 7,
959
960                ab_edge: 5,
961                bc_edge: 11,
962                ca_edge: 16,
963                ab_forward: false,
964                bc_forward: false,
965                ca_forward: false,
966                contents: TriangleContents::None,
967            }, //6
968            Triangle {
969                a: 2,
970                b: 3,
971                c: 8,
972
973                ab_edge: 6,
974                bc_edge: 12,
975                ca_edge: 17,
976                ab_forward: false,
977                bc_forward: false,
978                ca_forward: false,
979                contents: TriangleContents::None,
980            }, //7
981            Triangle {
982                a: 3,
983                b: 4,
984                c: 9,
985
986                ab_edge: 7,
987                bc_edge: 13,
988                ca_edge: 18,
989                ab_forward: false,
990                bc_forward: false,
991                ca_forward: false,
992                contents: TriangleContents::None,
993            }, //8
994            Triangle {
995                a: 4,
996                b: 5,
997                c: 10,
998
999                ab_edge: 8,
1000                bc_edge: 14,
1001                ca_edge: 19,
1002                ab_forward: false,
1003                bc_forward: false,
1004                ca_forward: false,
1005                contents: TriangleContents::None,
1006            }, //9
1007            // Second ring
1008            Triangle {
1009                a: 5,
1010                b: 6,
1011                c: 10,
1012
1013                ab_edge: 15,
1014                bc_edge: 20,
1015                ca_edge: 14,
1016                ab_forward: false,
1017                bc_forward: false,
1018                ca_forward: false,
1019                contents: TriangleContents::None,
1020            }, //10
1021            Triangle {
1022                a: 1,
1023                b: 7,
1024                c: 6,
1025
1026                ab_edge: 16,
1027                bc_edge: 21,
1028                ca_edge: 10,
1029                ab_forward: false,
1030                bc_forward: false,
1031                ca_forward: false,
1032                contents: TriangleContents::None,
1033            }, //11
1034            Triangle {
1035                a: 2,
1036                b: 8,
1037                c: 7,
1038
1039                ab_edge: 17,
1040                bc_edge: 22,
1041                ca_edge: 11,
1042                ab_forward: false,
1043                bc_forward: false,
1044                ca_forward: false,
1045                contents: TriangleContents::None,
1046            }, //12
1047            Triangle {
1048                a: 3,
1049                b: 9,
1050                c: 8,
1051
1052                ab_edge: 18,
1053                bc_edge: 23,
1054                ca_edge: 12,
1055                ab_forward: false,
1056                bc_forward: false,
1057                ca_forward: false,
1058                contents: TriangleContents::None,
1059            }, //13
1060            Triangle {
1061                a: 4,
1062                b: 10,
1063                c: 9,
1064
1065                ab_edge: 19,
1066                bc_edge: 24,
1067                ca_edge: 13,
1068                ab_forward: false,
1069                bc_forward: false,
1070                ca_forward: false,
1071                contents: TriangleContents::None,
1072            }, //14
1073            // Bottom
1074            Triangle {
1075                a: 10,
1076                b: 6,
1077                c: 11,
1078
1079                ab_edge: 20,
1080                bc_edge: 26,
1081                ca_edge: 25,
1082                ab_forward: false,
1083                bc_forward: false,
1084                ca_forward: false,
1085                contents: TriangleContents::None,
1086            }, //15
1087            Triangle {
1088                a: 6,
1089                b: 7,
1090                c: 11,
1091
1092                ab_edge: 21,
1093                bc_edge: 27,
1094                ca_edge: 26,
1095                ab_forward: false,
1096                bc_forward: false,
1097                ca_forward: false,
1098                contents: TriangleContents::None,
1099            }, //16
1100            Triangle {
1101                a: 7,
1102                b: 8,
1103                c: 11,
1104
1105                ab_edge: 22,
1106                bc_edge: 28,
1107                ca_edge: 27,
1108                ab_forward: false,
1109                bc_forward: false,
1110                ca_forward: false,
1111                contents: TriangleContents::None,
1112            }, //17
1113            Triangle {
1114                a: 8,
1115                b: 9,
1116                c: 11,
1117
1118                ab_edge: 23,
1119                bc_edge: 29,
1120                ca_edge: 28,
1121                ab_forward: false,
1122                bc_forward: false,
1123                ca_forward: false,
1124                contents: TriangleContents::None,
1125            }, //18
1126            Triangle {
1127                a: 9,
1128                b: 10,
1129                c: 11,
1130
1131                ab_edge: 24,
1132                bc_edge: 25,
1133                ca_edge: 29,
1134                ab_forward: false,
1135                bc_forward: false,
1136                ca_forward: false,
1137                contents: TriangleContents::None,
1138            }, //19
1139        ];
1140
1141        pub const EDGES: usize = 30;
1142    }
1143}
1144
1145#[cfg(test)]
1146mod test {
1147    #[test]
1148    fn assert_normal_numbers() {
1149        use super::consts;
1150        let all_source_points = [
1151            &consts::cube::INITIAL_POINTS[..],
1152            &consts::icosphere::INITIAL_POINTS[..],
1153            &consts::square::INITIAL_POINTS[..],
1154            &consts::tetrasphere::INITIAL_POINTS[..],
1155            &consts::triangle::INITIAL_POINTS[..],
1156        ];
1157
1158        for point in all_source_points.iter().flat_map(|x| x.iter()) {
1159            assert!(point.is_finite());
1160        }
1161    }
1162}