Nero/light offsets

This commit is contained in:
Nero 2019-07-25 20:51:20 +00:00 committed by Joshua Barretto
parent d77d4dc60e
commit 53086cb3b2
7 changed files with 125 additions and 20 deletions

View File

@ -401,8 +401,12 @@ impl Client {
} => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
self.state.write_component(entity, pos);
self.state.write_component(entity, vel);
self.state.write_component(entity, ori);
if let Some(v) = vel {
self.state.write_component(entity, v);
};
if let Some(o) = ori {
self.state.write_component(entity, o);
};
if let Some(a_s) = action_state {
self.state.write_component(entity, a_s);
}

View File

@ -3,6 +3,7 @@ use vek::*;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct LightEmitter {
pub offset: Vec3<f32>,
pub col: Rgb<f32>,
pub strength: f32,
}
@ -10,8 +11,9 @@ pub struct LightEmitter {
impl Default for LightEmitter {
fn default() -> Self {
Self {
offset: Vec3::zero(),
col: Rgb::one(),
strength: 250.0,
strength: 1.0,
}
}
}

View File

@ -38,8 +38,8 @@ pub enum ServerMsg {
EntityPhysics {
entity: u64,
pos: comp::Pos,
vel: comp::Vel,
ori: comp::Ori,
vel: Option<comp::Vel>,
ori: Option<comp::Ori>,
action_state: Option<comp::ActionState>,
},
TerrainChunkUpdate {

View File

@ -138,6 +138,18 @@ lazy_static! {
"/object [Name]: Spawn an object",
handle_object,
),
ChatCommand::new(
"light",
"{} {} {} {} {} {} {}",
"/light <opt: <<cr> <cg> <cb>> <<ox> <oy> <oz>> <<strenght>>>: Spawn entity with light",
handle_light,
),
ChatCommand::new(
"lantern",
"{} ",
"/lantern : adds/remove light near player",
handle_lantern,
),
];
}
@ -514,6 +526,81 @@ fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action:
}
}
fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
let (opt_r, opt_g, opt_b, opt_x, opt_y, opt_z, opt_s) =
scan_fmt!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32);
let mut light_emitter = comp::LightEmitter::default();
if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) {
light_emitter.col = Rgb::new(r, g, b)
};
if let (Some(x), Some(y), Some(z)) = (opt_x, opt_y, opt_z) {
light_emitter.offset = Vec3::new(x, y, z)
};
if let Some(s) = opt_s {
light_emitter.strength = s
};
let pos = server
.state
.ecs()
.read_storage::<comp::Pos>()
.get(entity)
.copied();
if let Some(pos) = pos {
server
.state
.ecs_mut()
.create_entity_synced()
.with(pos)
.with(comp::ForceUpdate)
.with(light_emitter)
.build();
server
.clients
.notify(entity, ServerMsg::Chat(format!("Spawned object.")));
} else {
server
.clients
.notify(entity, ServerMsg::Chat(format!("You have no position!")));
}
}
fn handle_lantern(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) {
if server
.state
.read_storage::<comp::LightEmitter>()
.get(entity)
.is_some()
{
server
.state
.ecs()
.write_storage::<comp::LightEmitter>()
.remove(entity);
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You put out the lantern.")),
);
} else {
let _ = server
.state
.ecs()
.write_storage::<comp::LightEmitter>()
.insert(
entity,
comp::LightEmitter {
offset: Vec3::new(1.0, 0.2, 0.8),
col: Rgb::new(0.824, 0.365, 0.196),
strength: 1.5,
},
);
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You lighted your lantern.")),
);
}
}
fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
let opt_alias = scan_fmt!(&args, action.arg_fmt, String);
match opt_alias {

View File

@ -172,7 +172,10 @@ impl Server {
.with(comp::Vel(Vec3::zero()))
.with(comp::Ori(Vec3::unit_y()))
.with(comp::Body::Object(object))
.with(comp::LightEmitter::default())
.with(comp::LightEmitter {
offset: Vec3::unit_z(),
..comp::LightEmitter::default()
})
.with(comp::ActionState::default())
.with(comp::ForceUpdate)
}
@ -664,11 +667,11 @@ impl Server {
state.write_component(entity, player);
// Sync physics
for (&uid, &pos, &vel, &ori, action_state) in (
for (&uid, &pos, vel, ori, action_state) in (
&state.ecs().read_storage::<Uid>(),
&state.ecs().read_storage::<comp::Pos>(),
&state.ecs().read_storage::<comp::Vel>(),
&state.ecs().read_storage::<comp::Ori>(),
state.ecs().read_storage::<comp::Vel>().maybe(),
state.ecs().read_storage::<comp::Ori>().maybe(),
state.ecs().read_storage::<comp::ActionState>().maybe(),
)
.join()
@ -676,8 +679,8 @@ impl Server {
client.notify(ServerMsg::EntityPhysics {
entity: uid.into(),
pos,
vel,
ori,
vel: vel.copied(),
ori: ori.copied(),
action_state: action_state.copied(),
});
}
@ -762,12 +765,12 @@ impl Server {
}
// Sync physics
for (entity, &uid, &pos, &vel, &ori, action_state, force_update) in (
for (entity, &uid, &pos, vel, ori, action_state, force_update) in (
&self.state.ecs().entities(),
&self.state.ecs().read_storage::<Uid>(),
&self.state.ecs().read_storage::<comp::Pos>(),
&self.state.ecs().read_storage::<comp::Vel>(),
&self.state.ecs().read_storage::<comp::Ori>(),
self.state.ecs().read_storage::<comp::Vel>().maybe(),
self.state.ecs().read_storage::<comp::Ori>().maybe(),
self.state.ecs().read_storage::<comp::ActionState>().maybe(),
self.state.ecs().read_storage::<comp::ForceUpdate>().maybe(),
)
@ -776,8 +779,8 @@ impl Server {
let msg = ServerMsg::EntityPhysics {
entity: uid.into(),
pos,
vel,
ori,
vel: vel.copied(),
ori: ori.copied(),
action_state: action_state.copied(),
};

View File

@ -26,6 +26,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
light += strength
* lights[i].light_col.rgb
* lights[i].light_col.a
* clamp(dot(normalize(light_pos - wpos), wnorm), LIGHT_AMBIENCE, 1.0);
}
return light;

View File

@ -144,20 +144,28 @@ impl Scene {
// Update light constants
let mut lights = (
&client.state().ecs().read_storage::<comp::Pos>(),
client.state().ecs().read_storage::<comp::Ori>().maybe(),
&client.state().ecs().read_storage::<comp::LightEmitter>(),
)
.join()
.filter(|(pos, _)| {
.filter(|(pos, _, _)| {
(pos.0.distance_squared(player_pos) as f32)
< self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS
})
.map(|(pos, light_emitter)| {
.map(|(pos, ori, light_emitter)| {
let rot = {
if let Some(o) = ori {
Mat3::rotation_z(-o.0.x.atan2(o.0.y))
} else {
Mat3::identity()
}
};
Light::new(
pos.0 + Vec3::unit_z(),
pos.0 + (rot * light_emitter.offset),
light_emitter.col,
light_emitter.strength,
)
}) // TODO: Don't add 1 to z!
})
.collect::<Vec<_>>();
lights.sort_by_key(|light| {
Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32