Skip to main content

kengaai_lod/
lib.rs

1use glam::Vec3;
2use std::collections::HashMap;
3
4/// Уровень детализации модели
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum LodLevel {
7    /// Высокая детализация (близко к камере)
8    High = 0,
9    /// Средняя детализация
10    Medium = 1,
11    /// Низкая детализация (далеко от камеры)
12    Low = 2,
13    /// Очень низкая детализация (очень далеко)
14    VeryLow = 3,
15}
16
17/// Конфигурация LOD для модели
18#[derive(Debug, Clone)]
19pub struct LodConfig {
20    /// Расстояния переключения между уровнями LOD
21    pub distances: [f32; 4],
22    /// Имена моделей для каждого уровня LOD
23    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
35/// Менеджер LOD системы
36pub struct LodManager {
37    /// Конфигурации LOD для каждой модели
38    configs: HashMap<String, LodConfig>,
39    /// Позиция камеры для расчета расстояний
40    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    /// Регистрирует модель с LOD конфигурацией
52    pub fn register_model(&mut self, model_name: String, config: LodConfig) {
53        self.configs.insert(model_name, config);
54    }
55
56    /// Обновляет позицию камеры
57    pub fn update_camera_position(&mut self, position: Vec3) {
58        self.camera_position = position;
59    }
60
61    /// Определяет необходимый уровень LOD для модели на основе расстояния до камеры
62    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            // Если модель не зарегистрирована, используем высокий уровень детализации
77            LodLevel::High
78        }
79    }
80
81    /// Получает имя модели для конкретного уровня LOD
82    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    /// Проверяет, нужно ли переключать LOD для модели
89    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