Extract the mesh loader

This commit is contained in:
numzero 2024-03-25 19:00:04 +03:00
parent 2ec43c822d
commit af5322a47e
2 changed files with 100 additions and 92 deletions

View File

@ -1,3 +1,5 @@
mod mesh_loader;
use std::fs::File;
use std::{env, io};
use std::f32::consts::PI;
@ -6,96 +8,7 @@ use std::io::Write;
use rand::Rng;
use glm;
use glm::{dot, ivec2, IVec2, ivec3, to_ivec3, vec2, 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();
glm::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 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)]
struct Face {
vertices: [Vec3; 3],
normal: Vec3,
}
use crate::mesh_loader::load_mesh;
const W: i32 = 800;
const H: i32 = 600;
@ -171,8 +84,7 @@ fn main() -> io::Result<()> {
let mesh = {
let f = File::open(&args[1])?;
let mut f = BufReader::new(f);
ObjMesh::read(&mut f)?
.flatten()
load_mesh(&mut f)?
};
let mut img = Image {
w: W,

96
src/mesh_loader.rs Normal file
View File

@ -0,0 +1,96 @@
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())
}