falcon_library/model3d/
off.rs1use super::{Mesh, Model, ParseError, Result};
10
11pub fn parse(bytes: &[u8]) -> Result<Model> {
12 let text = std::str::from_utf8(bytes).map_err(|_| ParseError("OFF is not text".into()))?;
13 let mut lines = text.lines().map(|l| l.split('#').next().unwrap_or("").trim()).filter(|l| !l.is_empty());
14 let bad = |what: &str| ParseError(format!("OFF: {what}"));
15 if lines.next() != Some("OFF") {
16 return Err(bad("missing OFF header"));
17 }
18 let counts: Vec<usize> = lines.next().ok_or_else(|| bad("missing counts"))?.split_whitespace().map_while(|t| t.parse().ok()).collect();
19 let (&nv, &nf) = (counts.first().ok_or_else(|| bad("bad counts"))?, counts.get(1).ok_or_else(|| bad("bad counts"))?);
20 let mut mesh = Mesh::default();
21 for _ in 0..nv {
22 let line = lines.next().ok_or_else(|| bad("too few vertices"))?;
23 let v: Vec<f32> = line.split_whitespace().take(3).map_while(|t| t.parse().ok()).collect();
24 let [x, y, z] = v[..] else { return Err(bad("bad vertex")) };
25 mesh.positions.push([x, y, z]);
26 }
27 for _ in 0..nf {
28 let line = lines.next().ok_or_else(|| bad("too few faces"))?;
29 let mut t = line.split_whitespace();
30 let n: usize = t.next().and_then(|s| s.parse().ok()).ok_or_else(|| bad("bad face"))?;
31 let ix: Vec<u32> = t.take(n).map_while(|s| s.parse().ok()).collect();
32 if ix.len() != n {
33 return Err(bad("bad face"));
34 }
35 for k in 1..n.saturating_sub(1) {
36 mesh.indices.extend([ix[0], ix[k], ix[k + 1]]);
37 }
38 }
39 Model { meshes: vec![mesh] }.finish()
40}