geng_obj/
lib.rs

1use batbox_la::*;
2use std::collections::HashMap;
3
4#[derive(ugli::Vertex, Debug, Copy, Clone)]
5pub struct Vertex {
6    pub a_v: vec3<f32>,
7    pub a_vt: vec2<f32>,
8    pub a_vn: vec3<f32>,
9}
10
11pub fn parse(source: &str) -> HashMap<String, Vec<Vertex>> {
12    let mut result = HashMap::new();
13
14    let mut current_name = String::from("__unnamed__");
15
16    let mut v = Vec::new();
17    let mut vn = Vec::new();
18    let mut vt = Vec::new();
19    let mut current_obj = Vec::new();
20    for line in source.lines().chain(std::iter::once("o _")) {
21        if line.starts_with("v ") {
22            let mut parts = line.split_whitespace();
23            parts.next();
24            let x: f32 = parts.next().unwrap().parse().unwrap();
25            let y: f32 = parts.next().unwrap().parse().unwrap();
26            let z: f32 = parts.next().unwrap().parse().unwrap();
27            v.push(vec3(x, y, z));
28        } else if line.starts_with("vn ") {
29            let mut parts = line.split_whitespace();
30            parts.next();
31            let x: f32 = parts.next().unwrap().parse().unwrap();
32            let y: f32 = parts.next().unwrap().parse().unwrap();
33            let z: f32 = parts.next().unwrap().parse().unwrap();
34            vn.push(vec3(x, y, z));
35        } else if line.starts_with("vt ") {
36            let mut parts = line.split_whitespace();
37            parts.next();
38            let x: f32 = parts.next().unwrap().parse().unwrap();
39            let y: f32 = parts.next().unwrap().parse().unwrap();
40            vt.push(vec2(x, y));
41        } else if line.starts_with("f ") {
42            let mut parts = line.split_whitespace();
43            parts.next();
44            let to_vertex = |s: &str| {
45                let mut parts = s.split('/');
46                let i_v: usize = parts.next().unwrap().parse().unwrap();
47                let i_vt: usize = parts.next().unwrap().parse().unwrap();
48                let i_vn: usize = parts.next().unwrap().parse().unwrap();
49                Vertex {
50                    a_v: v[i_v - 1],
51                    a_vn: vn[i_vn - 1],
52                    a_vt: vt[i_vt - 1],
53                }
54            };
55            let mut cur = Vec::new();
56            for s in parts {
57                cur.push(to_vertex(s));
58            }
59            for i in 2..cur.len() {
60                current_obj.push(cur[0]);
61                current_obj.push(cur[i - 1]);
62                current_obj.push(cur[i]);
63            }
64        } else if line.starts_with("o ") || line.starts_with("g ") {
65            if !current_obj.is_empty() {
66                result.insert(current_name.clone(), current_obj);
67                current_obj = Vec::new();
68            }
69            current_name = String::from(&line[2..]);
70        }
71    }
72    result
73}
74
75pub fn recalculate_normals(data: &mut [Vertex]) {
76    for face in data.chunks_mut(3) {
77        let n = vec3::cross(face[1].a_v - face[0].a_v, face[2].a_v - face[0].a_v).normalize();
78        for v in face {
79            v.a_vn = n;
80        }
81    }
82}
83
84pub fn unitize<'a, I: Iterator<Item = &'a mut [Vertex]>>(iter: I) {
85    let vss: Vec<&'a mut [Vertex]> = iter.collect();
86    const INF: f32 = 1e9;
87    let mut min_x: f32 = INF;
88    let mut max_x: f32 = -INF;
89    let mut min_y: f32 = INF;
90    let mut max_y: f32 = -INF;
91    for vs in &vss {
92        for v in vs.iter() {
93            let x = v.a_v.x;
94            let y = v.a_v.y;
95            min_x = min_x.min(x);
96            max_x = max_x.max(x);
97            min_y = min_y.min(y);
98            max_y = max_y.max(y);
99        }
100    }
101    let center = vec3(min_x + max_x, min_y + max_y, 0.0) / 2.0;
102    let div = (max_y - min_y).max(max_x - min_x) / 2.0;
103    for vs in vss {
104        for v in vs.iter_mut() {
105            v.a_v = (v.a_v - center) / div;
106        }
107    }
108}
109
110pub fn scale(data: &mut [Vertex], k: f32) {
111    for v in data {
112        v.a_v *= k;
113    }
114}
115
116pub fn united(data: HashMap<String, Vec<Vertex>>) -> Vec<Vertex> {
117    let mut result = Vec::new();
118    for part in data.values() {
119        result.extend(part);
120    }
121    result
122}