geometry.rs
1    use bytemuck::{Pod, Zeroable};
2    use nalgebra::Vector4;
3    use rapier3d::parry::math::Point;
4    use tobj::{LoadError, Model, Material};
5    
6    
7    #[repr(C)]
8    #[derive(Clone, Copy, Debug)]
9    pub struct Vertex {
10       pos: [f32; 4],
11       normal: [f32; 4],
12       uv: [f32; 2],
13   }
14   
15   impl Vertex {
16       pub fn position(&self) -> Point<f32> {
17           Point::<f32>::new(self.pos[0], self.pos[1], self.pos[2])
18       }
19       pub fn from(pos: [f32; 3], nor: [f32; 3], uv: [f32; 2]) -> Vertex {
20           Vertex {
21               pos: [pos[0], pos[1], pos[2], 1.0],
22               normal: [nor[0], nor[1], nor[2], 0.0],
23               uv: [uv[0], uv[1]],
24           }
25       }
26   }
27   
28   unsafe impl Pod for Vertex {}
29   unsafe impl Zeroable for Vertex {}
30   
31   #[derive(Clone, Debug)]
32   pub struct RawMesh {
33       pub vertices: Vec<Vertex>,
34       pub indices: Vec<[u32; 3]>,
35   }
36   
37   
38   /// We use meshes in a few different places. To keep things simple, we return
39   /// the most basic, direct-to-memory version. If something fancy needs to be done
40   /// with it, the fancy stays there
41   pub fn load_obj(obj_path: &str) -> Result<RawMesh, String> {
42   
43       log::info!("Loading object {}", obj_path);
44   
45       // Is there no better way to translate error messages?
46       let (models, materials) = match tobj::load_obj(obj_path, true) {
47           Ok((a, b)) => {Ok((a, b))}
48           Err(load_error) => {Err(load_error.to_string())}
49       }?;
50   
51       // println!("# of models: {}", models.len());
52       // println!("# of materials: {}", materials.len());
53       // println!("{:?}", materials);
54   
55       let mut index_data: Vec<[u32; 3]> = Vec::new();
56       let mut vertex_data = Vec::new();
57   
58       for model in models {
59           let mesh = &model.mesh;
60   
61           // Cycle through the faces and chunk out the indices
62           let mut next_face = 0;
63           for f in 0..mesh.num_face_indices.len() {
64               // calculate the next chunk
65               let end = next_face + mesh.num_face_indices[f] as usize;
66               let face_indices: Vec<_> = mesh.indices[next_face..end].iter().collect();
67   
68               if face_indices.len() != 3 {
69                   return Err("we only handle triangulated faces".to_string());
70               }
71               index_data.push([*face_indices[0], *face_indices[1], *face_indices[2]]);
72               next_face = end;
73           }
74   
75           if mesh.positions.len() % 3 != 0 {
76               return Err(format!("position array not % 3 : {}", mesh.positions.len()))
77           }
78           if mesh.texcoords.len() % 2 != 0 {
79               return Err(format!("position array not % 3 : {}", mesh.positions.len()))
80           }
81           if mesh.normals.is_empty() {
82               return Err(format!("It would be best if this had normals"))
83           }
84           if mesh.texcoords.is_empty() {
85               log::info!("\tMesh texture coordinates empty")
86           }
87   
88           for v in 0..mesh.positions.len() / 3 {
89               let texcoords = if mesh.texcoords.len() == 0 {
90                   [0.0, 0.0]
91               } else {
92                   [mesh.texcoords[2 * v], mesh.texcoords[2 * v + 1]]
93               };
94   
95               vertex_data.push(Vertex::from(
96                   [
97                       mesh.positions[3 * v],
98                       mesh.positions[3 * v + 1],
99                       mesh.positions[3 * v + 2],
100                  ],
101                  [
102                      mesh.normals[3 * v],
103                      mesh.normals[3 * v + 1],
104                      mesh.normals[3 * v + 2],
105                  ],
106                  texcoords,
107              ));
108          }
109      }
110      Ok(RawMesh {
111          vertices: vertex_data.to_vec(),
112          indices: index_data.to_vec(),
113      })
114  }
115  
116  // pub fn create_quad_mesh() -> RawMesh {
117  //
118  //     let mut index_data: Vec<[u32; 3]> = Vec::new();
119  //     let mut vertex_data = Vec::new();
120  //
121  //     vertex_data.push(Vertex::from(
122  //         [
123  //             mesh.positions[3 * v],
124  //             mesh.positions[3 * v + 1],
125  //             mesh.positions[3 * v + 2],
126  //         ],
127  //         [
128  //             mesh.normals[3 * v],
129  //             mesh.normals[3 * v + 1],
130  //             mesh.normals[3 * v + 2],
131  //         ],
132  //         [mesh.texcoords[2 * v], mesh.texcoords[2 * v + 1]],
133  //     ));
134  //
135  //     RawMesh {
136  //         vertices: vertex_data.to_vec(),
137  //         indices: index_data.to_vec(),
138  //     }
139  // }
140