Make light effect entities

This commit is contained in:
Thinkofname 2016-04-08 11:08:21 +01:00
parent 027134f4c6
commit 3e8de93759
3 changed files with 107 additions and 1 deletions

View File

@ -22,6 +22,8 @@ pub fn add_systems(m: &mut ecs::Manager) {
m.add_render_system(sys);
let sys = systems::LerpRotation::new(m);
m.add_render_system(sys);
let sys = systems::LightEntity::new(m);
m.add_render_system(sys);
block_entity::add_systems(m);
}
@ -156,3 +158,17 @@ impl GameInfo {
}
}
}
pub struct Light {
pub block_light: f32,
pub sky_light: f32,
}
impl Light {
pub fn new() -> Light {
Light {
block_light: 0.0,
sky_light: 0.0,
}
}
}

View File

@ -9,6 +9,7 @@ use super::{
Gravity,
Bounds,
GameInfo,
Light
};
use world;
use render;
@ -45,6 +46,7 @@ pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
Point3::new(0.3, 1.8, 0.3)
)));
m.add_component_direct(entity, PlayerModel::new("", false, false, true));
m.add_component_direct(entity, Light::new());
entity
}
@ -60,6 +62,7 @@ pub fn create_remote(m: &mut ecs::Manager, name: &str) -> ecs::Entity {
Point3::new(0.3, 1.8, 0.3)
)));
m.add_component_direct(entity, PlayerModel::new(name, true, true, false));
m.add_component_direct(entity, Light::new());
entity
}
@ -113,6 +116,7 @@ struct PlayerRenderer {
position: ecs::Key<Position>,
rotation: ecs::Key<Rotation>,
game_info: ecs::Key<GameInfo>,
light: ecs::Key<Light>,
}
impl PlayerRenderer {
@ -120,15 +124,18 @@ impl PlayerRenderer {
let player_model = m.get_key();
let position = m.get_key();
let rotation = m.get_key();
let light = m.get_key();
PlayerRenderer {
filter: ecs::Filter::new()
.with(player_model)
.with(position)
.with(rotation),
.with(rotation)
.with(light),
player_model: player_model,
position: position,
rotation: rotation,
game_info: m.get_key(),
light: light,
}
}
}
@ -160,6 +167,7 @@ impl ecs::System for PlayerRenderer {
let player_model = m.get_component_mut(e, self.player_model).unwrap();
let position = m.get_component_mut(e, self.position).unwrap();
let rotation = m.get_component_mut(e, self.rotation).unwrap();
let light = m.get_component(e, self.light).unwrap();
if player_model.dirty {
self.entity_removed(m, e, world, renderer);
@ -168,6 +176,10 @@ impl ecs::System for PlayerRenderer {
if let Some(pmodel) = player_model.model {
let mdl = renderer.model.get_model(pmodel).unwrap();
mdl.block_light = light.block_light;
mdl.sky_light = light.sky_light;
let offset = if player_model.first_person {
let ox = (rotation.yaw - PI64/2.0).cos() * 0.25;
let oz = -(rotation.yaw - PI64/2.0).sin() * 0.25;

View File

@ -3,6 +3,7 @@ use super::*;
use ecs;
use world;
use render;
use shared::Position as BPos;
pub struct ApplyVelocity {
filter: ecs::Filter,
@ -214,3 +215,80 @@ impl ecs::System for LerpRotation {
}
}
}
pub struct LightEntity {
filter: ecs::Filter,
position: ecs::Key<Position>,
bounds: ecs::Key<Bounds>,
light: ecs::Key<Light>
}
impl LightEntity {
pub fn new(m: &mut ecs::Manager) -> LightEntity {
let position = m.get_key();
let bounds = m.get_key();
let light = m.get_key();
LightEntity {
filter: ecs::Filter::new()
.with(position)
.with(bounds)
.with(light),
position: position,
bounds: bounds,
light: light,
}
}
}
impl ecs::System for LightEntity {
fn filter(&self) -> &ecs::Filter {
&self.filter
}
fn update(&mut self, m: &mut ecs::Manager, world: &mut world::World, _: &mut render::Renderer) {
use cgmath::EuclideanVector;
for e in m.find(&self.filter) {
let pos = m.get_component(e, self.position).unwrap();
let bounds = m.get_component(e, self.bounds).unwrap();
let light = m.get_component_mut(e, self.light).unwrap();
let mut count = 0.0;
let mut block_light = 0.0;
let mut sky_light = 0.0;
let min_x = (pos.position.x + bounds.bounds.min.x).floor() as i32;
let min_y = (pos.position.y + bounds.bounds.min.y).floor() as i32;
let min_z = (pos.position.z + bounds.bounds.min.z).floor() as i32;
let max_x = (pos.position.x + bounds.bounds.max.x).ceil() as i32 + 1;
let max_y = (pos.position.y + bounds.bounds.max.y).ceil() as i32 + 1;
let max_z = (pos.position.z + bounds.bounds.max.z).ceil() as i32 + 1;
let length = (bounds.bounds.max - bounds.bounds.min).length() as f32;
for y in min_y .. max_y {
for z in min_z .. max_z {
for x in min_x .. max_x {
let dist = length - (
((x as f32 + 0.5) - pos.position.x as f32).powi(2)
+ ((y as f32 + 0.5) - pos.position.y as f32).powi(2)
+ ((z as f32 + 0.5) - pos.position.z as f32).powi(2)
)
.sqrt()
.min(length);
let dist = dist / length;
count += dist;
block_light += world.get_block_light(BPos::new(x, y, z)) as f32 * dist;
sky_light += world.get_sky_light(BPos::new(x, y, z)) as f32 * dist;
}
}
}
if count <= 0.01 {
light.block_light = 0.0;
light.sky_light = 0.0;
} else {
light.block_light = block_light / count;
light.sky_light = sky_light / count;
}
}
}
}