1use crate::{
3 binary::{Error, Result},
4 records::Record,
5};
6use serde_json::Value;
7
8#[derive(Debug, Clone, PartialEq)]
10pub struct MeshGeometry {
11 pub vertices: Vec<f32>,
13 pub indices: Vec<u32>,
15}
16fn error() -> Error {
17 Error {
18 offset: 0,
19 message: "Invalid derived mesh geometry".into(),
20 }
21}
22fn numbers(record: &Record, name: &str) -> Result<Vec<u32>> {
23 record
24 .get(name)
25 .and_then(Value::as_array)
26 .ok_or_else(error)?
27 .iter()
28 .map(|value| {
29 value
30 .as_u64()
31 .and_then(|number| u32::try_from(number).ok())
32 .ok_or_else(error)
33 })
34 .collect()
35}
36pub fn mesh_geometry(record: &Record) -> Result<MeshGeometry> {
38 let vertices: Vec<f32> = numbers(record, "vertices")?
39 .into_iter()
40 .map(f32::from_bits)
41 .collect();
42 let mut indices = numbers(record, "indices")?;
43 let changes = record
44 .get("indexChanges")
45 .and_then(Value::as_array)
46 .ok_or_else(error)?;
47 let mut cursor = 0_i64;
48 for collapse in record
49 .get("collapses")
50 .and_then(Value::as_array)
51 .ok_or_else(error)?
52 {
53 cursor = cursor
54 .checked_add(collapse["verticesToLose"].as_i64().ok_or_else(error)?)
55 .ok_or_else(error)?;
56 let replacement = cursor - 1;
57 if replacement < 0 || replacement as usize >= vertices.len() / 8 {
58 continue;
59 }
60 let start = collapse["indexChangesOffset"]
61 .as_i64()
62 .ok_or_else(error)?
63 .max(0) as usize;
64 let count = collapse["indicesToChange"]
65 .as_i64()
66 .ok_or_else(error)?
67 .max(0) as usize;
68 for value in changes.iter().skip(start).take(count) {
69 if let Some(slot) = value
70 .as_u64()
71 .and_then(|slot| indices.get_mut(slot as usize))
72 {
73 *slot = replacement as u32;
74 }
75 }
76 }
77 if !vertices.len().is_multiple_of(8)
78 || indices
79 .iter()
80 .any(|&index| index as usize >= vertices.len() / 8)
81 {
82 return Err(error());
83 }
84 Ok(MeshGeometry { vertices, indices })
85}
86pub fn skin_geometry(record: &Record) -> Result<MeshGeometry> {
88 let faces = numbers(record, "vertexIndices")?;
89 let uv_indices = numbers(record, "uvIndices")?;
90 let points = numbers(record, "positionNormals")?;
91 let uvs = numbers(record, "uvs")?;
92 let mut vertices = Vec::with_capacity(faces.len() * 8);
93 for (index, &face) in faces.iter().enumerate() {
94 let at = face as usize * 6;
95 let uv = *uv_indices.get(index).ok_or_else(error)? as usize * 2;
96 for &value in points.get(at..at + 6).ok_or_else(error)? {
97 vertices.push(f32::from_bits(value));
98 }
99 for &value in uvs.get(uv..uv + 2).ok_or_else(error)? {
100 vertices.push(f32::from_bits(value));
101 }
102 }
103 Ok(MeshGeometry {
104 vertices,
105 indices: (0..faces.len() as u32).collect(),
106 })
107}