Renderer/src/obj.rs
2022-07-15 00:08:51 +02:00

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(())
}
}