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}