sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
// Sistema de LOD (Level of Detail) para otimização de performance
use crate::mesh3d::{Mesh3D, Vec3};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LODMesh {
    pub levels: Vec<LODLevel>,
    pub current_level: usize,
    pub auto_switch: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LODLevel {
    pub mesh: Mesh3D,
    pub distance: f32,
    pub quality: LODQuality,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LODQuality {
    Ultra,   // Distância 0-50
    High,    // Distância 50-100
    Medium,  // Distância 100-200
    Low,     // Distância 200-400
    VeryLow, // Distância 400+
}

impl LODMesh {
    pub fn new(base_mesh: Mesh3D) -> Self {
        let levels = vec![
            LODLevel {
                mesh: base_mesh.clone(),
                distance: 0.0,
                quality: LODQuality::Ultra,
            },
            LODLevel {
                mesh: Self::simplify_mesh(&base_mesh, 0.75),
                distance: 50.0,
                quality: LODQuality::High,
            },
            LODLevel {
                mesh: Self::simplify_mesh(&base_mesh, 0.5),
                distance: 100.0,
                quality: LODQuality::Medium,
            },
            LODLevel {
                mesh: Self::simplify_mesh(&base_mesh, 0.25),
                distance: 200.0,
                quality: LODQuality::Low,
            },
            LODLevel {
                mesh: Self::simplify_mesh(&base_mesh, 0.1),
                distance: 400.0,
                quality: LODQuality::VeryLow,
            },
        ];

        Self {
            levels,
            current_level: 0,
            auto_switch: true,
        }
    }

    pub fn with_custom_levels(levels: Vec<LODLevel>) -> Self {
        Self {
            levels,
            current_level: 0,
            auto_switch: true,
        }
    }

    pub fn update(&mut self, camera_position: Vec3, object_position: Vec3) {
        if !self.auto_switch {
            return;
        }

        let distance = camera_position.distance(&object_position);
        
        for (i, level) in self.levels.iter().enumerate().rev() {
            if distance >= level.distance {
                self.current_level = i;
                break;
            }
        }
    }

    pub fn get_current_mesh(&self) -> &Mesh3D {
        &self.levels[self.current_level].mesh
    }

    pub fn get_current_quality(&self) -> LODQuality {
        self.levels[self.current_level].quality
    }

    pub fn set_quality(&mut self, quality: LODQuality) {
        self.auto_switch = false;
        for (i, level) in self.levels.iter().enumerate() {
            if level.quality == quality {
                self.current_level = i;
                break;
            }
        }
    }

    pub fn enable_auto_switch(&mut self) {
        self.auto_switch = true;
    }

    // Simplifica uma mesh reduzindo vértices
    fn simplify_mesh(mesh: &Mesh3D, factor: f32) -> Mesh3D {
        if factor >= 1.0 {
            return mesh.clone();
        }

        let target_vertices = (mesh.vertices.len() as f32 * factor) as usize;
        let target_vertices = target_vertices.max(3); // Mínimo 3 vértices

        if target_vertices >= mesh.vertices.len() {
            return mesh.clone();
        }

        // Simplificação básica: pega vértices em intervalos
        let step = mesh.vertices.len() / target_vertices;
        let step = step.max(1);

        let mut new_vertices = Vec::new();
        let mut new_indices = Vec::new();

        for i in (0..mesh.vertices.len()).step_by(step) {
            new_vertices.push(mesh.vertices[i].clone());
        }

        // Reconstrói índices (simplificado)
        for i in (0..new_vertices.len()).step_by(3) {
            if i + 2 < new_vertices.len() {
                new_indices.push(i as u32);
                new_indices.push((i + 1) as u32);
                new_indices.push((i + 2) as u32);
            }
        }

        let mut simplified = Mesh3D::finalize(new_vertices, new_indices);
        simplified.position = mesh.position;
        simplified.rotation = mesh.rotation;
        simplified.scale = mesh.scale;
        simplified
    }

    pub fn get_stats(&self) -> LODStats {
        LODStats {
            current_level: self.current_level,
            current_quality: self.get_current_quality(),
            vertex_count: self.levels[self.current_level].mesh.vertices.len(),
            triangle_count: self.levels[self.current_level].mesh.indices.len() / 3,
            total_levels: self.levels.len(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct LODStats {
    pub current_level: usize,
    pub current_quality: LODQuality,
    pub vertex_count: usize,
    pub triangle_count: usize,
    pub total_levels: usize,
}

impl LODQuality {
    pub fn from_distance(distance: f32) -> Self {
        if distance < 50.0 {
            LODQuality::Ultra
        } else if distance < 100.0 {
            LODQuality::High
        } else if distance < 200.0 {
            LODQuality::Medium
        } else if distance < 400.0 {
            LODQuality::Low
        } else {
            LODQuality::VeryLow
        }
    }

    pub fn get_simplification_factor(&self) -> f32 {
        match self {
            LODQuality::Ultra => 1.0,
            LODQuality::High => 0.75,
            LODQuality::Medium => 0.5,
            LODQuality::Low => 0.25,
            LODQuality::VeryLow => 0.1,
        }
    }
}