97 lines
2.2 KiB
Rust
97 lines
2.2 KiB
Rust
use std::io;
|
|
use glm::{vec2, vec3, Vec2, Vec3};
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
struct ObjVertex {
|
|
vertex: usize,
|
|
normal: usize,
|
|
tex_coord: usize,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
struct ObjFace {
|
|
vertices: [ObjVertex; 3],
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct ObjMesh {
|
|
vertices: Vec<Vec3>,
|
|
normals: Vec<Vec3>,
|
|
tex_coords: Vec<Vec2>,
|
|
faces: Vec<ObjFace>,
|
|
}
|
|
|
|
impl ObjMesh {
|
|
fn parse_v2(tokens: &[&str]) -> Vec2 {
|
|
assert_eq!(tokens.len(), 2);
|
|
let tokens: Vec<_> = tokens.iter().map(|&t| t.parse().unwrap()).collect();
|
|
vec2(tokens[0], tokens[1])
|
|
}
|
|
|
|
fn parse_v3(tokens: &[&str]) -> Vec3 {
|
|
assert_eq!(tokens.len(), 3);
|
|
let tokens: Vec<_> = tokens.iter().map(|&t| t.parse().unwrap()).collect();
|
|
vec3(tokens[0], tokens[1], tokens[2])
|
|
}
|
|
|
|
fn parse_fv(desc: &&str) -> ObjVertex {
|
|
let tokens: Vec<_> = desc.split('/').map(|s| s.parse::<usize>().unwrap() - 1).collect();
|
|
assert_eq!(tokens.len(), 3);
|
|
ObjVertex { vertex: tokens[0], tex_coord: tokens[1], normal: tokens[2] }
|
|
}
|
|
|
|
fn parse_f(tokens: &[&str]) -> ObjFace {
|
|
let vertices: Vec<_> = tokens.iter().map(ObjMesh::parse_fv).collect();
|
|
ObjFace { vertices: vertices.as_slice().try_into().unwrap() }
|
|
}
|
|
|
|
fn read(f: &mut impl io::BufRead) -> io::Result<ObjMesh> {
|
|
let mut result = ObjMesh {
|
|
vertices: Vec::new(),
|
|
normals: Vec::new(),
|
|
tex_coords: Vec::new(),
|
|
faces: Vec::new(),
|
|
};
|
|
loop {
|
|
let mut line = String::new();
|
|
if f.read_line(&mut line)? == 0 {
|
|
break;
|
|
}
|
|
let tokens: Vec<&str> = line
|
|
.trim()
|
|
.split('#')
|
|
.next()
|
|
.unwrap()
|
|
.split(' ')
|
|
.collect();
|
|
match tokens[0] {
|
|
"v" => result.vertices.push(Self::parse_v3(&tokens[1..])),
|
|
"vn" => result.normals.push(Self::parse_v3(&tokens[1..])),
|
|
"vt" => result.tex_coords.push(Self::parse_v2(&tokens[1..])),
|
|
"f" => result.faces.push(Self::parse_f(&tokens[1..])),
|
|
_ => (),
|
|
}
|
|
}
|
|
Ok(result)
|
|
}
|
|
|
|
fn flatten(&self) -> Vec<Face> {
|
|
self.faces.iter().map(|face| {
|
|
Face {
|
|
vertices: face.vertices.map(|iv| self.vertices[iv.vertex]),
|
|
normal: self.normals[face.vertices[0].normal],
|
|
}
|
|
}).collect()
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct Face {
|
|
pub vertices: [Vec3; 3],
|
|
pub normal: Vec3,
|
|
}
|
|
|
|
pub fn load_mesh(f: &mut impl io::BufRead) -> io::Result<Vec<Face>> {
|
|
Ok(ObjMesh::read(f)?.flatten())
|
|
}
|