diff options
| -rw-r--r-- | TODO.md | 2 | ||||
| -rw-r--r-- | engine/src/file_format/wavefront/obj.rs | 49 | 
2 files changed, 29 insertions, 22 deletions
@@ -29,5 +29,5 @@  - [ ] Physics  - [ ] Rotation (using quaternions)  - [ ] Add support for entity tags in ECS framework -- [ ] engine::file_format:wavefront::obj::Obj::to_mesh seems to produce meshes with +- [x] engine::file_format:wavefront::obj::Obj::to_mesh seems to produce meshes with        pointless vertex indices since it flat maps all face vertices diff --git a/engine/src/file_format/wavefront/obj.rs b/engine/src/file_format/wavefront/obj.rs index 88e6580..6ca11c2 100644 --- a/engine/src/file_format/wavefront/obj.rs +++ b/engine/src/file_format/wavefront/obj.rs @@ -2,6 +2,7 @@  //!  //! File format documentation: <https://paulbourke.net/dataformats/obj> +use std::collections::HashMap;  use std::fs::read_to_string;  use std::path::PathBuf; @@ -82,26 +83,32 @@ impl Obj      /// - A face index does not fit in a [`u32`]      pub fn to_mesh(&self) -> Result<Mesh, Error>      { -        let vertices = self -            .faces -            .iter() -            .flat_map(|face| face.vertices.clone()) -            .map(|face_vertex| face_vertex.to_vertex(self)) -            .collect::<Result<Vec<_>, Error>>()?; - -        Ok(Mesh::new( -            vertices, -            Some( -                self.faces -                    .iter() -                    .flat_map(|face| face.vertices.clone()) -                    .enumerate() -                    .map(|(index, _)| { -                        u32::try_from(index).map_err(|_| Error::FaceIndexTooBig(index)) -                    }) -                    .collect::<Result<Vec<_>, _>>()?, -            ), -        )) +        let mut vertices = Vec::<Vertex>::with_capacity(self.faces.len() * 3); +        let mut indices = Vec::<u32>::with_capacity(self.faces.len() * 3); + +        let mut added_face_vertices = +            HashMap::<FaceVertex, u32>::with_capacity(self.faces.len() * 3); + +        for face in &self.faces { +            for face_vertex in &face.vertices { +                if let Some(index) = added_face_vertices.get(&face_vertex) { +                    indices.push(*index); + +                    continue; +                } + +                vertices.push(face_vertex.to_vertex(self)?); + +                let vertex_index = u32::try_from(vertices.len() - 1) +                    .map_err(|_| Error::FaceIndexTooBig(vertices.len() - 1))?; + +                indices.push(vertex_index); + +                added_face_vertices.insert(face_vertex.clone(), vertex_index); +            } +        } + +        Ok(Mesh::new(vertices, Some(indices)))      }      /// Reads and parses the material libraries of this `Obj`. @@ -142,7 +149,7 @@ pub struct Face      pub material_name: Option<String>,  } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)]  pub struct FaceVertex  {      pub position: u32,  | 
