use serde::{Deserialize, Serialize};
use crate::ecs::camera::{Camera, OrthographicCamera, PerspectiveCamera, Projection};
use crate::ecs::light::{Light, LightType};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneLight {
Directional {
color: [f32; 3],
intensity: f32,
cast_shadows: bool,
shadow_bias: f32,
},
Point {
color: [f32; 3],
intensity: f32,
range: f32,
cast_shadows: bool,
shadow_bias: f32,
},
Spot {
color: [f32; 3],
intensity: f32,
range: f32,
inner_cone_angle: f32,
outer_cone_angle: f32,
cast_shadows: bool,
shadow_bias: f32,
},
}
impl SceneLight {
pub fn directional(color: [f32; 3], intensity: f32) -> Self {
Self::Directional {
color,
intensity,
cast_shadows: true,
shadow_bias: 0.005,
}
}
pub fn point(color: [f32; 3], intensity: f32, range: f32) -> Self {
Self::Point {
color,
intensity,
range,
cast_shadows: false,
shadow_bias: 0.0,
}
}
pub fn spot(
color: [f32; 3],
intensity: f32,
range: f32,
inner_cone_angle: f32,
outer_cone_angle: f32,
) -> Self {
Self::Spot {
color,
intensity,
range,
inner_cone_angle,
outer_cone_angle,
cast_shadows: false,
shadow_bias: 0.0,
}
}
pub fn to_light(&self) -> Light {
match self {
SceneLight::Directional {
color,
intensity,
cast_shadows,
shadow_bias,
} => Light {
light_type: LightType::Directional,
color: nalgebra_glm::Vec3::new(color[0], color[1], color[2]),
intensity: *intensity,
range: 0.0,
inner_cone_angle: 0.0,
outer_cone_angle: 0.0,
cast_shadows: *cast_shadows,
shadow_bias: *shadow_bias,
},
SceneLight::Point {
color,
intensity,
range,
cast_shadows,
shadow_bias,
} => Light {
light_type: LightType::Point,
color: nalgebra_glm::Vec3::new(color[0], color[1], color[2]),
intensity: *intensity,
range: *range,
inner_cone_angle: 0.0,
outer_cone_angle: 0.0,
cast_shadows: *cast_shadows,
shadow_bias: *shadow_bias,
},
SceneLight::Spot {
color,
intensity,
range,
inner_cone_angle,
outer_cone_angle,
cast_shadows,
shadow_bias,
} => Light {
light_type: LightType::Spot,
color: nalgebra_glm::Vec3::new(color[0], color[1], color[2]),
intensity: *intensity,
range: *range,
inner_cone_angle: *inner_cone_angle,
outer_cone_angle: *outer_cone_angle,
cast_shadows: *cast_shadows,
shadow_bias: *shadow_bias,
},
}
}
}
impl From<&Light> for SceneLight {
fn from(light: &Light) -> Self {
let color = [light.color.x, light.color.y, light.color.z];
match light.light_type {
LightType::Directional => SceneLight::Directional {
color,
intensity: light.intensity,
cast_shadows: light.cast_shadows,
shadow_bias: light.shadow_bias,
},
LightType::Point => SceneLight::Point {
color,
intensity: light.intensity,
range: light.range,
cast_shadows: light.cast_shadows,
shadow_bias: light.shadow_bias,
},
LightType::Spot => SceneLight::Spot {
color,
intensity: light.intensity,
range: light.range,
inner_cone_angle: light.inner_cone_angle,
outer_cone_angle: light.outer_cone_angle,
cast_shadows: light.cast_shadows,
shadow_bias: light.shadow_bias,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SceneCamera {
Perspective {
aspect_ratio: Option<f32>,
y_fov_rad: f32,
z_far: Option<f32>,
z_near: f32,
},
Orthographic {
x_mag: f32,
y_mag: f32,
z_far: f32,
z_near: f32,
},
}
impl SceneCamera {
pub fn perspective(y_fov_rad: f32, z_near: f32) -> Self {
Self::Perspective {
aspect_ratio: None,
y_fov_rad,
z_far: None,
z_near,
}
}
pub fn orthographic(x_mag: f32, y_mag: f32, z_near: f32, z_far: f32) -> Self {
Self::Orthographic {
x_mag,
y_mag,
z_far,
z_near,
}
}
pub fn to_camera(&self) -> Camera {
match self {
SceneCamera::Perspective {
aspect_ratio,
y_fov_rad,
z_far,
z_near,
} => Camera {
projection: Projection::Perspective(PerspectiveCamera {
aspect_ratio: *aspect_ratio,
y_fov_rad: *y_fov_rad,
z_far: *z_far,
z_near: *z_near,
}),
smoothing: None,
},
SceneCamera::Orthographic {
x_mag,
y_mag,
z_far,
z_near,
} => Camera {
projection: Projection::Orthographic(OrthographicCamera {
x_mag: *x_mag,
y_mag: *y_mag,
z_far: *z_far,
z_near: *z_near,
}),
smoothing: None,
},
}
}
}
impl From<&Camera> for SceneCamera {
fn from(camera: &Camera) -> Self {
match &camera.projection {
Projection::Perspective(perspective) => SceneCamera::Perspective {
aspect_ratio: perspective.aspect_ratio,
y_fov_rad: perspective.y_fov_rad,
z_far: perspective.z_far,
z_near: perspective.z_near,
},
Projection::Orthographic(orthographic) => SceneCamera::Orthographic {
x_mag: orthographic.x_mag,
y_mag: orthographic.y_mag,
z_far: orthographic.z_far,
z_near: orthographic.z_near,
},
}
}
}