1use glam::Vec2;
2#[cfg(feature = "tracing")]
3use tracing::instrument;
4
5use crate::{instance::U32Layer, Layer, Mesh};
6
7impl Mesh {
8 pub fn reorder_neighbors_ccw_and_fix_corners(&mut self) {
10 let mut reordered_neighbors = vec![];
11 for layer in self.layers.iter() {
12 let mut reordered_neighbors_in_layer = vec![];
13 for vertex in &layer.vertices {
14 let vertex_coords = vertex.coords + layer.offset;
15 let mut polygons = vertex
17 .polygons
18 .iter()
19 .filter(|p| **p != u32::MAX)
20 .cloned()
21 .collect::<Vec<_>>();
22 polygons.sort_unstable_by_key(|p| {
24 let vertices =
25 &self.layers[p.layer() as usize].polygons[p.polygon() as usize].vertices;
26 let center = vertices
27 .iter()
28 .map(|v| self.layers[p.layer() as usize].vertices[*v as usize].coords)
29 .sum::<Vec2>()
30 / vertices.len() as f32
31 + self.layers[p.layer() as usize].offset;
32 let direction = center - vertex_coords;
33 let angle = Vec2::Y.angle_to(direction);
34 (angle * 100000.0) as i32
35 });
36 polygons.dedup_by_key(|p| *p);
37 if polygons.is_empty() {
38 reordered_neighbors_in_layer.push(vec![u32::MAX]);
39 } else {
40 let first = polygons[0];
44 let last = *polygons.last().unwrap();
45 if first == last {
46 polygons.push(u32::MAX);
47 } else {
48 polygons = polygons
49 .windows(2)
50 .map(|pair| [pair[0], pair[1]])
51 .chain(std::iter::once([last, first]))
52 .flat_map(|[pair0, pair1]| {
53 let layer0 = &self.layers[pair0.layer() as usize];
54 let layer1 = &self.layers[pair1.layer() as usize];
55 let mut polygon0 =
56 layer0.polygons[pair0.polygon() as usize].vertices.clone();
57 polygon0.reverse();
58 let mut found = false;
59 let Some(previous0) =
60 polygon0.iter().cycle().take(polygon0.len() * 2).find(|v| {
61 if found {
62 return true;
63 }
64 if (layer0.vertices[**v as usize].coords + layer0.offset)
65 .distance_squared(vertex_coords)
66 < 0.0001
67 {
68 found = true;
69 }
70 false
71 })
72 else {
73 return vec![pair0, u32::MAX];
74 };
75 let polygon1 = &layer1.polygons[pair1.polygon() as usize].vertices;
76 let mut found = false;
77 let Some(next1) =
78 polygon1.iter().cycle().take(polygon1.len() * 2).find(|v| {
79 if found {
80 return true;
81 }
82 if (layer1.vertices[**v as usize].coords + layer1.offset)
83 .distance_squared(vertex_coords)
84 < 0.0001
85 {
86 found = true;
87 }
88 false
89 })
90 else {
91 return vec![pair0, u32::MAX];
92 };
93
94 if layer0.vertices[*previous0 as usize].coords + layer0.offset
95 != layer1.vertices[*next1 as usize].coords + layer1.offset
96 {
97 vec![pair0, u32::MAX]
98 } else {
99 vec![pair0]
100 }
101 })
102 .collect();
103 }
104 reordered_neighbors_in_layer.push(polygons);
105 }
106 }
107
108 reordered_neighbors.push(reordered_neighbors_in_layer);
109 }
110 for (layer, new) in self.layers.iter_mut().zip(reordered_neighbors.into_iter()) {
111 for (vertex, new) in layer.vertices.iter_mut().zip(new.into_iter()) {
112 vertex.is_corner = new.contains(&u32::MAX);
113 vertex.polygons = new;
114 }
115 }
116 }
117
118 #[cfg_attr(feature = "tracing", instrument(skip_all))]
120 pub fn remove_useless_vertices(&mut self) -> bool {
121 !self
122 .layers
123 .iter_mut()
124 .map(|layer| layer.remove_useless_vertices())
125 .all(|m| !m)
126 }
127
128 #[cfg_attr(feature = "tracing", instrument(skip_all))]
130 pub fn update_is_one_way(&mut self) {
131 self.layers
132 .iter_mut()
133 .for_each(|layer| layer.update_is_one_way());
134 }
135}
136
137impl Layer {
138 #[cfg_attr(feature = "tracing", instrument(skip_all))]
140 pub fn remove_useless_vertices(&mut self) -> bool {
141 let mut removed = false;
142 let mut new_indexes = vec![u32::MAX; self.vertices.len()];
143 let mut kept = 0;
144 for (i, vertex) in self.vertices.iter().enumerate() {
145 if vertex.polygons.is_empty() || vertex.polygons == [u32::MAX] {
146 removed = true;
147 } else {
148 new_indexes[i] = kept;
149 kept += 1;
150 }
151 }
152 for polygon in self.polygons.iter_mut() {
153 for vertex in polygon.vertices.iter_mut() {
154 *vertex = new_indexes[*vertex as usize];
155 }
156 }
157 self.vertices = self
158 .vertices
159 .iter()
160 .enumerate()
161 .filter_map(|(i, _)| {
162 if new_indexes[i] != u32::MAX {
163 Some(self.vertices[i].clone())
164 } else {
165 None
166 }
167 })
168 .collect();
169 if !self.height.is_empty() {
170 self.height = self
171 .height
172 .iter()
173 .enumerate()
174 .filter_map(|(i, _)| {
175 if new_indexes[i] != u32::MAX {
176 Some(self.height[i])
177 } else {
178 None
179 }
180 })
181 .collect();
182 }
183 removed
184 }
185
186 #[cfg_attr(feature = "tracing", instrument(skip_all))]
188 pub fn update_is_one_way(&mut self) {
189 for polygon in self.polygons.iter_mut() {
190 if polygon.vertices.len() == 3 {
191 polygon.is_one_way = polygon
192 .vertices
193 .iter()
194 .any(|vertex| self.vertices[*vertex as usize].polygons.len() == 2);
195 } else {
196 polygon.is_one_way = polygon
197 .vertices
198 .iter()
199 .filter(|vertex| self.vertices[**vertex as usize].polygons.len() == 2)
200 .count()
201 == polygon.vertices.len() - 2;
202 }
203 }
204 }
205}