summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md2
-rw-r--r--engine/src/file_format/wavefront/obj.rs49
2 files changed, 29 insertions, 22 deletions
diff --git a/TODO.md b/TODO.md
index f9bc8ee..dc966c6 100644
--- a/TODO.md
+++ b/TODO.md
@@ -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,