Skip to main content

titanss/rendering/
lod.rs

1use super::mesh::LodLevel;
2
3pub struct LodConfig {
4    pub radius: f64,
5    pub low_poly_distance: f64,
6    pub medium_poly_distance: f64,
7}
8
9impl LodConfig {
10    pub fn new(radius: f64) -> Self {
11        Self {
12            radius,
13            low_poly_distance: radius * 500.0,
14            medium_poly_distance: radius * 100.0,
15        }
16    }
17
18    pub fn with_distances(radius: f64, medium: f64, low: f64) -> Self {
19        Self {
20            radius,
21            low_poly_distance: low,
22            medium_poly_distance: medium,
23        }
24    }
25
26    pub fn select_lod(&self, camera_distance: f64) -> LodLevel {
27        if camera_distance > self.low_poly_distance {
28            LodLevel::Low
29        } else if camera_distance > self.medium_poly_distance {
30            LodLevel::Medium
31        } else {
32            LodLevel::High
33        }
34    }
35
36    pub fn angular_diameter_rad(&self, camera_distance: f64) -> f64 {
37        2.0 * (self.radius / camera_distance).atan()
38    }
39
40    pub fn pixel_diameter(&self, camera_distance: f64, fov_rad: f64, viewport_height: u32) -> f64 {
41        let angular = self.angular_diameter_rad(camera_distance);
42        (angular / fov_rad) * viewport_height as f64
43    }
44
45    pub fn adaptive_subdivisions(
46        &self,
47        camera_distance: f64,
48        fov_rad: f64,
49        viewport_height: u32,
50    ) -> u32 {
51        let pixels = self.pixel_diameter(camera_distance, fov_rad, viewport_height);
52        if pixels < 16.0 {
53            1
54        } else if pixels < 64.0 {
55            2
56        } else if pixels < 256.0 {
57            3
58        } else if pixels < 1024.0 {
59            4
60        } else if pixels < 4096.0 {
61            5
62        } else {
63            6
64        }
65    }
66}