enigma-3d 0.2.15

A 3D Rendering Engine with a focus on simplicity and ease of use. Far from feature complete and not recommended for production use.
Documentation
use glium::implement_uniform_block;
use serde::{Deserialize, Serialize};

pub enum LightEmissionType {
    Source,
    Ambient,
}

pub enum ShadowResolution {
    Low,
    Medium,
    High,
    Ultra,
    Custom(u32),
}

impl ShadowResolution {
    pub fn value(&self) -> u32 {
        match self {
            ShadowResolution::Low => 512,
            ShadowResolution::Medium => 1024,
            ShadowResolution::High => 2048,
            ShadowResolution::Ultra => 4096,
            ShadowResolution::Custom(v) => *v,
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct LightSerializer {
    pub position: [f32; 3],
    pub color: [f32; 3],
    pub intensity: f32,
    pub direction: [f32; 3],
    pub cast_shadow: bool,
}

#[derive(Copy, Clone)]
pub struct Light {
    pub position: [f32; 3],
    pub color: [f32; 3],
    pub intensity: f32,
    pub direction: [f32; 3],
    pub cast_shadow: bool
}

impl Light {
    pub fn new(position: [f32; 3], color: [f32; 3], intensity: f32, direction: Option<[f32;3]>, cast_shadow: bool) -> Self {
        Self {
            position,
            color,
            intensity,
            direction : direction.unwrap_or_else(|| [0.0, 0.0, 0.0]),
            cast_shadow,
        }
    }

    pub fn default() -> Self {
        Light::new([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], 1.0, None, true)
    }

    pub fn is_directional(&self) -> bool {
        self.direction != [0.0, 0.0, 0.0]
    }

    pub fn from_serializer(serializer: LightSerializer) -> Self {
        Self {
            position: serializer.position,
            color: serializer.color,
            intensity: serializer.intensity,
            direction: serializer.direction,
            cast_shadow: serializer.cast_shadow,
        }
    }

    pub fn to_serializer(&self) -> LightSerializer {
        LightSerializer {
            position: self.position,
            color: self.color,
            intensity: self.intensity,
            direction: self.direction,
            cast_shadow: self.cast_shadow,
        }
    }
}

pub struct LightBlock {
    pub position: [[f32; 4]; 4],
    pub directions: [[f32; 4]; 4],
    pub color: [[f32; 4]; 4],
    pub intensity: [f32; 4],
    pub cast_shadow: [i32; 4],
    pub amount: i32,
    pub ambient_color: [f32; 3],
    pub ambient_intensity: f32,
}

impl std::fmt::Debug for LightBlock {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("LightBlock")
            .field("position", &self.position)
            .field("color", &self.color)
            .field("intensity", &self.intensity)
            .field("amount", &self.amount)
            .field("ambient_color", &self.ambient_color)
            .finish()
    }
}

glium::implement_uniform_block!(Light, position, color, intensity, direction, cast_shadow);
glium::implement_uniform_block!(LightBlock, position, directions, cast_shadow, color, intensity, amount, ambient_color, ambient_intensity);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn shadow_resolution_values() {
        assert_eq!(ShadowResolution::Low.value(), 512);
        assert_eq!(ShadowResolution::Medium.value(), 1024);
        assert_eq!(ShadowResolution::High.value(), 2048);
        assert_eq!(ShadowResolution::Ultra.value(), 4096);
        assert_eq!(ShadowResolution::Custom(333).value(), 333);
    }
}