use crate::mesh3d::Vec3D;
pub const BRIGHTNESS_CHARS: &str = ".,-~:;=!*(%#$@";
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LightType {
Ambient,
Directional {
direction: Vec3D,
},
Point {
position: Vec3D,
},
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Light {
pub light_type: LightType,
pub intensity: f64,
}
impl Light {
#[must_use]
pub const fn new_ambient(intensity: f64) -> Self {
Self {
light_type: LightType::Ambient,
intensity,
}
}
#[must_use]
pub const fn new_directional(intensity: f64, direction: Vec3D) -> Self {
Self {
light_type: LightType::Directional { direction },
intensity,
}
}
#[must_use]
pub const fn new_point(intensity: f64, position: Vec3D) -> Self {
Self {
light_type: LightType::Point { position },
intensity,
}
}
fn calculate_intensity_for_direction(&self, normal: Vec3D, direction: Vec3D) -> f64 {
let n_dot_l = normal.dot(direction);
if n_dot_l > 0.0 {
self.intensity * n_dot_l / (normal.length() * direction.length())
} else {
0.0
}
}
#[must_use]
pub fn calculate_intensity(&self, point: Vec3D, normal: Vec3D) -> f64 {
match self.light_type {
LightType::Ambient => self.intensity,
LightType::Directional { direction } => {
self.calculate_intensity_for_direction(normal, direction)
}
LightType::Point { position } => {
let direction = point - position;
self.calculate_intensity_for_direction(normal, direction)
}
}
}
}