95 lines
No EOL
3.2 KiB
Rust
95 lines
No EOL
3.2 KiB
Rust
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<Point3>,
|
|
textures: Vec<Point3>,
|
|
normals: Vec<Vec3>,
|
|
faces: Vec<Face>,
|
|
}
|
|
|
|
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::<f64>(),
|
|
split[2].parse::<f64>(),
|
|
split[3].parse::<f64>()
|
|
));
|
|
// can throw ParseFloatError
|
|
},
|
|
// textures
|
|
"vt" => {
|
|
if split.len() < 2 { continue };
|
|
normals.push(Point3::new(
|
|
split[1].parse::<f64>(),
|
|
if split.len() >= 3 { split[2].parse::<f64>() } else { 0.0 },
|
|
if split.len() >= 4 { split[3].parse::<f64>() } else { 0.0 },
|
|
));
|
|
// can throw ParseFloatError
|
|
},
|
|
// normals
|
|
"vn" => {
|
|
if split.len() != 4 { continue };
|
|
normals.push(Vec3::new(
|
|
split[1].parse::<f64>(),
|
|
split[2].parse::<f64>(),
|
|
split[3].parse::<f64>()
|
|
));
|
|
// 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::<u64>()] } else { Vec3::empty() },
|
|
bNormal: if b[1] != "" { normals[b[1].parse::<u64>()] } else { Vec3::empty() },
|
|
cNormal: if c[1] != "" { normals[c[1].parse::<u64>()] } else { Vec3::empty() },
|
|
aTexture: if a[2] != "" { textures[a[1].parse::<u64>()] } else { Point3::empty() }
|
|
}
|
|
)
|
|
} else { // format 'f 1 2 3'
|
|
faces.push(Point3::new(
|
|
split[1].parse::<f64>(),
|
|
split[2].parse::<f64>(),
|
|
split[3].parse::<f64>()
|
|
));
|
|
}
|
|
|
|
// can throw ParseFloatError
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
} |