Skip to main content

conspire/geometry/mesh/tessellation/read/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::{
5    geometry::{
6        Coordinate, Coordinates,
7        mesh::{
8            Connectivity,
9            tessellation::{D, Tessellation},
10        },
11    },
12    math::TensorVec,
13};
14use std::{
15    cell::OnceCell,
16    collections::HashMap,
17    fs::File,
18    io::{BufReader, Error as ErrorIO, Read},
19    path::Path,
20};
21
22impl TryFrom<&Path> for Tessellation {
23    type Error = ErrorIO;
24    fn try_from(path: &Path) -> Result<Self, Self::Error> {
25        let mut reader = BufReader::new(File::open(path)?);
26        let mut header = [0u8; 80];
27        reader.read_exact(&mut header)?;
28        let mut count_bytes = [0u8; 4];
29        reader.read_exact(&mut count_bytes)?;
30        let triangle_count = u32::from_le_bytes(count_bytes) as usize;
31        let mut connectivity = Vec::with_capacity(triangle_count);
32        let mut normals = Coordinates::with_capacity(triangle_count);
33        let mut vertex_map = HashMap::with_capacity(D * triangle_count);
34        let mut unique_vertices_f32 = Vec::with_capacity(D * triangle_count);
35        (0..triangle_count).try_for_each(|_| {
36            let normal_f32 = read_vec3_f32(&mut reader)?;
37            let v0 = read_vec3_f32(&mut reader)?;
38            let v1 = read_vec3_f32(&mut reader)?;
39            let v2 = read_vec3_f32(&mut reader)?;
40            let mut attr = [0u8; 2];
41            reader.read_exact(&mut attr)?;
42            let _attribute_byte_count = u16::from_le_bytes(attr);
43            let i0 = dedup_vertex(&mut vertex_map, &mut unique_vertices_f32, v0);
44            let i1 = dedup_vertex(&mut vertex_map, &mut unique_vertices_f32, v1);
45            let i2 = dedup_vertex(&mut vertex_map, &mut unique_vertices_f32, v2);
46            connectivity.push([i0, i1, i2]);
47            normals.push(Coordinate::const_from([
48                normal_f32[0] as f64,
49                normal_f32[1] as f64,
50                normal_f32[2] as f64,
51            ]));
52            Ok::<(), ErrorIO>(())
53        })?;
54        let coordinates: Coordinates<D> = unique_vertices_f32
55            .into_iter()
56            .map(|v| Coordinate::const_from([v[0] as f64, v[1] as f64, v[2] as f64]))
57            .collect();
58        let connectivity = vec![Connectivity::Triangular(connectivity.into())];
59        let mesh = (connectivity, coordinates).into();
60        let normals = vec![normals].into();
61        Ok(Tessellation {
62            mesh,
63            normals,
64            bvh: OnceCell::new(),
65        })
66    }
67}
68
69fn read_vec3_f32<R: Read>(reader: &mut R) -> Result<[f32; D], ErrorIO> {
70    Ok([read_f32(reader)?, read_f32(reader)?, read_f32(reader)?])
71}
72
73fn read_f32<R: Read>(reader: &mut R) -> Result<f32, ErrorIO> {
74    let mut bytes = [0u8; 4];
75    reader.read_exact(&mut bytes)?;
76    Ok(f32::from_le_bytes(bytes))
77}
78
79fn dedup_vertex(
80    vertex_map: &mut HashMap<[u32; D], usize>,
81    unique_vertices: &mut Vec<[f32; D]>,
82    vertex: [f32; D],
83) -> usize {
84    let key = [
85        vertex[0].to_bits(),
86        vertex[1].to_bits(),
87        vertex[2].to_bits(),
88    ];
89    if let Some(&index) = vertex_map.get(&key) {
90        index
91    } else {
92        let index = unique_vertices.len();
93        unique_vertices.push(vertex);
94        vertex_map.insert(key, index);
95        index
96    }
97}