1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use super::*;

#[derive(ugli::Vertex, Debug, Copy, Clone)]
pub struct Vertex {
    pub a_v: Vec3<f32>,
    pub a_vt: Vec2<f32>,
    pub a_vn: Vec3<f32>,
}

pub fn parse(source: &str) -> HashMap<String, Vec<Vertex>> {
    let mut result = HashMap::new();

    let mut current_name = String::from("__unnamed__");

    let mut v = Vec::new();
    let mut vn = Vec::new();
    let mut vt = Vec::new();
    let mut current_obj = Vec::new();
    for line in source.lines().chain(std::iter::once("o _")) {
        if line.starts_with("v ") {
            let mut parts = line.split_whitespace();
            parts.next();
            let x: f32 = parts.next().unwrap().parse().unwrap();
            let y: f32 = parts.next().unwrap().parse().unwrap();
            let z: f32 = parts.next().unwrap().parse().unwrap();
            v.push(vec3(x, y, z));
        } else if line.starts_with("vn ") {
            let mut parts = line.split_whitespace();
            parts.next();
            let x: f32 = parts.next().unwrap().parse().unwrap();
            let y: f32 = parts.next().unwrap().parse().unwrap();
            let z: f32 = parts.next().unwrap().parse().unwrap();
            vn.push(vec3(x, y, z));
        } else if line.starts_with("vt ") {
            let mut parts = line.split_whitespace();
            parts.next();
            let x: f32 = parts.next().unwrap().parse().unwrap();
            let y: f32 = parts.next().unwrap().parse().unwrap();
            vt.push(vec2(x, y));
        } else if line.starts_with("f ") {
            let mut parts = line.split_whitespace();
            parts.next();
            let to_vertex = |s: &str| {
                let mut parts = s.split("/");
                let i_v: usize = parts.next().unwrap().parse().unwrap();
                let i_vt: usize = parts.next().unwrap().parse().unwrap();
                let i_vn: usize = parts.next().unwrap().parse().unwrap();
                Vertex {
                    a_v: v[i_v - 1],
                    a_vn: vn[i_vn - 1],
                    a_vt: vt[i_vt - 1],
                }
            };
            let mut cur = Vec::new();
            while let Some(s) = parts.next() {
                cur.push(to_vertex(s));
            }
            for i in 2..cur.len() {
                current_obj.push(cur[0]);
                current_obj.push(cur[i - 1]);
                current_obj.push(cur[i]);
            }
        } else if line.starts_with("o ") || line.starts_with("g ") {
            if current_obj.len() != 0 {
                result.insert(current_name.clone(), current_obj);
                current_obj = Vec::new();
            }
            current_name = String::from(&line[2..]);
        }
    }
    result
}

pub fn recalculate_normals(data: &mut [Vertex]) {
    for face in data.chunks_mut(3) {
        let n = Vec3::cross(face[1].a_v - face[0].a_v, face[2].a_v - face[0].a_v).normalize();
        for v in face {
            v.a_vn = n;
        }
    }
}

pub fn unitize<'a, I: Iterator<Item = &'a mut [Vertex]>>(iter: I) {
    let vss: Vec<&'a mut [Vertex]> = iter.collect();
    const INF: f32 = 1e9;
    let mut min_x: f32 = INF;
    let mut max_x: f32 = -INF;
    let mut min_y: f32 = INF;
    let mut max_y: f32 = -INF;
    for vs in &vss {
        for v in vs.iter() {
            let x = v.a_v.x;
            let y = v.a_v.y;
            min_x = min_x.min(x);
            max_x = max_x.max(x);
            min_y = min_y.min(y);
            max_y = max_y.max(y);
        }
    }
    let center = vec3(min_x + max_x, min_y + max_y, 0.0) / 2.0;
    let div = (max_y - min_y).max(max_x - min_x) / 2.0;
    for vs in vss {
        for v in vs.iter_mut() {
            v.a_v = (v.a_v - center) / div;
        }
    }
}

pub fn scale(data: &mut [Vertex], k: f32) {
    for v in data {
        v.a_v *= k;
    }
}

pub fn united(data: HashMap<String, Vec<Vertex>>) -> Vec<Vertex> {
    let mut result = Vec::new();
    for part in data.values() {
        result.extend(part);
    }
    result
}