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}