use crate::mesh3d::{Mesh3D, Vec3};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Skybox {
pub mesh: Mesh3D,
pub textures: SkyboxTextures,
pub brightness: f32,
pub rotation_speed: f32,
pub current_rotation: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SkyboxTextures {
CubeMap {
front: String,
back: String,
left: String,
right: String,
top: String,
bottom: String,
},
Procedural(ProceduralSky),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProceduralSky {
pub horizon_color: [u8; 4],
pub zenith_color: [u8; 4],
pub ground_color: [u8; 4],
pub sun_color: [u8; 4],
pub sun_position: Vec3,
pub sun_size: f32,
pub stars: bool,
pub star_count: u32,
}
impl Skybox {
pub fn new_cubemap(
front: String,
back: String,
left: String,
right: String,
top: String,
bottom: String,
) -> Self {
let mesh = Self::create_skybox_mesh();
Self {
mesh,
textures: SkyboxTextures::CubeMap {
front,
back,
left,
right,
top,
bottom,
},
brightness: 1.0,
rotation_speed: 0.0,
current_rotation: 0.0,
}
}
pub fn new_procedural(config: ProceduralSky) -> Self {
let mesh = Self::create_skybox_mesh();
Self {
mesh,
textures: SkyboxTextures::Procedural(config),
brightness: 1.0,
rotation_speed: 0.0,
current_rotation: 0.0,
}
}
pub fn simple_gradient(top_color: [u8; 4], bottom_color: [u8; 4]) -> Self {
Self::new_procedural(ProceduralSky {
horizon_color: bottom_color,
zenith_color: top_color,
ground_color: [50, 50, 50, 255],
sun_color: [255, 255, 200, 255],
sun_position: Vec3::new(0.0, 1.0, 0.5).normalize(),
sun_size: 0.05,
stars: false,
star_count: 0,
})
}
pub fn day_sky() -> Self {
Self::new_procedural(ProceduralSky {
horizon_color: [135, 206, 235, 255], zenith_color: [25, 25, 112, 255], ground_color: [34, 139, 34, 255], sun_color: [255, 255, 200, 255],
sun_position: Vec3::new(0.3, 0.8, 0.5).normalize(),
sun_size: 0.05,
stars: false,
star_count: 0,
})
}
pub fn night_sky() -> Self {
Self::new_procedural(ProceduralSky {
horizon_color: [25, 25, 112, 255], zenith_color: [0, 0, 20, 255], ground_color: [20, 20, 30, 255],
sun_color: [200, 200, 255, 255], sun_position: Vec3::new(-0.3, 0.6, 0.5).normalize(),
sun_size: 0.04,
stars: true,
star_count: 200,
})
}
pub fn sunset_sky() -> Self {
Self::new_procedural(ProceduralSky {
horizon_color: [255, 140, 0, 255], zenith_color: [255, 69, 0, 255], ground_color: [139, 69, 19, 255],
sun_color: [255, 100, 0, 255],
sun_position: Vec3::new(0.8, 0.2, 0.5).normalize(),
sun_size: 0.08,
stars: false,
star_count: 0,
})
}
fn create_skybox_mesh() -> Mesh3D {
let size = 500.0;
let mut mesh = Mesh3D::cube(size);
mesh.flip_normals(); mesh
}
pub fn update(&mut self, dt: f32) {
if self.rotation_speed != 0.0 {
self.current_rotation += self.rotation_speed * dt;
self.mesh.rotation.y = self.current_rotation;
}
}
pub fn set_rotation_speed(&mut self, speed: f32) {
self.rotation_speed = speed;
}
pub fn set_brightness(&mut self, brightness: f32) {
self.brightness = brightness.max(0.0).min(2.0);
}
}
impl Default for ProceduralSky {
fn default() -> Self {
Self {
horizon_color: [135, 206, 235, 255],
zenith_color: [25, 25, 112, 255],
ground_color: [34, 139, 34, 255],
sun_color: [255, 255, 200, 255],
sun_position: Vec3::new(0.0, 1.0, 0.0),
sun_size: 0.05,
stars: false,
star_count: 0,
}
}
}