use super::{Point3, Vec3}; use std::fs::File; use std::io::{self, prelude::*, BufReader}; pub struct Face { aNormal: Vec3, bNormal: Vec3, cNormal: Vec3, aTexture: Point3, bTexture: Point3, cTexture: Point3, a: Point3, b: Point3, c: Point3, onlyPoints: boolean, } pub struct Obj { vertexes: Vec, textures: Vec, normals: Vec, faces: Vec, } impl Obj { pub fn fromFile(&self, path: String) -> Self { let file = File::open(path)?; let reader = BufReader::new(file); for line in reader.lines() { let split = line.split_whitespace(); match split[0] { // vertexes "v" => { if split.len() != 4 { continue }; self.vertexes.push(Point3::new( split[1].parse::(), split[2].parse::(), split[3].parse::() )); // can throw ParseFloatError }, // textures "vt" => { if split.len() < 2 { continue }; normals.push(Point3::new( split[1].parse::(), if split.len() >= 3 { split[2].parse::() } else { 0.0 }, if split.len() >= 4 { split[3].parse::() } else { 0.0 }, )); // can throw ParseFloatError }, // normals "vn" => { if split.len() != 4 { continue }; normals.push(Vec3::new( split[1].parse::(), split[2].parse::(), split[3].parse::() )); // can throw ParseFloatError }, // faces "f" => { if split.len() != 4 { continue }; if split[1].contains("/") { // format 'f 1/4/6 2/7/8 3/7/8' let a = split[1].split("/"); let b = split[2].split("/"); let c = split[3].split("/"); faces.push( Face { aNormal: if a[1] != "" { normals[a[1].parse::()] } else { Vec3::empty() }, bNormal: if b[1] != "" { normals[b[1].parse::()] } else { Vec3::empty() }, cNormal: if c[1] != "" { normals[c[1].parse::()] } else { Vec3::empty() }, aTexture: if a[2] != "" { textures[a[1].parse::()] } else { Point3::empty() } } ) } else { // format 'f 1 2 3' faces.push(Point3::new( split[1].parse::(), split[2].parse::(), split[3].parse::() )); } // can throw ParseFloatError } } } Ok(()) } }