use glam::Vec3;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LodLevel {
High = 0,
Medium = 1,
Low = 2,
VeryLow = 3,
}
#[derive(Debug, Clone)]
pub struct LodConfig {
pub distances: [f32; 4],
pub model_names: [Option<String>; 4],
}
impl Default for LodConfig {
fn default() -> Self {
Self {
distances: [10.0, 30.0, 60.0, 200.0],
model_names: [None, None, None, None],
}
}
}
pub struct LodManager {
configs: HashMap<String, LodConfig>,
camera_position: Vec3,
}
impl LodManager {
pub fn new() -> Self {
Self {
configs: HashMap::new(),
camera_position: Vec3::ZERO,
}
}
pub fn register_model(&mut self, model_name: String, config: LodConfig) {
self.configs.insert(model_name, config);
}
pub fn update_camera_position(&mut self, position: Vec3) {
self.camera_position = position;
}
pub fn get_lod_level(&self, model_name: &str, model_position: Vec3) -> LodLevel {
if let Some(config) = self.configs.get(model_name) {
let distance = model_position.distance(self.camera_position);
if distance < config.distances[0] {
LodLevel::High
} else if distance < config.distances[1] {
LodLevel::Medium
} else if distance < config.distances[2] {
LodLevel::Low
} else {
LodLevel::VeryLow
}
} else {
LodLevel::High
}
}
pub fn get_model_name_for_lod(&self, model_name: &str, lod_level: LodLevel) -> Option<String> {
self.configs
.get(model_name)
.and_then(|config| config.model_names[lod_level as usize].clone())
}
pub fn should_switch_lod(&self, model_name: &str, current_lod: LodLevel, model_position: Vec3) -> bool {
let new_lod = self.get_lod_level(model_name, model_position);
new_lod != current_lod
}
}
impl Default for LodManager {
fn default() -> Self {
Self::new()
}
}