diff --git a/assets/shaders/shader.vert b/assets/shaders/shader.vert index 1b7a338..b4bfb74 100644 --- a/assets/shaders/shader.vert +++ b/assets/shaders/shader.vert @@ -2,6 +2,7 @@ uniform mat4 perspective; uniform mat4 view; +uniform vec3 texture_size; in vec3 vertex; in vec2 tex_coords; @@ -12,7 +13,7 @@ out vec3 v_normal; void main() { v_normal = normal; - v_tex_coords = tex_coords; + v_tex_coords = vec2(tex_coords.x * texture_size.x, tex_coords.y * texture_size.y); gl_Position = perspective * view * vec4(vertex, 1.0); } diff --git a/src/model/material.rs b/src/model/material.rs index dd65134..c49b0ad 100644 --- a/src/model/material.rs +++ b/src/model/material.rs @@ -14,7 +14,7 @@ pub struct Material { pub diffuse: Vector3, /// Map linking each texture map to its file path. - pub textures: HashMap, + pub textures: HashMap)>, /// Instructions that are unknown. /// diff --git a/src/model/mod.rs b/src/model/mod.rs index 2f279d7..e85d92c 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -102,7 +102,7 @@ pub struct Model { pub materials: HashMap, /// Map associating the name of a texture and the real texture. - pub textures: HashMap>, + pub textures: HashMap, Vector3)>, /// The list of parts of the model. pub parts: Vec, @@ -544,15 +544,15 @@ impl Model { /// Builds the SrgbTextures for rendering. pub fn build_texture_for_material(&mut self, material: &Material, renderer: &Renderer) { - if let Some(path) = material.textures.get("map_Kd") { + if let Some((path, size)) = material.textures.get("map_Kd") { let texture = renderer.make_texture(path); // Don't need to insert multiple times the same texture - self.textures.entry(path.to_owned()).or_insert(Rc::new(texture)); + self.textures.entry(path.to_owned()).or_insert((Rc::new(texture), *size)); }; } /// Returns the rendering texture. - pub fn get_texture_by_name(&self, name: &str) -> Option<&Rc> { + pub fn get_texture_by_name(&self, name: &str) -> Option<&(Rc, Vector3)> { self.textures.get(name) } @@ -562,7 +562,7 @@ impl Model { } /// Returns a ref mut to the table of textures. - pub fn textures_mut(&mut self) -> &mut HashMap> { + pub fn textures_mut(&mut self) -> &mut HashMap, Vector3)> { &mut self.textures } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index fc1f916..c0f3d8b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -46,7 +46,8 @@ pub enum Element { /// /// First string is the name of the map. /// Second string is the path to the image file. - Texture(String, String), + /// Vector3 is the size of the texture. + Texture(String, String, Vector3), /// Change the main color of the current material. Diffuse(Vector3), @@ -107,6 +108,12 @@ pub enum ParserError { /// usize is the line. NoMaterialExist(String, usize), + /// No path after a map + NoPathAfterMap(String, usize), + + /// Unexpected token + UnexpectedToken(String, usize, String), + /// Something weird happened OtherError(String), } @@ -175,6 +182,10 @@ impl fmt::Display for ParserError { write!(f, "Redecralation of material in {}:{}:\n\t{} already exists", p, n, l), ParserError::NoMaterialExist(ref p, l) => write!(f, "Missing material in {}:{}\n\tNo material were defined, can't set attribute", p, l), + ParserError::NoPathAfterMap(ref p, l) => + write!(f, "Missing path for map in {}:{}", p, l), + ParserError::UnexpectedToken(ref p, l, ref t) => + write!(f, "Unexpected token {} in {}:{}", t, p, l), ParserError::OtherError(ref p) => write!(f, "Something weird happened in {}...", p), } @@ -265,7 +276,7 @@ impl Parser for LP { } }, - Element::Texture(texture_name, texture_path) => { + Element::Texture(texture_name, texture_path, size) => { if current_material_name.is_none() { return Err(ParserError::NoMaterialExist(path.to_owned(), num)); } @@ -279,7 +290,7 @@ impl Parser for LP { } let current_material = current_material.unwrap(); - current_material.textures.insert(texture_name, texture_path); + current_material.textures.insert(texture_name, (texture_path, size)); }, Element::Diffuse(v) => { diff --git a/src/parser/mtl.rs b/src/parser/mtl.rs index 73575f9..287fdcf 100644 --- a/src/parser/mtl.rs +++ b/src/parser/mtl.rs @@ -54,9 +54,25 @@ impl LineParser for MtlParser { map if map.starts_with("map_") => { - let mut full_path = root.clone(); - full_path.push(split.nth(0).unwrap().to_owned()); - Ok(Element::Texture(first.to_owned(), full_path.to_str().unwrap().to_owned())) + let split = split.collect::>(); + if split.len() == 0 { + Err(ParserError::NoPathAfterMap(path.to_owned(), line_number)) + } else if split.len() == 1 { + let mut full_path = root.clone(); + full_path.push(split[0].to_owned()); + Ok(Element::Texture(first.to_owned(), full_path.to_str().unwrap().to_owned(), Vector3::new(1.0, 1.0, 1.0))) + } else if split[0] == "-s" { + let size = Vector3::new( + if let Ok(f) = split[1].parse::() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[1].to_owned())); }, + if let Ok(f) = split[2].parse::() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[2].to_owned())); }, + if let Ok(f) = split[3].parse::() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[3].to_owned())); }, + ); + let mut full_path = root.clone(); + full_path.push(split[4].to_owned()); + Ok(Element::Texture(first.to_owned(), full_path.to_str().unwrap().to_owned(), size)) + } else { + Err(ParserError::UnexpectedKeyword(path.to_owned(), line_number, split[2].to_owned())) + } }, diff --git a/src/renderer.rs b/src/renderer.rs index 1983b09..0ebd676 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -151,10 +151,10 @@ impl Renderer { let texture = self.get_texture_of_part(&model, part); - let texture = if let Some(texture) = texture { - texture + let (texture, size) = if let Some((texture, size)) = texture { + (texture, size) } else { - &self.default_texture + (&self.default_texture, Vector3::new(1.0, 1.0, 1.0)) }; target.draw( @@ -166,6 +166,7 @@ impl Renderer { tex: texture, perspective: Into::<[[f32; 4]; 4]>::into(perspective), view: Into::<[[f32; 4]; 4]>::into(view), + texture_size: Into::<[f32; 3]>::into(size), ), ¶ms, ).unwrap(); @@ -177,12 +178,12 @@ impl Renderer { } /// Renders a part of a model. - fn get_texture_of_part<'a>(&self, model: &'a Model, part: &Part) -> Option<&'a SrgbTexture2d> { + fn get_texture_of_part<'a>(&self, model: &'a Model, part: &Part) -> Option<(&'a SrgbTexture2d, Vector3)> { if let Some(ref material_name) = part.material_name { if let Some(ref material) = model.materials.get(material_name) { - if let Some(texture) = material.textures.get("map_Kd") { - if let Some(ref texture) = model.get_texture_by_name(&texture) { - Some(texture) + if let Some((texture, _)) = material.textures.get("map_Kd") { + if let Some((texture, size)) = model.get_texture_by_name(texture) { + Some((texture, *size)) } else { None }