use super::mesh::LodLevel;
pub struct LodConfig {
pub radius: f64,
pub low_poly_distance: f64,
pub medium_poly_distance: f64,
}
impl LodConfig {
pub fn new(radius: f64) -> Self {
Self {
radius,
low_poly_distance: radius * 500.0,
medium_poly_distance: radius * 100.0,
}
}
pub fn with_distances(radius: f64, medium: f64, low: f64) -> Self {
Self {
radius,
low_poly_distance: low,
medium_poly_distance: medium,
}
}
pub fn select_lod(&self, camera_distance: f64) -> LodLevel {
if camera_distance > self.low_poly_distance {
LodLevel::Low
} else if camera_distance > self.medium_poly_distance {
LodLevel::Medium
} else {
LodLevel::High
}
}
pub fn angular_diameter_rad(&self, camera_distance: f64) -> f64 {
2.0 * (self.radius / camera_distance).atan()
}
pub fn pixel_diameter(&self, camera_distance: f64, fov_rad: f64, viewport_height: u32) -> f64 {
let angular = self.angular_diameter_rad(camera_distance);
(angular / fov_rad) * viewport_height as f64
}
pub fn adaptive_subdivisions(
&self,
camera_distance: f64,
fov_rad: f64,
viewport_height: u32,
) -> u32 {
let pixels = self.pixel_diameter(camera_distance, fov_rad, viewport_height);
if pixels < 16.0 {
1
} else if pixels < 64.0 {
2
} else if pixels < 256.0 {
3
} else if pixels < 1024.0 {
4
} else if pixels < 4096.0 {
5
} else {
6
}
}
}