| 158 | cmax[1] = cmax[1].max(cy); |
| 159 | cmax[2] = cmax[2].max(cz); |
| 160 | } |
| 161 | |
| 162 | let span = [ |
| 163 | (cmax[0] - cmin[0]).max(1.0e-6), |
| 164 | (cmax[1] - cmin[1]).max(1.0e-6), |
| 165 | (cmax[2] - cmin[2]).max(1.0e-6), |
| 166 | ]; |
| 167 | |
| 168 | let mut keyed = Vec::with_capacity(tri_count); |
| 169 | for tri_i in 0..tri_count { |
| 170 | let base = tri_i * 3; |
| 171 | let Some(a) = positions.get(indices[base] as usize) else { |
| 172 | return Ok(MeshletPack { |
| 173 | packed_indices: indices.to_vec(), |
| 174 | meshlets: Vec::new(), |
| 175 | }); |
| 176 | }; |
| 177 | let Some(b) = positions.get(indices[base + 1] as usize) else { |
| 178 | return Ok(MeshletPack { |
| 179 | packed_indices: indices.to_vec(), |
| 180 | meshlets: Vec::new(), |
| 181 | }); |
| 182 | }; |
| 183 | let Some(c) = positions.get(indices[base + 2] as usize) else { |
| 184 | return Ok(MeshletPack { |
| 185 | packed_indices: indices.to_vec(), |
| 186 | meshlets: Vec::new(), |
| 187 | }); |
| 188 | }; |
| 189 | let nx = (((a[0] + b[0] + c[0]) * (1.0 / 3.0) - cmin[0]) / span[0]).clamp(0.0, 1.0); |
| 190 | let ny = (((a[1] + b[1] + c[1]) * (1.0 / 3.0) - cmin[1]) / span[1]).clamp(0.0, 1.0); |
| 191 | let nz = (((a[2] + b[2] + c[2]) * (1.0 / 3.0) - cmin[2]) / span[2]).clamp(0.0, 1.0); |
| 192 | keyed.push((morton3(nx, ny, nz), tri_i as u32)); |
| 193 | } |
| 194 | keyed.sort_unstable_by_key(|item| item.0); |
| 195 | |
| 196 | let mut packed_indices = Vec::with_capacity(indices.len()); |
| 197 | for (_, tri) in keyed { |
| 198 | let base = tri as usize * 3; |
| 199 | packed_indices.push(indices[base]); |
| 200 | packed_indices.push(indices[base + 1]); |
| 201 | packed_indices.push(indices[base + 2]); |
| 202 | } |
| 203 | if tri_len < indices.len() { |
| 204 | packed_indices.extend_from_slice(&indices[tri_len..]); |
| 205 | } |
| 206 | |
| 207 | let packed_tri_len = (packed_indices.len() / 3) * 3; |
| 208 | let mut meshlets = Vec::with_capacity(packed_tri_len.div_ceil(chunk)); |
| 209 | let mut start = 0usize; |
| 210 | while start < packed_tri_len { |
| 211 | let end = start.saturating_add(chunk).min(packed_tri_len); |
| 212 | if let Some((center, radius)) = meshlet_bounds(positions, &packed_indices[start..end]) { |
| 213 | let (index_start, index_count) = checked_meshlet_index_range(start, end)?; |
| 214 | meshlets.push(MeshletBounds { |
| 215 | index_start, |
| 216 | index_count, |
| 217 | center, |