use std::{marker::PhantomData, ops::Range};
use crate::{Icosphere, IcosphereVertex, triangle_count};
#[derive(Debug, Clone)]
pub struct IcosphereLevels<T, S>
where
T: IcosphereVertex,
S: Icosphere<T>,
{
levels: Vec<S>,
pub min_binning_depth: usize,
pub binning_depth_step: usize,
_phantom: PhantomData<T>,
}
impl<T, S> IcosphereLevels<T, S>
where
T: IcosphereVertex,
S: Icosphere<T>,
{
pub fn get(&self, level: usize) -> &S {
&self.levels[level * self.binning_depth_step]
}
pub fn binning_depth_at_level(&self, level: usize) -> usize {
self.min_binning_depth + level * self.binning_depth_step
}
pub fn level_of_binning_depth(&self, binning_depth: usize) -> Option<usize> {
if binning_depth < self.min_binning_depth
|| binning_depth >= self.binning_depth_at_level(self.levels.len())
|| (binning_depth - self.min_binning_depth) % self.binning_depth_step != 0
{
return None;
}
Some((binning_depth - self.min_binning_depth) / self.binning_depth_step)
}
pub fn chunk_size(&self) -> usize {
1 << (2 * self.binning_depth_step)
}
pub fn chunk_count(&self, level: usize) -> usize {
assert!(level > 0, "chunk_count is only defined at level > 0");
let binning_depth = self.binning_depth_at_level(level - 1);
triangle_count(binning_depth)
}
pub fn subchunk_indices(&self, chunk_index: usize) -> Range<usize> {
let size = self.chunk_size();
let start = chunk_index * size;
let end = start + size;
start..end
}
}