1use crate::mesh::Mesh;
2use meshopt::{SimplifyOptions, VertexDataAdapter, simplify_with_attributes_and_locks};
3
4pub const NORMAL_WEIGHT: f32 = 0.5;
5pub const UV_WEIGHT: f32 = 1.0;
6pub const MIN_TRIANGLES: usize = 32;
7pub const MAX_LEVELS: usize = 8;
8
9#[derive(Clone, Debug)]
10pub struct Level {
11 pub mesh: Mesh,
12 pub error: f32,
13}
14
15pub fn chain(mesh: &Mesh) -> Vec<Level> {
16 let mut levels = vec![Level {
17 mesh: mesh.clone(),
18 error: 0.0,
19 }];
20 if mesh.indices.is_empty() {
21 return levels;
22 }
23 let positions: Vec<u8> = mesh
24 .positions
25 .iter()
26 .flat_map(|p| p.iter().flat_map(|v| v.to_le_bytes()))
27 .collect();
28 let Ok(adapter) = VertexDataAdapter::new(&positions, 12, 0) else {
29 return levels;
30 };
31 let attributes: Vec<f32> = mesh
32 .normals
33 .iter()
34 .zip(mesh.uvs.iter())
35 .flat_map(|(n, uv)| [n[0], n[1], n[2], uv[0], uv[1]])
36 .collect();
37 let weights = [
38 NORMAL_WEIGHT,
39 NORMAL_WEIGHT,
40 NORMAL_WEIGHT,
41 UV_WEIGHT,
42 UV_WEIGHT,
43 ];
44 let locks = vec![false; mesh.positions.len()];
45 let mut previous = mesh.triangle_count();
46 let mut target = previous / 2;
47 while levels.len() < MAX_LEVELS && target >= MIN_TRIANGLES {
48 let mut error = 0.0f32;
49 let indices = simplify_with_attributes_and_locks(
50 &mesh.indices,
51 &adapter,
52 &attributes,
53 &weights,
54 5 * std::mem::size_of::<f32>(),
55 &locks,
56 target * 3,
57 f32::MAX,
58 SimplifyOptions::ErrorAbsolute | SimplifyOptions::LockBorder,
59 Some(&mut error),
60 );
61 let triangles = indices.len() / 3;
62 if triangles == 0 || triangles * 10 > previous * 9 {
63 break;
64 }
65 let floor = levels.last().map_or(0.0, |level| level.error);
66 levels.push(Level {
67 mesh: compact(mesh, &indices),
68 error: error.max(floor),
69 });
70 previous = triangles;
71 target = triangles / 2;
72 }
73 levels
74}
75
76pub fn errors(levels: &[Level]) -> Vec<f32> {
77 levels.iter().map(|level| level.error).collect()
78}
79
80fn compact(mesh: &Mesh, indices: &[u32]) -> Mesh {
81 let mut remap = vec![u32::MAX; mesh.positions.len()];
82 let mut positions = Vec::new();
83 let mut normals = Vec::new();
84 let mut tangents = Vec::new();
85 let mut uvs = Vec::new();
86 let mut out = Vec::with_capacity(indices.len());
87 for &index in indices {
88 let slot = &mut remap[index as usize];
89 if *slot == u32::MAX {
90 *slot = positions.len() as u32;
91 positions.push(mesh.positions[index as usize]);
92 normals.push(mesh.normals[index as usize]);
93 tangents.push(mesh.tangents[index as usize]);
94 uvs.push(mesh.uvs[index as usize]);
95 }
96 out.push(*slot);
97 }
98 Mesh::new(positions, normals, tangents, uvs, out)
99}