Fixed some things, enable parsing from anything that impl Read
This commit is contained in:
		
							parent
							
								
									f730824f03
								
							
						
					
					
						commit
						66001b2f71
					
				
							
								
								
									
										134
									
								
								src/model/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/model/mod.rs
									
									
									
									
									
								
							@ -5,11 +5,12 @@ pub mod material;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
use std::collections::hash_map::Entry;
 | 
					use std::collections::hash_map::Entry;
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use glium::VertexBuffer;
 | 
					use glium::VertexBuffer;
 | 
				
			||||||
use glium::texture::SrgbTexture2d;
 | 
					use glium::texture::SrgbTexture2d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use parser::{parse, ParserError};
 | 
					use parser::{parse_file, ParserError};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use model::face::{FaceVertex, Face};
 | 
					use model::face::{FaceVertex, Face};
 | 
				
			||||||
use model::material::Material;
 | 
					use model::material::Material;
 | 
				
			||||||
@ -38,11 +39,14 @@ pub struct Part {
 | 
				
			|||||||
    pub material_name: Option<String>,
 | 
					    pub material_name: Option<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// List of all the faces in the part.
 | 
					    /// List of all the faces in the part.
 | 
				
			||||||
    pub faces: Vec<Face>,
 | 
					    faces: Vec<Face>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// VertexBuffer for rendering.
 | 
					    /// VertexBuffer for rendering.
 | 
				
			||||||
    vertex_buffer: Option<VertexBuffer<Vertex>>,
 | 
					    vertex_buffer: Option<VertexBuffer<Vertex>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// True if the faces have been changed since the last time the buffer was built.
 | 
				
			||||||
 | 
					    needs_update: bool,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Part {
 | 
					impl Part {
 | 
				
			||||||
@ -53,6 +57,7 @@ impl Part {
 | 
				
			|||||||
            material_name: material_name,
 | 
					            material_name: material_name,
 | 
				
			||||||
            faces: vec![],
 | 
					            faces: vec![],
 | 
				
			||||||
            vertex_buffer: None,
 | 
					            vertex_buffer: None,
 | 
				
			||||||
 | 
					            needs_update: true,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,6 +68,7 @@ impl Part {
 | 
				
			|||||||
        let mut f = f;
 | 
					        let mut f = f;
 | 
				
			||||||
        f.material_name = self.material_name.clone();
 | 
					        f.material_name = self.material_name.clone();
 | 
				
			||||||
        self.faces.push(f);
 | 
					        self.faces.push(f);
 | 
				
			||||||
 | 
					        self.needs_update = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns a reference to the vertex buffer.
 | 
					    /// Returns a reference to the vertex buffer.
 | 
				
			||||||
@ -70,6 +76,11 @@ impl Part {
 | 
				
			|||||||
        &self.vertex_buffer
 | 
					        &self.vertex_buffer
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a reference to the faces.
 | 
				
			||||||
 | 
					    pub fn faces(&self) -> &Vec<Face> {
 | 
				
			||||||
 | 
					        &self.faces
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,7 +102,7 @@ pub struct Model {
 | 
				
			|||||||
    pub materials: HashMap<String, Material>,
 | 
					    pub materials: HashMap<String, Material>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Map associating the name of a texture and the real texture.
 | 
					    /// Map associating the name of a texture and the real texture.
 | 
				
			||||||
    pub textures: HashMap<String, SrgbTexture2d>,
 | 
					    pub textures: HashMap<String, Rc<SrgbTexture2d>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// The list of parts of the model.
 | 
					    /// The list of parts of the model.
 | 
				
			||||||
    pub parts: Vec<Part>,
 | 
					    pub parts: Vec<Part>,
 | 
				
			||||||
@ -127,10 +138,57 @@ impl Model {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Merges the model passed as parameter into the current model.
 | 
					    /// Copies the materials and textures from the other model into self.
 | 
				
			||||||
    pub fn merge(&mut self, other: Model) {
 | 
					    pub fn merge_material_and_textures(&mut self, other: &Model) {
 | 
				
			||||||
 | 
					        // Merge the materials
 | 
				
			||||||
 | 
					        for (name, material) in &other.materials {
 | 
				
			||||||
 | 
					            let entry = self.materials.entry(name.clone());
 | 
				
			||||||
 | 
					            if let Entry::Occupied(_) = entry {
 | 
				
			||||||
 | 
					                eprintln!("Warning: materials merged but sharing the same name");
 | 
				
			||||||
 | 
					                // Return error
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                entry.or_insert(material.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge the textures
 | 
				
			||||||
 | 
					        for (name, texture) in &other.textures {
 | 
				
			||||||
 | 
					            let entry = self.textures.entry(name.clone());
 | 
				
			||||||
 | 
					            if let Entry::Occupied(_) = entry {
 | 
				
			||||||
 | 
					                eprintln!("Warning: textures merged but sharing the same name");
 | 
				
			||||||
 | 
					                // return Error;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                entry.or_insert(texture.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Merges the model passed as parameter into new parts of the current model.
 | 
				
			||||||
 | 
					    pub fn merge_in_new_parts(&mut self, other: Model) {
 | 
				
			||||||
        let mut other = other;
 | 
					        let mut other = other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge the materials
 | 
				
			||||||
 | 
					        for (name, material) in other.materials {
 | 
				
			||||||
 | 
					            let entry = self.materials.entry(name);
 | 
				
			||||||
 | 
					            if let Entry::Occupied(_) = entry {
 | 
				
			||||||
 | 
					                eprintln!("Warning: materials merged but sharing the same name");
 | 
				
			||||||
 | 
					                // Return error
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                entry.or_insert(material);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge the textures
 | 
				
			||||||
 | 
					        for (name, texture) in other.textures {
 | 
				
			||||||
 | 
					            let entry = self.textures.entry(name);
 | 
				
			||||||
 | 
					            if let Entry::Occupied(_) = entry {
 | 
				
			||||||
 | 
					                eprintln!("Warning: textures merged but sharing the same name");
 | 
				
			||||||
 | 
					                // return Error;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                entry.or_insert(texture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let vertex_offset = self.vertices.len();
 | 
					        let vertex_offset = self.vertices.len();
 | 
				
			||||||
        let tex_coord_offset = self.texture_coordinates.len();
 | 
					        let tex_coord_offset = self.texture_coordinates.len();
 | 
				
			||||||
        let normal_offset = self.normals.len();
 | 
					        let normal_offset = self.normals.len();
 | 
				
			||||||
@ -161,9 +219,17 @@ impl Model {
 | 
				
			|||||||
                new_part.faces.push(face.clone());
 | 
					                new_part.faces.push(face.clone());
 | 
				
			||||||
                self.faces.push(face.clone());
 | 
					                self.faces.push(face.clone());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            new_part.needs_update = true;
 | 
				
			||||||
            self.parts.push(new_part);
 | 
					            self.parts.push(new_part);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Merges the model passed as parameter into existing parts of the current model.
 | 
				
			||||||
 | 
					    pub fn merge_in_existing_parts(&mut self, other: Model) {
 | 
				
			||||||
 | 
					        let mut other = other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Merge the materials
 | 
					        // Merge the materials
 | 
				
			||||||
        for (name, material) in other.materials {
 | 
					        for (name, material) in other.materials {
 | 
				
			||||||
            let entry = self.materials.entry(name);
 | 
					            let entry = self.materials.entry(name);
 | 
				
			||||||
@ -185,11 +251,51 @@ impl Model {
 | 
				
			|||||||
                entry.or_insert(texture);
 | 
					                entry.or_insert(texture);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let vertex_offset = self.vertices.len();
 | 
				
			||||||
 | 
					        let tex_coord_offset = self.texture_coordinates.len();
 | 
				
			||||||
 | 
					        let normal_offset = self.normals.len();
 | 
				
			||||||
 | 
					        let face_offset = self.faces.len();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge the elements
 | 
				
			||||||
 | 
					        self.vertices.append(&mut other.vertices);
 | 
				
			||||||
 | 
					        self.texture_coordinates.append(&mut other.texture_coordinates);
 | 
				
			||||||
 | 
					        self.normals.append(&mut other.normals);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge the parts and faces
 | 
				
			||||||
 | 
					        for part in &mut other.parts {
 | 
				
			||||||
 | 
					            self.change_part(part.material_name.clone());
 | 
				
			||||||
 | 
					            let mut new_faces = vec![];
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                let new_part = self.current_part_mut().unwrap();
 | 
				
			||||||
 | 
					                for face in &mut part.faces {
 | 
				
			||||||
 | 
					                    for fv in &mut [&mut face.a, &mut face.b, &mut face.c] {
 | 
				
			||||||
 | 
					                        fv.vertex += vertex_offset;
 | 
				
			||||||
 | 
					                        if let Some(tex_coord) = fv.texture_coordinate {
 | 
				
			||||||
 | 
					                            fv.texture_coordinate = Some(tex_coord + tex_coord_offset);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if let Some(normal) = fv.normal {
 | 
				
			||||||
 | 
					                            fv.normal = Some(normal + normal_offset);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if let Some(id) = face.id {
 | 
				
			||||||
 | 
					                        face.id = Some(id + face_offset);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    face.material_name = new_part.material_name.clone();
 | 
				
			||||||
 | 
					                    new_part.faces.push(face.clone());
 | 
				
			||||||
 | 
					                    new_faces.push(face);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for face in new_faces {
 | 
				
			||||||
 | 
					                self.faces.push(face.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a model from a file.
 | 
					    /// Creates a model from a file.
 | 
				
			||||||
    pub fn from(path: &str) -> Result<Model, ParserError> {
 | 
					    pub fn from(path: &str) -> Result<Model, ParserError> {
 | 
				
			||||||
        parse(path)
 | 
					        parse_file(path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Computes the area of a 3D face of the model.
 | 
					    /// Computes the area of a 3D face of the model.
 | 
				
			||||||
@ -380,7 +486,7 @@ impl Model {
 | 
				
			|||||||
    /// Creates only non-existant vertex buffers, doesn't update the old ones.
 | 
					    /// Creates only non-existant vertex buffers, doesn't update the old ones.
 | 
				
			||||||
    pub fn build_new_vertex_buffers(&mut self, renderer: &Renderer) {
 | 
					    pub fn build_new_vertex_buffers(&mut self, renderer: &Renderer) {
 | 
				
			||||||
        for part in &mut self.parts {
 | 
					        for part in &mut self.parts {
 | 
				
			||||||
            if part.vertex_buffer.is_none() {
 | 
					            if part.vertex_buffer.is_none() || part.needs_update {
 | 
				
			||||||
                Model::build_vertex_buffer_for_part(
 | 
					                Model::build_vertex_buffer_for_part(
 | 
				
			||||||
                    &self.vertices,
 | 
					                    &self.vertices,
 | 
				
			||||||
                    &self.texture_coordinates,
 | 
					                    &self.texture_coordinates,
 | 
				
			||||||
@ -400,7 +506,7 @@ impl Model {
 | 
				
			|||||||
        renderer: &Renderer) {
 | 
					        renderer: &Renderer) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut vertex_buffer = vec![];
 | 
					        let mut vertex_buffer = vec![];
 | 
				
			||||||
        for face in &part.faces {
 | 
					        for face in part.faces() {
 | 
				
			||||||
            for &&v in &[&face.a, &face.b, &face.c] {
 | 
					            for &&v in &[&face.a, &face.b, &face.c] {
 | 
				
			||||||
                let vertex = vertices[v.vertex].into();
 | 
					                let vertex = vertices[v.vertex].into();
 | 
				
			||||||
                let tex_coord = if let Some(tex_index) = v.texture_coordinate {
 | 
					                let tex_coord = if let Some(tex_index) = v.texture_coordinate {
 | 
				
			||||||
@ -424,6 +530,7 @@ impl Model {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        part.vertex_buffer = Some(renderer.build_vertex_buffer(&vertex_buffer));
 | 
					        part.vertex_buffer = Some(renderer.build_vertex_buffer(&vertex_buffer));
 | 
				
			||||||
 | 
					        part.needs_update = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Builds the textures of all materials.
 | 
					    /// Builds the textures of all materials.
 | 
				
			||||||
@ -438,17 +545,22 @@ impl Model {
 | 
				
			|||||||
        if let Some(path) = material.textures.get("map_Kd") {
 | 
					        if let Some(path) = material.textures.get("map_Kd") {
 | 
				
			||||||
            let texture = renderer.make_texture(path);
 | 
					            let texture = renderer.make_texture(path);
 | 
				
			||||||
            // Don't need to insert multiple times the same texture
 | 
					            // Don't need to insert multiple times the same texture
 | 
				
			||||||
            self.textures.entry(path.to_owned()).or_insert(texture);
 | 
					            self.textures.entry(path.to_owned()).or_insert(Rc::new(texture));
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the rendering texture.
 | 
					    /// Returns the rendering texture.
 | 
				
			||||||
    pub fn get_texture_by_name(&self, name: &str) -> Option<&SrgbTexture2d> {
 | 
					    pub fn get_texture_by_name(&self, name: &str) -> Option<&Rc<SrgbTexture2d>> {
 | 
				
			||||||
        self.textures.get(name)
 | 
					        self.textures.get(name)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the material.
 | 
				
			||||||
 | 
					    pub fn get_material_by_name(&self, name: &str) -> Option<&Material> {
 | 
				
			||||||
 | 
					        self.materials.get(name)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns a ref mut to the table of textures.
 | 
					    /// Returns a ref mut to the table of textures.
 | 
				
			||||||
    pub fn textures_mut(&mut self) -> &mut HashMap<String, SrgbTexture2d> {
 | 
					    pub fn textures_mut(&mut self) -> &mut HashMap<String, Rc<SrgbTexture2d>> {
 | 
				
			||||||
        &mut self.textures
 | 
					        &mut self.textures
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ pub mod mtl;
 | 
				
			|||||||
use std::fmt;
 | 
					use std::fmt;
 | 
				
			||||||
use std::path::{Path, PathBuf};
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::{BufReader, Error};
 | 
					use std::io::{BufReader, Error, Read};
 | 
				
			||||||
use math::vector::{Vector2, Vector3};
 | 
					use math::vector::{Vector2, Vector3};
 | 
				
			||||||
use model::face::Face;
 | 
					use model::face::Face;
 | 
				
			||||||
use model::material::Material;
 | 
					use model::material::Material;
 | 
				
			||||||
@ -112,31 +112,46 @@ pub enum ParserError {
 | 
				
			|||||||
    OtherError(String),
 | 
					    OtherError(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Parses a content from a reader, guess the file type from path, and return the model.
 | 
				
			||||||
 | 
					pub fn parse<R: Read>(reader: R, path: &str) -> Result<Model, ParserError> {
 | 
				
			||||||
 | 
					    let mut model = Model::new();
 | 
				
			||||||
 | 
					    parse_into_model(reader, path, &mut model)?;
 | 
				
			||||||
 | 
					    Ok(model)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Parses a file and append the result to the model passed as parameter.
 | 
				
			||||||
 | 
					pub fn parse_file_into_model(path: &str, model: &mut Model) -> Result<(), ParserError> {
 | 
				
			||||||
 | 
					    let file = match File::open(path) {
 | 
				
			||||||
 | 
					        Ok(file) => file,
 | 
				
			||||||
 | 
					        Err(e) => return Err(ParserError::IoError(path.to_owned(), e)),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let bufreader = BufReader::new(file);
 | 
				
			||||||
 | 
					    parse_into_model(bufreader, path, model)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Detects the format from path name and parses it into the model.
 | 
					/// Detects the format from path name and parses it into the model.
 | 
				
			||||||
pub fn parse_into_model(path: &str, model: &mut Model) -> Result<(), ParserError> {
 | 
					pub fn parse_into_model<R: Read>(reader: R, path: &str, model: &mut Model) -> Result<(), ParserError> {
 | 
				
			||||||
    let extension = Path::new(path).extension().unwrap().to_str().unwrap();
 | 
					    let extension = Path::new(path).extension().unwrap().to_str().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use self::obj::ObjParser;
 | 
					    use self::obj::ObjParser;
 | 
				
			||||||
    use self::mtl::MtlParser;
 | 
					    use self::mtl::MtlParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut parser: Option<Box<Parser>> = match extension {
 | 
					    match extension {
 | 
				
			||||||
        "obj" => Some(Box::new(ObjParser::new())),
 | 
					        "obj" => ObjParser::new().parse_into_model(model, reader, path)?,
 | 
				
			||||||
        "mtl" => Some(Box::new(MtlParser::new())),
 | 
					        "mtl" => MtlParser::new().parse_into_model(model, reader, path)?,
 | 
				
			||||||
        _ => None,
 | 
					        _ => return Err(ParserError::UnknownFormat(path.to_owned())),
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if let Some(parser) = parser.as_mut() {
 | 
					 | 
				
			||||||
        parser.parse_into_model(model, path)?;
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        Err(ParserError::UnknownFormat(path.to_owned()))
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Detects the format from path name and parses it into a new model.
 | 
					/// Detects the format from path name and parses it into a new model.
 | 
				
			||||||
pub fn parse(path: &str) -> Result<Model, ParserError> {
 | 
					pub fn parse_file(path: &str) -> Result<Model, ParserError> {
 | 
				
			||||||
    let mut model = Model::new();
 | 
					    let mut model = Model::new();
 | 
				
			||||||
    parse_into_model(path, &mut model)?;
 | 
					    parse_file_into_model(path, &mut model)?;
 | 
				
			||||||
    Ok(model)
 | 
					    Ok(model)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -171,22 +186,22 @@ impl fmt::Display for ParserError {
 | 
				
			|||||||
pub trait Parser {
 | 
					pub trait Parser {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Parses a file and adds its content into an empty model and returns the model.
 | 
					    /// Parses a file and adds its content into an empty model and returns the model.
 | 
				
			||||||
    fn parse(&mut self, path: &str) -> Result<Model, ParserError> {
 | 
					    fn parse<R: Read>(&mut self, reader: R, path: &str) -> Result<Model, ParserError> {
 | 
				
			||||||
        let mut model = Model::new();
 | 
					        let mut model = Model::new();
 | 
				
			||||||
        self.parse_into_model(&mut model, path)?;
 | 
					        self.parse_into_model(&mut model, reader, path)?;
 | 
				
			||||||
        Ok(model)
 | 
					        Ok(model)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Parses a file and adds its content to an already existing model.
 | 
					    /// Parses a file and adds its content to an already existing model.
 | 
				
			||||||
    fn parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError> {
 | 
					    fn parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError> {
 | 
				
			||||||
        logln!("Parsing {}...", path);
 | 
					        logln!("Parsing {}...", path);
 | 
				
			||||||
        self.priv_parse_into_model(model, path)
 | 
					        self.priv_parse_into_model(model, reader, path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Parses a file and adds its content to an already existing model.
 | 
					    /// Parses a file and adds its content to an already existing model.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// This is the method you should implement for you format parser.
 | 
					    /// This is the method you should implement for you format parser.
 | 
				
			||||||
    fn priv_parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError>;
 | 
					    fn priv_parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Anything that can parse a 3D file line by line.
 | 
					/// Anything that can parse a 3D file line by line.
 | 
				
			||||||
@ -200,16 +215,9 @@ pub trait LineParser {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<LP: LineParser> Parser for LP {
 | 
					impl<LP: LineParser> Parser for LP {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn priv_parse_into_model(&mut self, model: &mut Model, path: &str) -> Result<(), ParserError> {
 | 
					    fn priv_parse_into_model<R: Read>(&mut self, model: &mut Model, reader: R, path: &str) -> Result<(), ParserError> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let file = File::open(path);
 | 
					        let file = BufReader::new(reader);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if file.is_err() {
 | 
					 | 
				
			||||||
            return Err(ParserError::IoError(path.to_owned(), file.err().unwrap()));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let file = file.unwrap();
 | 
					 | 
				
			||||||
        let file = BufReader::new(&file);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut current_material_name = None;
 | 
					        let mut current_material_name = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -218,11 +226,10 @@ impl<LP: LineParser> Parser for LP {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            let num = num + 1;
 | 
					            let num = num + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if line.is_err() {
 | 
					            let line = match line {
 | 
				
			||||||
                return Err(ParserError::OtherError(path.to_owned()));
 | 
					                Ok(x) => x,
 | 
				
			||||||
            }
 | 
					                Err(e) => return Err(ParserError::IoError(path.to_owned(), e)),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
            let line = line.unwrap();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let element = self.parse_line(num, &line, &path)?;
 | 
					            let element = self.parse_line(num, &line, &path)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -238,7 +245,7 @@ impl<LP: LineParser> Parser for LP {
 | 
				
			|||||||
                    let mut path = PathBuf::from(path);
 | 
					                    let mut path = PathBuf::from(path);
 | 
				
			||||||
                    path.pop();
 | 
					                    path.pop();
 | 
				
			||||||
                    path.push(material_path);
 | 
					                    path.push(material_path);
 | 
				
			||||||
                    if let Err(err) = parse_into_model(path.to_str().unwrap(), model) {
 | 
					                    if let Err(err) = parse_file_into_model(path.to_str().unwrap(), model) {
 | 
				
			||||||
                        return Err(err);
 | 
					                        return Err(err);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ use glium::glutin::VirtualKeyCode;
 | 
				
			|||||||
use model_converter::scene::Scene;
 | 
					use model_converter::scene::Scene;
 | 
				
			||||||
use model_converter::math::bounding_box::BoundingBox3;
 | 
					use model_converter::math::bounding_box::BoundingBox3;
 | 
				
			||||||
use model_converter::math::vector::Vector3;
 | 
					use model_converter::math::vector::Vector3;
 | 
				
			||||||
use model_converter::parser::parse;
 | 
					use model_converter::parser::parse_file;
 | 
				
			||||||
use model_converter::renderer::Renderer;
 | 
					use model_converter::renderer::Renderer;
 | 
				
			||||||
use model_converter::controls::{OrbitControls, FirstPersonControls};
 | 
					use model_converter::controls::{OrbitControls, FirstPersonControls};
 | 
				
			||||||
use model_converter::camera::Camera;
 | 
					use model_converter::camera::Camera;
 | 
				
			||||||
@ -65,7 +65,7 @@ fn main() {
 | 
				
			|||||||
    let mut models = vec![];
 | 
					    let mut models = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for input in matches.values_of("input").unwrap() {
 | 
					    for input in matches.values_of("input").unwrap() {
 | 
				
			||||||
        match parse(&input) {
 | 
					        match parse_file(&input) {
 | 
				
			||||||
            Ok(model) => {
 | 
					            Ok(model) => {
 | 
				
			||||||
                if model.vertices.len() > 0 {
 | 
					                if model.vertices.len() > 0 {
 | 
				
			||||||
                    bbox = bbox.union(&model.bounding_box());
 | 
					                    bbox = bbox.union(&model.bounding_box());
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
//! This module contains everything related to scenes.
 | 
					//! This module contains everything related to scenes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::slice::Iter;
 | 
					use std::slice::{Iter, IterMut};
 | 
				
			||||||
use std::vec::IntoIter;
 | 
					use std::vec::IntoIter;
 | 
				
			||||||
use std::rc::Rc;
 | 
					use std::rc::Rc;
 | 
				
			||||||
use std::cell::RefCell;
 | 
					use std::cell::RefCell;
 | 
				
			||||||
@ -33,6 +33,11 @@ impl Scene {
 | 
				
			|||||||
    pub fn iter(&self) -> Iter<Rc<RefCell<Model>>> {
 | 
					    pub fn iter(&self) -> Iter<Rc<RefCell<Model>>> {
 | 
				
			||||||
        self.models.iter()
 | 
					        self.models.iter()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a mutable iterator to the model of the scene.
 | 
				
			||||||
 | 
					    pub fn iter_mut(&mut self) -> IterMut<Rc<RefCell<Model>>> {
 | 
				
			||||||
 | 
					        self.models.iter_mut()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl IntoIterator for Scene {
 | 
					impl IntoIterator for Scene {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user