use super::GeometryRouter;
use crate::Mesh;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
impl GeometryRouter {
#[inline]
pub(super) fn compute_mesh_hash(mesh: &Mesh) -> u64 {
use rustc_hash::FxHasher;
let mut hasher = FxHasher::default();
let pos_len = mesh.positions.len();
let idx_len = mesh.indices.len();
pos_len.hash(&mut hasher);
idx_len.hash(&mut hasher);
const MAX_HASH_ELEMENTS: usize = 128;
if pos_len <= MAX_HASH_ELEMENTS {
for pos in &mesh.positions {
pos.to_bits().hash(&mut hasher);
}
} else {
let step = pos_len / MAX_HASH_ELEMENTS;
for i in (0..pos_len).step_by(step).take(MAX_HASH_ELEMENTS) {
mesh.positions[i].to_bits().hash(&mut hasher);
}
if pos_len >= 3 {
mesh.positions[pos_len - 1].to_bits().hash(&mut hasher);
mesh.positions[pos_len - 2].to_bits().hash(&mut hasher);
mesh.positions[pos_len - 3].to_bits().hash(&mut hasher);
}
}
if idx_len <= MAX_HASH_ELEMENTS {
for idx in &mesh.indices {
idx.hash(&mut hasher);
}
} else {
let step = idx_len / MAX_HASH_ELEMENTS;
for i in (0..idx_len).step_by(step).take(MAX_HASH_ELEMENTS) {
mesh.indices[i].hash(&mut hasher);
}
if idx_len >= 3 {
mesh.indices[idx_len - 1].hash(&mut hasher);
mesh.indices[idx_len - 2].hash(&mut hasher);
mesh.indices[idx_len - 3].hash(&mut hasher);
}
}
hasher.finish()
}
#[inline]
pub(super) fn get_or_cache_by_hash(&self, mesh: Mesh) -> Arc<Mesh> {
let hash = Self::compute_mesh_hash(&mesh);
{
let cache = self.geometry_hash_cache.borrow();
if let Some(cached) = cache.get(&hash) {
return Arc::clone(cached);
}
}
let arc_mesh = Arc::new(mesh);
{
let mut cache = self.geometry_hash_cache.borrow_mut();
cache.insert(hash, Arc::clone(&arc_mesh));
}
arc_mesh
}
}