diff options
Diffstat (limited to 'engine/src/file_format')
| -rw-r--r-- | engine/src/file_format/wavefront/mtl.rs | 20 | ||||
| -rw-r--r-- | engine/src/file_format/wavefront/obj.rs | 147 |
2 files changed, 116 insertions, 51 deletions
diff --git a/engine/src/file_format/wavefront/mtl.rs b/engine/src/file_format/wavefront/mtl.rs index 7d1c570..f3c7a64 100644 --- a/engine/src/file_format/wavefront/mtl.rs +++ b/engine/src/file_format/wavefront/mtl.rs @@ -234,6 +234,24 @@ fn statements_to_materials( path: Path::new(texture_file_path).to_path_buf(), }); } + Keyword::Ns => { + if statement.arguments.len() != 1 { + return Err(Error::UnsupportedArgumentCount { + keyword: statement.keyword.to_string(), + arg_count: statement.arguments.len(), + line_no, + }); + } + + let shininess = statement.get_float_arg(0, line_no)?; + + tracing::debug!( + "Adding shininess {shininess} to material {}", + curr_material.name + ); + + curr_material.shininess = shininess; + } Keyword::Newmtl => {} } } @@ -279,5 +297,7 @@ keyword! { #[keyword(rename = "map_Ks")] MapKs, + + Ns, } } diff --git a/engine/src/file_format/wavefront/obj.rs b/engine/src/file_format/wavefront/obj.rs index 88d566c..ebbbe45 100644 --- a/engine/src/file_format/wavefront/obj.rs +++ b/engine/src/file_format/wavefront/obj.rs @@ -13,7 +13,12 @@ use crate::file_format::wavefront::common::{ Statement, Triplet, }; -use crate::mesh::{Mesh, Vertex}; +use crate::mesh::vertex_buffer::{ + NamedVertexAttr, + VertexAttrInfo, + VertexBuffer as MeshVertexBuffer, +}; +use crate::mesh::{Mesh, VertexAttrType, POSITION_VERTEX_ATTRIB_NAME}; use crate::util::try_option; use crate::vector::{Vec2, Vec3}; @@ -82,7 +87,24 @@ impl Obj /// - A face index does not fit in a [`u32`] pub fn to_mesh(&self) -> Result<Mesh, Error> { - let mut vertices = Vec::<Vertex>::with_capacity(self.faces.len() * 3); + let mut vertex_buf = MeshVertexBuffer::with_capacity( + &[ + VertexAttrInfo { + name: POSITION_VERTEX_ATTRIB_NAME.into(), + ty: VertexAttrType::Float32Array { length: 3 }, + }, + VertexAttrInfo { + name: "texture_coords".into(), + ty: VertexAttrType::Float32Array { length: 2 }, + }, + VertexAttrInfo { + name: "normal".into(), + ty: VertexAttrType::Float32Array { length: 3 }, + }, + ], + self.faces.len() * 3, + ); + let mut indices = Vec::<u32>::with_capacity(self.faces.len() * 3); let mut added_face_vertices = @@ -96,10 +118,75 @@ impl Obj continue; } - vertices.push(face_vertex.to_vertex(self)?); + let pos = self + .vertex_positions + .get(face_vertex.position as usize - 1) + .ok_or(Error::FaceVertexPositionNotFound { + vertex_pos_index: face_vertex.position, + })? + .clone(); + + let texture_pos = face_vertex.texture.map_or_else( + || { + if !self.texture_positions.is_empty() { + tracing::warn!(concat!( + "Wavefront OBJ has texture coordinates ", + "but face vertex does not specify one" + )); + } + + Ok(Vec2::default()) + }, + |face_vertex_texture| { + self.texture_positions + .get(face_vertex_texture as usize - 1) + .ok_or(Error::FaceTexturePositionNotFound { + texture_pos_index: face_vertex_texture, + }) + .cloned() + }, + )?; + + let normal = face_vertex.normal.map_or_else( + || { + if !self.vertex_normals.is_empty() { + tracing::warn!(concat!( + "Wavefront OBJ has normals ", + "but face vertex does not specify one" + )); + } + + Ok(Vec3::default()) + }, + |face_vertex_normal| { + self.vertex_normals + .get(face_vertex_normal as usize - 1) + .ok_or(Error::FaceVertexNormalNotFound { + vertex_normal_index: face_vertex_normal, + }) + .cloned() + }, + )?; - let vertex_index = u32::try_from(vertices.len() - 1) - .map_err(|_| Error::FaceIndexTooBig(vertices.len() - 1))?; + vertex_buf.push(( + NamedVertexAttr { + name: POSITION_VERTEX_ATTRIB_NAME, + value: pos.into_array(), + }, + NamedVertexAttr { + name: "texture_coords", + value: texture_pos.into_array(), + }, + NamedVertexAttr { + name: "normal", + value: normal.into_array(), + }, + )); + + let vertex_index = vertex_buf.len() - 1; + + let vertex_index = u32::try_from(vertex_index) + .map_err(|_| Error::FaceIndexTooBig(vertex_index))?; indices.push(vertex_index); @@ -107,7 +194,10 @@ impl Obj } } - Ok(Mesh::new(vertices, Some(indices))) + Ok(Mesh::builder() + .vertices(vertex_buf) + .indices(indices) + .build()) } /// Reads and parses the material libraries of this `Obj`. @@ -156,51 +246,6 @@ pub struct FaceVertex pub normal: Option<u32>, } -impl FaceVertex -{ - /// Tries to convert this face vertex into a [`Vertex`]. - /// - /// # Errors - /// Returns `Err` if: - /// - The face's vertex position cannot be found in the given [`Obj`] - /// - The face's texture position cannot be found in the given [`Obj`] - /// - The face's vertex normal cannot be found in the given [`Obj`] - pub fn to_vertex(&self, obj: &Obj) -> Result<Vertex, Error> - { - let mut vertex_builder = Vertex::builder(); - - let vertex_pos = *obj.vertex_positions.get(self.position as usize - 1).ok_or( - Error::FaceVertexPositionNotFound { vertex_pos_index: self.position }, - )?; - - vertex_builder = vertex_builder.pos(vertex_pos); - - if let Some(face_vertex_texture) = self.texture { - let texture_pos = obj - .texture_positions - .get(face_vertex_texture as usize - 1) - .ok_or(Error::FaceTexturePositionNotFound { - texture_pos_index: face_vertex_texture, - })?; - - vertex_builder = vertex_builder.texture_coords(*texture_pos); - } - - if let Some(face_vertex_normal) = self.normal { - let vertex_normal = *obj - .vertex_normals - .get(face_vertex_normal as usize - 1) - .ok_or(Error::FaceVertexNormalNotFound { - vertex_normal_index: face_vertex_normal, - })?; - - vertex_builder = vertex_builder.normal(vertex_normal); - } - - Ok(vertex_builder.build()) - } -} - impl From<Triplet> for FaceVertex { fn from(triplet: Triplet) -> Self |
