refraction/src/mesh_loader.rs
2024-03-25 19:00:04 +03:00

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