1use crate::Tf;
16use genmesh::generators::{IcoSphere, IndexedPolygon, SharedVertex};
17use lazy_static::lazy_static;
18use nalgebra::base::dimension::{U1, U4};
19use std::rc::Rc;
20
21pub type Vertex = nalgebra::Matrix<f32, U4, U1, nalgebra::MatrixArray<f32, U4, U1>>;
23
24pub fn vertex(x: f32, y: f32, z: f32) -> Vertex {
26 Vertex::new(x, y, z, 1.0)
27}
28
29pub(crate) fn sphere_of_resolution(resolution: usize) -> Mesh {
30 Mesh::new(
31 IcoSphere::subdivide(resolution)
32 .shared_vertex_iter()
33 .map(|v| Tf::s(0.5).apply_to(vertex(v.pos.x, v.pos.y, v.pos.z)))
34 .collect(),
35 Some(
36 IcoSphere::subdivide(resolution)
37 .shared_vertex_iter()
38 .map(|v| vertex(v.normal.x, v.normal.y, v.normal.z))
39 .collect(),
40 ),
41 IcoSphere::subdivide(resolution)
42 .indexed_polygon_iter()
43 .map(|t| vec![t.x + 1, t.y + 1, t.z + 1])
44 .collect(),
45 )
46}
47
48lazy_static! {
49 static ref CUBE_MESH: Mesh = Mesh::new(
50 vec![
51 vertex(-0.5, 0.5, 0.5),
52 vertex(-0.5, -0.5, 0.5),
53 vertex(0.5, -0.5, 0.5),
54 vertex(0.5, 0.5, 0.5),
55 vertex(-0.5, 0.5, -0.5),
56 vertex(-0.5, -0.5, -0.5),
57 vertex(0.5, -0.5, -0.5),
58 vertex(0.5, 0.5, -0.5),
59 ],
60 None,
61 vec![
62 vec![1, 2, 3, 4],
63 vec![8, 7, 6, 5],
64 vec![4, 3, 7, 8],
65 vec![5, 1, 4, 8],
66 vec![5, 6, 2, 1],
67 vec![2, 6, 7, 3],
68 ]
69 );
70 static ref ICO_SPHERE: Mesh = sphere_of_resolution(0);
71}
72
73#[derive(Debug)]
81pub struct Mesh {
82 vertices: Vec<Vertex>,
83 normals: Option<Vec<Vertex>>,
84 faces: Vec<Vec<usize>>,
85}
86
87impl Mesh {
88 pub fn from(
90 vertices: Vec<Vertex>,
91 normals: Option<Vec<Vertex>>,
92 faces: Vec<Vec<usize>>,
93 ) -> Rc<Self> {
94 Rc::new(Self::new(vertices, normals, faces))
95 }
96
97 pub(crate) fn new(
98 vertices: Vec<Vertex>,
99 normals: Option<Vec<Vertex>>,
100 faces: Vec<Vec<usize>>,
101 ) -> Self {
102 Self {
103 vertices,
104 normals,
105 faces: faces,
106 }
107 }
108
109 pub(crate) fn vertices<'a>(&'a self) -> &'a [Vertex] {
110 self.vertices.as_slice()
111 }
112
113 pub(crate) fn normals<'a>(&'a self) -> Option<&'a [Vertex]> {
114 self.normals.as_ref().map(|ns| ns.as_slice())
115 }
116
117 pub(crate) fn faces<'a>(&'a self) -> impl Iterator<Item = &'a [usize]> {
118 self.faces.iter().map(|f| f.as_slice())
119 }
120}
121
122#[derive(Clone, Debug)]
123pub enum PrimitiveMesh {
124 Cube,
125 IcoSphere,
126}
127
128impl PrimitiveMesh {
129 pub(crate) fn mesh(&self) -> &'static Mesh {
130 match *self {
131 PrimitiveMesh::Cube => &*CUBE_MESH,
132 PrimitiveMesh::IcoSphere => &*ICO_SPHERE,
133 }
134 }
135}