#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct RemapResult {
pub new_indices: Vec<u32>,
pub old_to_new: Vec<u32>,
pub new_to_old: Vec<u32>,
}
#[allow(dead_code)]
pub fn compact_remap(indices: &[u32], vertex_count: usize) -> RemapResult {
let mut used = vec![false; vertex_count];
for &i in indices {
if (i as usize) < vertex_count {
used[i as usize] = true;
}
}
let mut old_to_new = vec![u32::MAX; vertex_count];
let mut new_to_old = Vec::new();
let mut next = 0u32;
for (i, &u) in used.iter().enumerate() {
if u {
old_to_new[i] = next;
new_to_old.push(i as u32);
next += 1;
}
}
let new_indices: Vec<u32> = indices.iter().map(|&i| old_to_new[i as usize]).collect();
RemapResult {
new_indices,
old_to_new,
new_to_old,
}
}
#[allow(dead_code)]
pub fn apply_remap(indices: &[u32], remap: &[u32]) -> Vec<u32> {
indices.iter().map(|&i| remap[i as usize]).collect()
}
#[allow(dead_code)]
pub fn used_index_count(indices: &[u32]) -> usize {
let mut set = std::collections::HashSet::new();
for &i in indices {
set.insert(i);
}
set.len()
}
#[allow(dead_code)]
pub fn unused_index_count(indices: &[u32], vertex_count: usize) -> usize {
vertex_count.saturating_sub(used_index_count(indices))
}
#[allow(dead_code)]
pub fn max_index(indices: &[u32]) -> Option<u32> {
indices.iter().copied().max()
}
#[allow(dead_code)]
pub fn indices_in_bounds(indices: &[u32], vertex_count: usize) -> bool {
indices.iter().all(|&i| (i as usize) < vertex_count)
}
#[allow(dead_code)]
pub fn reverse_winding(indices: &[u32]) -> Vec<u32> {
let tri_count = indices.len() / 3;
let mut result = Vec::with_capacity(indices.len());
for t in 0..tri_count {
result.push(indices[t * 3]);
result.push(indices[t * 3 + 2]);
result.push(indices[t * 3 + 1]);
}
result
}
#[allow(dead_code)]
pub fn remap_result_to_json(result: &RemapResult) -> String {
format!(
"{{\"new_vertex_count\":{},\"index_count\":{}}}",
result.new_to_old.len(),
result.new_indices.len(),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compact_remap_all_used() {
let r = compact_remap(&[0, 1, 2], 3);
assert_eq!(r.new_to_old.len(), 3);
assert_eq!(r.new_indices, vec![0, 1, 2]);
}
#[test]
fn test_compact_remap_gap() {
let r = compact_remap(&[0, 2, 3], 4);
assert_eq!(r.new_to_old.len(), 3);
assert!(r.new_indices.iter().all(|&i| i < 3));
}
#[test]
fn test_apply_remap() {
let remap = vec![2, 0, 1];
let result = apply_remap(&[0, 1, 2], &remap);
assert_eq!(result, vec![2, 0, 1]);
}
#[test]
fn test_used_index_count() {
assert_eq!(used_index_count(&[0, 1, 2, 0, 1, 2]), 3);
}
#[test]
fn test_unused_index_count() {
assert_eq!(unused_index_count(&[0, 2], 4), 2);
}
#[test]
fn test_max_index() {
assert_eq!(max_index(&[3, 1, 4, 1, 5]), Some(5));
assert_eq!(max_index(&[]), None);
}
#[test]
fn test_indices_in_bounds() {
assert!(indices_in_bounds(&[0, 1, 2], 3));
assert!(!indices_in_bounds(&[0, 1, 3], 3));
}
#[test]
fn test_reverse_winding() {
let r = reverse_winding(&[0, 1, 2, 3, 4, 5]);
assert_eq!(r, vec![0, 2, 1, 3, 5, 4]);
}
#[test]
fn test_remap_result_to_json() {
let r = compact_remap(&[0, 1, 2], 3);
let json = remap_result_to_json(&r);
assert!(json.contains("\"new_vertex_count\":3"));
}
#[test]
fn test_empty_indices() {
let r = compact_remap(&[], 5);
assert_eq!(r.new_to_old.len(), 0);
}
}