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#[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
65pub type IcoSphere<T> = Subdivided<T, IcoSphereBase>;
71
72impl<T> IcoSphere<T> {
73 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#[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
136pub type NormIcoSphere<T> = Subdivided<T, NormIcoSphereBase>;
142
143#[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
199pub type TetraSphere<T> = Subdivided<T, TetraSphereBase>;
205
206#[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
262pub type TrianglePlane<T> = Subdivided<T, TriangleBase>;
268
269#[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
309pub type SquarePlane<T> = Subdivided<T, SquareBase>;
315
316#[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
357pub type CubeSphere<T> = Subdivided<T, CubeBase>;
363
364mod 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 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 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 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 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 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 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 Vec3A::Y,
788 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 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 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 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, 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 }, ];
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}