/// This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
/// a new material for each triangle primitive in the object model.
This is limited to only CookTorranceMaterials, as I couldn't get a Box to clone
a new material for each triangle primitive in the object model.
This is limited to only CookTorranceMaterials as I couldn ' t get a Box to clone a new material for each triangle primitive in the object model .
pub fn from_obj(material: CookTorranceMaterial, flip_normals: bool, filename: &str) -> Result<Mesh, String> {
    let file_handle = match File::open(&filename) {
        Ok(f) => f,
        Err(err) => return Err(format!("{}", err))
    };
    let total_bytes = match file_handle.metadata() {
        Ok(metadata) => metadata.len(),
        Err(err) => return Err(format!("{}", err))
    };
    let file = BufReader::new(file_handle);
    let start_time = ::time::get_time();
    let print_every = 2048;
    let mut processed_bytes = 0;
    let mut vertices: Vec<Vec3> = Vec::new();
    let mut normals : Vec<Vec3> = Vec::new();
    let mut triangles: Vec<Box<Prim+Send+Sync>> = Vec::new();
    let mut tex_coords: Vec<Vec<f64>> = Vec::new();
    let mut current_line = 0;
    let normal_scale = if flip_normals { -1.0 } else { 1.0 };
    for line_res in file.lines() {
        let line = line_res.unwrap();
        let tokens: Vec<&str> = line[..].split_whitespace().collect();
        if tokens.is_empty() {
            continue;
        }
        match tokens[0] {
            "v" => {
                vertices.push(Vec3 {
                    x: tokens[1].parse().unwrap(),
                    y: tokens[2].parse().unwrap(),
                    z: tokens[3].parse().unwrap()
                });
            },
            "vt" => {
                tex_coords.push(vec![
                    tokens[1].parse().unwrap(),
                    tokens[2].parse().unwrap()
                ]);
            },
            "vn" => {
                normals.push(Vec3 {
                    x: tokens[1].parse::<f64>().unwrap() * normal_scale,
                    y: tokens[2].parse::<f64>().unwrap() * normal_scale,
                    z: tokens[3].parse::<f64>().unwrap() * normal_scale
                });
            },
            "f" => {
                // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]]
                let tail = match tokens.split_first() {
                    Some((_, tail)) => tail,
                    None => return Err("Face syntax of OBJ not supported or malformed".to_owned())
                };
                let pairs: Vec<Vec<usize>> = tail.iter().map( |token| {
                    let str_tokens: Vec<&str> = token.split('/').collect();
                    str_tokens.iter().map( |str_tok| {
                        match str_tok.parse::<usize>().ok() {
                            Some(usize_tok) => usize_tok - 1, // Have to offset as OBJ is 1-indexed
                            None => !0 // No data available/not supplied (eg. `//` as a token)
                        }
                    }).collect()
                }).collect();
                // If no texture coordinates were supplied, default to zero.
                // We stored nothing supplied as !0
                let (u, v) = if pairs[0][1] != !0 {
                    (vec![
                        tex_coords[pairs[0][1]][0],
                        tex_coords[pairs[1][1]][0],
                        tex_coords[pairs[2][1]][0]
                    ],
                    vec![
                        tex_coords[pairs[0][1]][1],
                        tex_coords[pairs[1][1]][1],
                        tex_coords[pairs[2][1]][1]
                    ])
                } else {
                    (vec![0.0, 0.0, 0.0],
                     vec![0.0, 0.0, 0.0])
                };
                let mut triopts = TriangleOptions::new(
                    vertices[pairs[0][0]],
                    vertices[pairs[1][0]],
                    vertices[pairs[2][0]]);
                triopts.material(Box::new(material.clone()));
                triopts.normals([
                    normals[pairs[0][2]],
                    normals[pairs[1][2]],
                    normals[pairs[2][2]],
                ]);
                triopts.texinfo([(u[0], v[0]), (u[1], v[1]), (u[2], v[2])]);
                triangles.push(Box::new(triopts.build()));
            },
            _ => {}
        }
        current_line += 1;
        processed_bytes += line.as_bytes().len();
        if current_line % print_every == 0 {
            ::util::print_progress("Bytes", start_time, processed_bytes, total_bytes as usize);
        }
    }
    // Cheat the progress meter
    ::util::print_progress("Bytes", start_time, total_bytes as usize, total_bytes as usize);
    Ok(Mesh { triangles: triangles })
}
pub fn from_obj ( material : CookTorranceMaterial , flip_normals : bool , filename : & str ) -> Result < Mesh , String > { let file_handle = match File :: open ( & filename ) { Ok ( f ) => f , Err ( err ) => return Err ( format ! ( " " err ) ) } ; let total_bytes = match file_handle . metadata ( ) { Ok ( metadata ) => metadata . len ( ) , Err ( err ) => return Err ( format ! ( " " err ) ) } ; let file = BufReader :: new ( file_handle ) ; let start_time = :: time :: get_time ( ) ; let print_every = 2048 ; let mut processed_bytes = 0 ; let mut vertices : Vec < Vec3 > = Vec :: new ( ) ; let mut normals : Vec < Vec3 > = Vec :: new ( ) ; let mut triangles : Vec < Box < Prim + Send + Sync > > = Vec :: new ( ) ; let mut tex_coords : Vec < Vec < f64 > > = Vec :: new ( ) ; let mut current_line = 0 ; let normal_scale = if flip_normals { - 1.0 } else { 1.0 } ; for line_res in file . lines ( ) { let line = line_res . unwrap ( ) ; let tokens : Vec < & str > = line [ .. ] . split_whitespace ( ) . collect ( ) ; if tokens . is_empty ( ) { continue ; } match tokens [ 0 ] { " " => { vertices . push ( Vec3 { x : tokens [ 1 ] . parse ( ) . unwrap ( ) , y : tokens [ 2 ] . parse ( ) . unwrap ( ) , z : tokens [ 3 ] . parse ( ) . unwrap ( ) } ) ; } , " " => { tex_coords . push ( vec ! [ tokens [ 1 ] parse ( ) unwrap ( ) tokens [ 2 ] parse ( ) unwrap ( ) ] ) ; } , " " => { normals . push ( Vec3 { x : tokens [ 1 ] . parse :: < f64 > ( ) . unwrap ( ) * normal_scale , y : tokens [ 2 ] . parse :: < f64 > ( ) . unwrap ( ) * normal_scale , z : tokens [ 3 ] . parse :: < f64 > ( ) . unwrap ( ) * normal_scale } ) ; } , " " => { // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]] let tail = match tokens . split_first ( ) { Some ( ( _ , tail ) ) => tail , None => return Err ( " " . to_owned ( ) ) } ; let pairs : Vec < Vec < usize > > = tail . iter ( ) . map ( | token | { let str_tokens : Vec < & str > = token . split ( '/' ) . collect ( ) ; str_tokens . iter ( ) . map ( | str_tok | { match str_tok . parse :: < usize > ( ) . ok ( ) { Some ( usize_tok ) => usize_tok - 1 , // Have to offset as OBJ is 1-indexed None => ! 0 // No data available/not supplied (eg. `//` as a token) } } ) . collect ( ) } ) . collect ( ) ; // If no texture coordinates were supplied, default to zero. // We stored nothing supplied as !0 let ( u , v ) = if pairs [ 0 ] [ 1 ] != ! 0 { ( vec ! [ tex_coords [ pairs [ 0 ] [ 1 ] ] [ 0 ] tex_coords [ pairs [ 1 ] [ 1 ] ] [ 0 ] tex_coords [ pairs [ 2 ] [ 1 ] ] [ 0 ] ] , vec ! [ tex_coords [ pairs [ 0 ] [ 1 ] ] [ 1 ] tex_coords [ pairs [ 1 ] [ 1 ] ] [ 1 ] tex_coords [ pairs [ 2 ] [ 1 ] ] [ 1 ] ] ) } else { ( vec ! [ 0.0 0.0 0.0 ] , vec ! [ 0.0 0.0 0.0 ] ) } ; let mut triopts = TriangleOptions :: new ( vertices [ pairs [ 0 ] [ 0 ] ] , vertices [ pairs [ 1 ] [ 0 ] ] , vertices [ pairs [ 2 ] [ 0 ] ] ) ; triopts . material ( Box :: new ( material . clone ( ) ) ) ; triopts . normals ( [ normals [ pairs [ 0 ] [ 2 ] ] , normals [ pairs [ 1 ] [ 2 ] ] , normals [ pairs [ 2 ] [ 2 ] ] , ] ) ; triopts . texinfo ( [ ( u [ 0 ] , v [ 0 ] ) , ( u [ 1 ] , v [ 1 ] ) , ( u [ 2 ] , v [ 2 ] ) ] ) ; triangles . push ( Box :: new ( triopts . build ( ) ) ) ; } , _ => { } } current_line += 1 ; processed_bytes += line . as_bytes ( ) . len ( ) ; if current_line % print_every == 0 { :: util :: print_progress ( " " , start_time , processed_bytes , total_bytes as usize ) ; } } // Cheat the progress meter :: util :: print_progress ( " " , start_time , total_bytes as usize , total_bytes as usize ) ; Ok ( Mesh { triangles : triangles } ) }
This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
a new material for each triangle primitive in the object model.
This is limited to only CookTorranceMaterials as I couldn ' t get a Box<Material > to clone a new material for each triangle primitive in the object model .
material
CookTorranceMaterial
flip_normals
bool
filename
&str