1use glam::Vec3;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum LodLevel {
7 High = 0,
9 Medium = 1,
11 Low = 2,
13 VeryLow = 3,
15}
16
17#[derive(Debug, Clone)]
19pub struct LodConfig {
20 pub distances: [f32; 4],
22 pub model_names: [Option<String>; 4],
24}
25
26impl Default for LodConfig {
27 fn default() -> Self {
28 Self {
29 distances: [10.0, 30.0, 60.0, 200.0],
30 model_names: [None, None, None, None],
31 }
32 }
33}
34
35pub struct LodManager {
37 configs: HashMap<String, LodConfig>,
39 camera_position: Vec3,
41}
42
43impl LodManager {
44 pub fn new() -> Self {
45 Self {
46 configs: HashMap::new(),
47 camera_position: Vec3::ZERO,
48 }
49 }
50
51 pub fn register_model(&mut self, model_name: String, config: LodConfig) {
53 self.configs.insert(model_name, config);
54 }
55
56 pub fn update_camera_position(&mut self, position: Vec3) {
58 self.camera_position = position;
59 }
60
61 pub fn get_lod_level(&self, model_name: &str, model_position: Vec3) -> LodLevel {
63 if let Some(config) = self.configs.get(model_name) {
64 let distance = model_position.distance(self.camera_position);
65
66 if distance < config.distances[0] {
67 LodLevel::High
68 } else if distance < config.distances[1] {
69 LodLevel::Medium
70 } else if distance < config.distances[2] {
71 LodLevel::Low
72 } else {
73 LodLevel::VeryLow
74 }
75 } else {
76 LodLevel::High
78 }
79 }
80
81 pub fn get_model_name_for_lod(&self, model_name: &str, lod_level: LodLevel) -> Option<String> {
83 self.configs
84 .get(model_name)
85 .and_then(|config| config.model_names[lod_level as usize].clone())
86 }
87
88 pub fn should_switch_lod(&self, model_name: &str, current_lod: LodLevel, model_position: Vec3) -> bool {
90 let new_lod = self.get_lod_level(model_name, model_position);
91 new_lod != current_lod
92 }
93}
94
95impl Default for LodManager {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100