From bbbe03a033f63e8f7233e08e3f2c93a78dc8b324 Mon Sep 17 00:00:00 2001 From: CapsizeGlimmer <> Date: Thu, 23 Apr 2020 22:36:19 -0400 Subject: [PATCH 01/27] Implement /sudo command --- CHANGELOG.md | 1 + server/src/cmd.rs | 452 +++++++++++++++++++++++++++++++++------------- 2 files changed, 329 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 628f68ae7d..075a366cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added waypoints next to dungeons - Made players spawn in towns - Added non-uniform block heights +- Added `/sudo` command ### Changed diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 7bc96dde8f..2d54773cb7 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -40,12 +40,14 @@ pub struct ChatCommand { /// * `&mut Server` - the `Server` instance executing the command. /// * `EcsEntity` - an `Entity` corresponding to the player that invoked the /// command. + /// * `EcsEntity` - an `Entity` for the player on whom the command is + /// invoked. This differs from the previous argument when using /sudo /// * `String` - a `String` containing the part of the command after the /// keyword. /// * `&ChatCommand` - the command to execute with the above arguments. /// Handler functions must parse arguments from the the given `String` /// (`scan_fmt!` is included for this purpose). - handler: fn(&mut Server, EcsEntity, String, &ChatCommand), + handler: fn(&mut Server, EcsEntity, EcsEntity, String, &ChatCommand), } impl ChatCommand { @@ -55,7 +57,7 @@ impl ChatCommand { arg_fmt: &'static str, help_string: &'static str, needs_admin: bool, - handler: fn(&mut Server, EcsEntity, String, &ChatCommand), + handler: fn(&mut Server, EcsEntity, EcsEntity, String, &ChatCommand), ) -> Self { Self { keyword, @@ -80,10 +82,10 @@ impl ChatCommand { ); return; } else { - (self.handler)(server, entity, args, self); + (self.handler)(server, entity, entity, args, self); } } else { - (self.handler)(server, entity, args, self); + (self.handler)(server, entity, entity, args, self); } } } @@ -261,79 +263,116 @@ lazy_static! { true, handle_debug, ), + ChatCommand::new( + "sudo", + "{} {} {/.*/}", + "/sudo / [args...] : Run command as if you were another player", + true, + handle_sudo, + ), ]; } -fn handle_give(server: &mut Server, entity: EcsEntity, args: String, _action: &ChatCommand) { +fn handle_give( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + _action: &ChatCommand, +) { if let Ok(item) = assets::load_cloned(&args) { server .state .ecs() .write_storage::() - .get_mut(entity) + .get_mut(target) .map(|inv| inv.push(item)); let _ = server .state .ecs() .write_storage::() .insert( - entity, + target, comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Given), ); } else { - server.notify_client(entity, ServerMsg::private(String::from("Invalid item!"))); + server.notify_client(client, ServerMsg::private(String::from("Invalid item!"))); } } -fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_jump( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { - match server.state.read_component_cloned::(entity) { + match server.state.read_component_cloned::(target) { Some(current_pos) => { server .state - .write_component(entity, comp::Pos(current_pos.0 + Vec3::new(x, y, z))); - server.state.write_component(entity, comp::ForceUpdate); + .write_component(target, comp::Pos(current_pos.0 + Vec3::new(x, y, z))); + server.state.write_component(target, comp::ForceUpdate); }, None => server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no position.")), ), } } } -fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_goto( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { if server .state - .read_component_cloned::(entity) + .read_component_cloned::(target) .is_some() { server .state - .write_component(entity, comp::Pos(Vec3::new(x, y, z))); - server.state.write_component(entity, comp::ForceUpdate); + .write_component(target, comp::Pos(Vec3::new(x, y, z))); + server.state.write_component(target, comp::ForceUpdate); } else { server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no position.")), ); } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } -fn handle_kill(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_kill( + server: &mut Server, + _client: EcsEntity, + target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { server .state .ecs_mut() .write_storage::() - .get_mut(entity) + .get_mut(target) .map(|s| s.health.set_to(0, comp::HealthSource::Suicide)); } -fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_time( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + args: String, + action: &ChatCommand, +) { let time = scan_fmt_some!(&args, action.arg_fmt, String); let new_time = match time.as_ref().map(|s| s.as_str()) { Some("midnight") => NaiveTime::from_hms(0, 0, 0), @@ -349,7 +388,7 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch Ok(time) => time, Err(_) => { server.notify_client( - entity, + client, ServerMsg::private(format!("'{}' is not a valid time.", n)), ); return; @@ -368,7 +407,7 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch Some(time) => format!("It is {}", time.format("%H:%M").to_string()), None => String::from("Unknown Time"), }; - server.notify_client(entity, ServerMsg::private(msg)); + server.notify_client(client, ServerMsg::private(msg)); return; }, }; @@ -377,7 +416,7 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch new_time.num_seconds_from_midnight() as f64; server.notify_client( - entity, + client, ServerMsg::private(format!( "Time changed to: {}", new_time.format("%H:%M").to_string() @@ -385,43 +424,55 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch ); } -fn handle_health(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_health( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok(hp) = scan_fmt!(&args, action.arg_fmt, u32) { if let Some(stats) = server .state .ecs() .write_storage::() - .get_mut(entity) + .get_mut(target) { stats.health.set_to(hp, comp::HealthSource::Command); } else { server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no health.")), ); } } else { server.notify_client( - entity, + client, ServerMsg::private(String::from("You must specify health amount!")), ); } } -fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_alias( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { server .state .ecs_mut() .write_storage::() - .get_mut(entity) + .get_mut(target) .map(|player| player.alias = alias); // Update name on client player lists let ecs = server.state.ecs(); if let (Some(uid), Some(player)) = ( - ecs.read_storage::().get(entity), - ecs.read_storage::().get(entity), + ecs.read_storage::().get(target), + ecs.read_storage::().get(target), ) { let msg = ServerMsg::PlayerListUpdate(PlayerListUpdate::Alias( (*uid).into(), @@ -430,60 +481,72 @@ fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &C server.state.notify_registered_clients(msg); } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } -fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_tp( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { let ecs = server.state.ecs(); let opt_player = (&ecs.entities(), &ecs.read_storage::()) .join() .find(|(_, player)| player.alias == alias) .map(|(entity, _)| entity); - match server.state.read_component_cloned::(entity) { + match server.state.read_component_cloned::(target) { Some(_pos) => match opt_player { Some(player) => match server.state.read_component_cloned::(player) { Some(pos) => { - server.state.write_component(entity, pos); - server.state.write_component(entity, comp::ForceUpdate); + server.state.write_component(target, pos); + server.state.write_component(target, comp::ForceUpdate); }, None => server.notify_client( - entity, + client, ServerMsg::private(format!("Unable to teleport to player '{}'!", alias)), ), }, None => { server.notify_client( - entity, + client, ServerMsg::private(format!("Player '{}' not found!", alias)), ); server.notify_client( - entity, + client, ServerMsg::private(String::from(action.help_string)), ); }, }, None => { - server.notify_client(entity, ServerMsg::private(format!("You have no position!"))); + server.notify_client(client, ServerMsg::private(format!("You have no position!"))); }, } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } -fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_spawn( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { match scan_fmt_some!(&args, action.arg_fmt, String, npc::NpcBody, String) { (Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount) => { - if let Some(alignment) = parse_alignment(entity, &opt_align) { + if let Some(alignment) = parse_alignment(target, &opt_align) { let amount = opt_amount .and_then(|a| a.parse().ok()) .filter(|x| *x > 0) .unwrap_or(1) .min(10); - match server.state.read_component_cloned::(entity) { + match server.state.read_component_cloned::(target) { Some(pos) => { let agent = if let comp::Alignment::Owned(_) | comp::Alignment::Npc = alignment { @@ -517,7 +580,7 @@ fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &C if let Some(uid) = server.state.ecs().uid_from_entity(new_entity) { server.notify_client( - entity, + client, ServerMsg::private( format!("Spawned entity with ID: {}", uid).to_owned(), ), @@ -525,24 +588,30 @@ fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &C } } server.notify_client( - entity, + client, ServerMsg::private(format!("Spawned {} entities", amount).to_owned()), ); }, None => server.notify_client( - entity, + client, ServerMsg::private("You have no position!".to_owned()), ), } } }, _ => { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); }, } } -fn handle_players(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_players( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { let ecs = server.state.ecs(); let players = ecs.read_storage::(); let count = players.join().count(); @@ -560,26 +629,32 @@ fn handle_players(server: &mut Server, entity: EcsEntity, _args: String, _action s }); - server.notify_client(entity, ServerMsg::private(header_message + &player_list)); + server.notify_client(client, ServerMsg::private(header_message + &player_list)); } else { - server.notify_client(entity, ServerMsg::private(header_message)); + server.notify_client(client, ServerMsg::private(header_message)); } } -fn handle_build(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_build( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { if server .state .read_storage::() - .get(entity) + .get(target) .is_some() { server .state .ecs() .write_storage::() - .remove(entity); + .remove(target); server.notify_client( - entity, + client, ServerMsg::private(String::from("Toggled off build mode!")), ); } else { @@ -587,18 +662,24 @@ fn handle_build(server: &mut Server, entity: EcsEntity, _args: String, _action: .state .ecs() .write_storage::() - .insert(entity, comp::CanBuild); + .insert(target, comp::CanBuild); server.notify_client( - entity, + client, ServerMsg::private(String::from("Toggled on build mode!")), ); } } -fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_help( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { for cmd in CHAT_COMMANDS.iter() { - if !cmd.needs_admin || server.entity_is_admin(entity) { - server.notify_client(entity, ServerMsg::private(String::from(cmd.help_string))); + if !cmd.needs_admin || server.entity_is_admin(client) { + server.notify_client(client, ServerMsg::private(String::from(cmd.help_string))); } } } @@ -613,7 +694,13 @@ fn parse_alignment(owner: EcsEntity, alignment: &str) -> Option } } -fn handle_killnpcs(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_killnpcs( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { let ecs = server.state.ecs(); let mut stats = ecs.write_storage::(); let players = ecs.read_storage::(); @@ -627,23 +714,29 @@ fn handle_killnpcs(server: &mut Server, entity: EcsEntity, _args: String, _actio } else { "No NPCs on server.".to_string() }; - server.notify_client(entity, ServerMsg::private(text)); + server.notify_client(client, ServerMsg::private(text)); } -fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: &ChatCommand) { +fn handle_object( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + _action: &ChatCommand, +) { let obj_type = scan_fmt!(&args, _action.arg_fmt, String); let pos = server .state .ecs() .read_storage::() - .get(entity) + .get(target) .copied(); let ori = server .state .ecs() .read_storage::() - .get(entity) + .get(target) .copied(); /*let builder = server.state .create_object(pos, ori, obj_type) @@ -701,7 +794,7 @@ fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: Ok("crafting_bench") => comp::object::Body::CraftingBench, _ => { return server.notify_client( - entity, + client, ServerMsg::private(String::from("Object not found!")), ); }, @@ -723,18 +816,24 @@ fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: )) .build(); server.notify_client( - entity, + client, ServerMsg::private(format!( "Spawned: {}", obj_str_res.unwrap_or("") )), ); } else { - server.notify_client(entity, ServerMsg::private(format!("You have no position!"))); + server.notify_client(client, ServerMsg::private(format!("You have no position!"))); } } -fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_light( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { let (opt_r, opt_g, opt_b, opt_x, opt_y, opt_z, opt_s) = scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32); @@ -756,7 +855,7 @@ fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &C .state .ecs() .read_storage::() - .get(entity) + .get(target) .copied(); if let Some(pos) = pos { server @@ -767,19 +866,25 @@ fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &C .with(comp::ForceUpdate) .with(light_emitter) .build(); - server.notify_client(entity, ServerMsg::private(format!("Spawned object."))); + server.notify_client(client, ServerMsg::private(format!("Spawned object."))); } else { - server.notify_client(entity, ServerMsg::private(format!("You have no position!"))); + server.notify_client(client, ServerMsg::private(format!("You have no position!"))); } } -fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_lantern( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { let opt_s = scan_fmt_some!(&args, action.arg_fmt, f32); if server .state .read_storage::() - .get(entity) + .get(target) .is_some() { if let Some(s) = opt_s { @@ -787,11 +892,11 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: .state .ecs() .write_storage::() - .get_mut(entity) + .get_mut(target) { light.strength = s.max(0.1).min(10.0); server.notify_client( - entity, + client, ServerMsg::private(String::from("You adjusted flame strength.")), ); } @@ -800,9 +905,9 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: .state .ecs() .write_storage::() - .remove(entity); + .remove(target); server.notify_client( - entity, + client, ServerMsg::private(String::from("You put out the lantern.")), ); } @@ -811,7 +916,7 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: .state .ecs() .write_storage::() - .insert(entity, comp::LightEmitter { + .insert(target, comp::LightEmitter { offset: Vec3::new(0.5, 0.2, 0.8), col: Rgb::new(1.0, 0.75, 0.3), strength: if let Some(s) = opt_s { @@ -822,50 +927,68 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: }); server.notify_client( - entity, + client, ServerMsg::private(String::from("You lit your lantern.")), ); } } -fn handle_explosion(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_explosion( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { let power = scan_fmt!(&args, action.arg_fmt, f32).unwrap_or(8.0); let ecs = server.state.ecs(); - match server.state.read_component_cloned::(entity) { + match server.state.read_component_cloned::(target) { Some(pos) => { ecs.read_resource::>() .emit_now(ServerEvent::Explosion { pos: pos.0, power, - owner: ecs.read_storage::().get(entity).copied(), + owner: ecs.read_storage::().get(target).copied(), }) }, None => server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no position!")), ), } } -fn handle_waypoint(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { - match server.state.read_component_cloned::(entity) { +fn handle_waypoint( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { + match server.state.read_component_cloned::(target) { Some(pos) => { let _ = server .state .ecs() .write_storage::() - .insert(entity, comp::Waypoint::new(pos.0)); - server.notify_client(entity, ServerMsg::private(String::from("Waypoint set!"))); + .insert(target, comp::Waypoint::new(pos.0)); + server.notify_client(client, ServerMsg::private(String::from("Waypoint set!"))); }, None => server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no position!")), ), } } -fn handle_adminify(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_adminify( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + args: String, + action: &ChatCommand, +) { if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { let ecs = server.state.ecs(); let opt_player = (&ecs.entities(), &ecs.read_storage::()) @@ -883,18 +1006,31 @@ fn handle_adminify(server: &mut Server, entity: EcsEntity, args: String, action: }, None => { server.notify_client( - entity, + client, ServerMsg::private(format!("Player '{}' not found!", alias)), ); - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); }, } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } -fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_tell( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { + if client != target { + server.notify_client( + client, + ServerMsg::tell(String::from("It's rude to impersonate people")), + ); + return; + } if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { let ecs = server.state.ecs(); let msg = &args[alias.len()..args.len()]; @@ -903,11 +1039,11 @@ fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &Ch .find(|(_, player)| player.alias == alias) .map(|(entity, _)| entity) { - if player != entity { + if player != target { if msg.len() > 1 { if let Some(name) = ecs .read_storage::() - .get(entity) + .get(target) .map(|s| s.alias.clone()) { server.notify_client( @@ -915,53 +1051,60 @@ fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &Ch ServerMsg::tell(format!("[{}] tells:{}", name, msg)), ); server.notify_client( - entity, + client, ServerMsg::tell(format!("To [{}]:{}", alias, msg)), ); } else { server.notify_client( - entity, + client, ServerMsg::private(String::from("Failed to send message.")), ); } } else { server.notify_client( - entity, + client, ServerMsg::private(format!("[{}] wants to talk to you.", alias)), ); } } else { server.notify_client( - entity, + client, ServerMsg::private(format!("You can't /tell yourself.")), ); } } else { server.notify_client( - entity, + client, ServerMsg::private(format!("Player '{}' not found!", alias)), ); } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } #[cfg(not(feature = "worldgen"))] fn handle_debug_column( server: &mut Server, - entity: EcsEntity, + client: EcsEntity, + target: EcsEntity, _args: String, _action: &ChatCommand, ) { server.notify_client( - entity, + client, ServerMsg::private(String::from("Unsupported without worldgen enabled")), ); } #[cfg(feature = "worldgen")] -fn handle_debug_column(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_debug_column( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + args: String, + action: &ChatCommand, +) { let sim = server.world.sim(); let sampler = server.world.sample_columns(); if let Ok((x, y)) = scan_fmt!(&args, action.arg_fmt, i32, i32) { @@ -1020,15 +1163,15 @@ spawn_rate {:?} "#, )) }; if let Some(s) = foo() { - server.notify_client(entity, ServerMsg::private(s)); + server.notify_client(client, ServerMsg::private(s)); } else { server.notify_client( - entity, + client, ServerMsg::private(String::from("Not a pregenerated chunk.")), ); } } else { - server.notify_client(entity, ServerMsg::private(String::from(action.help_string))); + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); } } @@ -1048,12 +1191,18 @@ fn find_target( } } -fn handle_exp(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_exp( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { let (a_exp, a_alias) = scan_fmt_some!(&args, action.arg_fmt, i64, String); if let Some(exp) = a_exp { let ecs = server.state.ecs_mut(); - let target = find_target(&ecs, a_alias, entity); + let target = find_target(&ecs, a_alias, target); let mut error_msg = None; @@ -1071,17 +1220,23 @@ fn handle_exp(server: &mut Server, entity: EcsEntity, args: String, action: &Cha } if let Some(msg) = error_msg { - server.notify_client(entity, msg); + server.notify_client(client, msg); } } } -fn handle_level(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { +fn handle_level( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { let (a_lvl, a_alias) = scan_fmt_some!(&args, action.arg_fmt, u32, String); if let Some(lvl) = a_lvl { let ecs = server.state.ecs_mut(); - let target = find_target(&ecs, a_alias, entity); + let target = find_target(&ecs, a_alias, target); let mut error_msg = None; @@ -1104,19 +1259,25 @@ fn handle_level(server: &mut Server, entity: EcsEntity, args: String, action: &C } if let Some(msg) = error_msg { - server.notify_client(entity, msg); + server.notify_client(client, msg); } } } use common::comp::Item; -fn handle_debug(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { +fn handle_debug( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { if let Ok(items) = assets::load_glob::("common.items.debug.*") { server .state() .ecs() .write_storage::() - .get_mut(entity) + .get_mut(target) // TODO: Consider writing a `load_glob_cloned` in `assets` and using that here .map(|inv| inv.push_all_unique(items.iter().map(|item| item.as_ref().clone()))); let _ = server @@ -1124,12 +1285,12 @@ fn handle_debug(server: &mut Server, entity: EcsEntity, _args: String, _action: .ecs() .write_storage::() .insert( - entity, + target, comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Debug), ); } else { server.notify_client( - entity, + client, ServerMsg::private(String::from( "Debug items not found? Something is very broken.", )), @@ -1139,12 +1300,13 @@ fn handle_debug(server: &mut Server, entity: EcsEntity, _args: String, _action: fn handle_remove_lights( server: &mut Server, - entity: EcsEntity, + client: EcsEntity, + target: EcsEntity, args: String, action: &ChatCommand, ) { let opt_radius = scan_fmt_some!(&args, action.arg_fmt, f32); - let opt_player_pos = server.state.read_component_cloned::(entity); + let opt_player_pos = server.state.read_component_cloned::(target); let mut to_delete = vec![]; match opt_player_pos { @@ -1168,7 +1330,7 @@ fn handle_remove_lights( } }, None => server.notify_client( - entity, + client, ServerMsg::private(String::from("You have no position.")), ), } @@ -1182,7 +1344,49 @@ fn handle_remove_lights( } server.notify_client( - entity, + client, ServerMsg::private(String::from(format!("Removed {} lights!", size))), ); } + +fn handle_sudo( + server: &mut Server, + client: EcsEntity, + _target: EcsEntity, + args: String, + action: &ChatCommand, +) { + if let (Some(player_alias), Some(mut cmd), cmd_args) = + scan_fmt_some!(&args, action.arg_fmt, String, String, String) + { + let cmd_args = cmd_args.unwrap_or(String::from("")); + if cmd.chars().next() == Some('/') { + cmd.remove(0); + } + if let Some(action) = CHAT_COMMANDS.iter().find(|c| c.keyword == cmd) { + let mut entity_opt = None; + let ecs = server.state.ecs(); + for (ent, player) in (&ecs.entities(), &ecs.read_storage::()).join() { + if player.alias == player_alias { + entity_opt = Some(ent); + break; + } + } + if let Some(entity) = entity_opt { + (action.handler)(server, client, entity, cmd_args, action); + } else { + server.notify_client( + client, + ServerMsg::private(format!("Could not find that player")), + ); + } + } else { + server.notify_client( + client, + ServerMsg::private(format!("Unknown command: /{}", cmd)), + ); + } + } else { + server.notify_client(client, ServerMsg::private(String::from(action.help_string))); + } +} From 29fd45eb5245c2d38bf67996a199959422f24898 Mon Sep 17 00:00:00 2001 From: CapsizeGlimmer <> Date: Fri, 24 Apr 2020 12:17:56 -0400 Subject: [PATCH 02/27] `/sudo player /kill` now lists the sudoer as killing the target --- server/src/cmd.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 2d54773cb7..7b747a8f62 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -353,17 +353,26 @@ fn handle_goto( fn handle_kill( server: &mut Server, - _client: EcsEntity, + client: EcsEntity, target: EcsEntity, _args: String, _action: &ChatCommand, ) { + let reason = if client == target { + comp::HealthSource::Suicide + } else { + if let Some(uid) = server.state.read_storage::().get(client) { + comp::HealthSource::Attack { by: *uid } + } else { + comp::HealthSource::Command + } + }; server .state .ecs_mut() .write_storage::() .get_mut(target) - .map(|s| s.health.set_to(0, comp::HealthSource::Suicide)); + .map(|s| s.health.set_to(0, reason)); } fn handle_time( From 2afa5d06b169c5aa76d17b8f89938f7c24a7833f Mon Sep 17 00:00:00 2001 From: CapsizeGlimmer <> Date: Sat, 25 Apr 2020 13:18:29 -0400 Subject: [PATCH 03/27] Fixed mutability in /sudo --- server/src/cmd.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 7b747a8f62..f8df738d0a 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1365,22 +1365,21 @@ fn handle_sudo( args: String, action: &ChatCommand, ) { - if let (Some(player_alias), Some(mut cmd), cmd_args) = + if let (Some(player_alias), Some(cmd), cmd_args) = scan_fmt_some!(&args, action.arg_fmt, String, String, String) { let cmd_args = cmd_args.unwrap_or(String::from("")); - if cmd.chars().next() == Some('/') { - cmd.remove(0); - } + let cmd = if cmd.chars().next() == Some('/') { + cmd.chars().skip(1).collect() + } else { + cmd + }; if let Some(action) = CHAT_COMMANDS.iter().find(|c| c.keyword == cmd) { - let mut entity_opt = None; let ecs = server.state.ecs(); - for (ent, player) in (&ecs.entities(), &ecs.read_storage::()).join() { - if player.alias == player_alias { - entity_opt = Some(ent); - break; - } - } + let entity_opt = (&ecs.entities(), &ecs.read_storage::()) + .join() + .find(|(_, player)| player.alias == player_alias) + .map(|(entity, _)| entity); if let Some(entity) = entity_opt { (action.handler)(server, client, entity, cmd_args, action); } else { From b2c8dc080623dad4ace3be5abfc6802bdd29b46a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 15:20:16 +0100 Subject: [PATCH 04/27] Added terrain sprite LoD --- common/src/figure/mod.rs | 2 +- common/src/vol.rs | 10 +- common/src/volumes/mod.rs | 1 + common/src/volumes/scaled.rs | 47 ++++ voxygen/src/mesh/mod.rs | 4 +- voxygen/src/mesh/segment.rs | 60 +++-- voxygen/src/mesh/terrain.rs | 6 +- voxygen/src/scene/figure/load.rs | 2 +- voxygen/src/scene/terrain.rs | 420 ++++++++++++++++--------------- 9 files changed, 329 insertions(+), 223 deletions(-) create mode 100644 common/src/volumes/scaled.rs diff --git a/common/src/figure/mod.rs b/common/src/figure/mod.rs index 0be11c7bf6..12b5e05d32 100644 --- a/common/src/figure/mod.rs +++ b/common/src/figure/mod.rs @@ -2,7 +2,7 @@ pub mod cell; pub mod mat_cell; pub use mat_cell::Material; -use self::{cell::Cell, mat_cell::MatCell}; +pub use self::{cell::Cell, mat_cell::MatCell}; use crate::{ vol::{IntoFullPosIterator, IntoFullVolIterator, ReadVol, SizedVol, Vox, WriteVol}, volumes::dyna::Dyna, diff --git a/common/src/vol.rs b/common/src/vol.rs index 8740e60917..85626c37d7 100644 --- a/common/src/vol.rs +++ b/common/src/vol.rs @@ -1,4 +1,4 @@ -use crate::ray::Ray; +use crate::{ray::Ray, volumes::scaled::Scaled}; use std::fmt::Debug; use vek::*; @@ -24,6 +24,13 @@ pub trait Vox: Sized + Clone + PartialEq { pub trait BaseVol { type Vox: Vox; type Error: Debug; + + fn scaled_by(&self, scale: Vec3) -> Scaled + where + Self: Sized, + { + Scaled { inner: self, scale } + } } /// Implementing `BaseVol` for any `&'a BaseVol` makes it possible to implement @@ -159,6 +166,7 @@ where /// Unfortunately we can't just implement `IntoIterator` in this generic way /// because it's defined in another crate. That's actually the only reason why /// the trait `IntoFullVolIterator` exists. +// TODO: See whether relaxed orphan rules permit this to be replaced now impl<'a, T: 'a + SizedVol> IntoFullVolIterator<'a> for &'a T where Self: IntoVolIterator<'a>, diff --git a/common/src/volumes/mod.rs b/common/src/volumes/mod.rs index b84e75b7c8..6e8a9d6f10 100644 --- a/common/src/volumes/mod.rs +++ b/common/src/volumes/mod.rs @@ -1,4 +1,5 @@ pub mod chunk; pub mod dyna; +pub mod scaled; pub mod vol_grid_2d; pub mod vol_grid_3d; diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs new file mode 100644 index 0000000000..4f70b45538 --- /dev/null +++ b/common/src/volumes/scaled.rs @@ -0,0 +1,47 @@ +use crate::vol::{BaseVol, ReadVol, SizedVol, Vox}; +use vek::*; + +pub struct Scaled<'a, V> { + pub inner: &'a V, + pub scale: Vec3, +} + +impl<'a, V: BaseVol> BaseVol for Scaled<'a, V> { + type Error = V::Error; + type Vox = V::Vox; +} + +impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { + #[inline(always)] + fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { + let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32); + let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32); + (-search_size.x / 2..search_size.x / 2) + .map(|i| { + (-search_size.y / 2..search_size.y / 2).map(move |j| { + (-search_size.z / 2..search_size.z / 2).map(move |k| Vec3::new(i, j, k)) + }) + }) + .flatten() + .flatten() + .map(|offs| self.inner.get(pos + offs)) + .find(|vox| vox.as_ref().map(|v| !v.is_empty()).unwrap_or(false)) + .unwrap_or_else(|| self.inner.get(pos)) + } +} + +impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> { + #[inline(always)] + fn lower_bound(&self) -> Vec3 { + self.inner + .lower_bound() + .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32) + } + + #[inline(always)] + fn upper_bound(&self) -> Vec3 { + self.inner + .upper_bound() + .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32) + } +} diff --git a/voxygen/src/mesh/mod.rs b/voxygen/src/mesh/mod.rs index 86bd6cc55c..695c1e617b 100644 --- a/voxygen/src/mesh/mod.rs +++ b/voxygen/src/mesh/mod.rs @@ -4,14 +4,14 @@ mod vol; use crate::render::{self, Mesh}; -pub trait Meshable { +pub trait Meshable<'a, P: render::Pipeline, T: render::Pipeline> { type Pipeline: render::Pipeline; type TranslucentPipeline: render::Pipeline; type Supplement; // Generate meshes - one opaque, one translucent fn generate_mesh( - &self, + &'a self, supp: Self::Supplement, ) -> (Mesh, Mesh); } diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index 962a6ed93e..2d8584442b 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -3,27 +3,43 @@ use crate::{ render::{self, FigurePipeline, Mesh, SpritePipeline}, }; use common::{ - figure::Segment, + figure::Cell, util::{linear_to_srgb, srgb_to_linear}, - vol::{IntoFullVolIterator, ReadVol, Vox}, + vol::{BaseVol, ReadVol, SizedVol, Vox}, }; use vek::*; type FigureVertex = ::Vertex; type SpriteVertex = ::Vertex; -impl Meshable for Segment { +impl<'a, V: 'a> Meshable<'a, FigurePipeline, FigurePipeline> for V +where + V: BaseVol + ReadVol + SizedVol, + /* TODO: Use VolIterator instead of manually iterating + * &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>, + * &'a V: BaseVol, */ +{ type Pipeline = FigurePipeline; - type Supplement = Vec3; + type Supplement = (Vec3, Vec3); type TranslucentPipeline = FigurePipeline; fn generate_mesh( - &self, - offs: Self::Supplement, + &'a self, + (offs, scale): Self::Supplement, ) -> (Mesh, Mesh) { let mut mesh = Mesh::new(); - for (pos, vox) in self.full_vol_iter() { + let vol_iter = (self.lower_bound().x..self.upper_bound().x) + .map(|i| { + (self.lower_bound().y..self.upper_bound().y).map(move |j| { + (self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k)) + }) + }) + .flatten() + .flatten() + .map(|pos| (pos, self.get(pos).unwrap())); + + for (pos, vox) in vol_iter { if let Some(col) = vox.get_color() { vol::push_vox_verts( &mut mesh, @@ -32,7 +48,7 @@ impl Meshable for Segment { &[[[Rgba::from_opaque(col); 3]; 3]; 3], |origin, norm, col, light, ao| { FigureVertex::new( - origin, + origin * scale, norm, linear_to_srgb(srgb_to_linear(col) * light), ao, @@ -62,18 +78,34 @@ impl Meshable for Segment { } } -impl Meshable for Segment { +impl<'a, V: 'a> Meshable<'a, SpritePipeline, SpritePipeline> for V +where + V: BaseVol + ReadVol + SizedVol, + /* TODO: Use VolIterator instead of manually iterating + * &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>, + * &'a V: BaseVol, */ +{ type Pipeline = SpritePipeline; - type Supplement = Vec3; + type Supplement = (Vec3, Vec3); type TranslucentPipeline = SpritePipeline; fn generate_mesh( - &self, - offs: Self::Supplement, + &'a self, + (offs, scale): Self::Supplement, ) -> (Mesh, Mesh) { let mut mesh = Mesh::new(); - for (pos, vox) in self.full_vol_iter() { + let vol_iter = (self.lower_bound().x..self.upper_bound().x) + .map(|i| { + (self.lower_bound().y..self.upper_bound().y).map(move |j| { + (self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k)) + }) + }) + .flatten() + .flatten() + .map(|pos| (pos, self.get(pos).unwrap())); + + for (pos, vox) in vol_iter { if let Some(col) = vox.get_color() { vol::push_vox_verts( &mut mesh, @@ -82,7 +114,7 @@ impl Meshable for Segment { &[[[Rgba::from_opaque(col); 3]; 3]; 3], |origin, norm, col, light, ao| { SpriteVertex::new( - origin, + origin * scale, norm, linear_to_srgb(srgb_to_linear(col) * light), ao, diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index fa8e94ea01..c71b959c9b 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -198,15 +198,15 @@ fn calc_light + ReadVol + Debug>( } } -impl + ReadVol + Debug> Meshable - for VolGrid2d +impl<'a, V: RectRasterableVol + ReadVol + Debug> + Meshable<'a, TerrainPipeline, FluidPipeline> for VolGrid2d { type Pipeline = TerrainPipeline; type Supplement = Aabb; type TranslucentPipeline = FluidPipeline; fn generate_mesh( - &self, + &'a self, range: Self::Supplement, ) -> (Mesh, Mesh) { let mut light = calc_light(range, self); diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 5f9762bcf3..cfd6e86dc8 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -55,7 +55,7 @@ fn graceful_load_mat_segment_flipped(mesh_name: &str) -> MatSegment { } fn generate_mesh(segment: &Segment, offset: Vec3) -> Mesh { - Meshable::::generate_mesh(segment, offset).0 + Meshable::::generate_mesh(segment, (offset, Vec3::one())).0 } pub fn load_mesh(mesh_name: &str, position: Vec3) -> Mesh { diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index b6bd3f4450..1d49269eaa 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -314,7 +314,7 @@ pub struct Terrain { mesh_todo: HashMap, ChunkMeshState>, // GPU data - sprite_models: HashMap<(BlockKind, usize), Model>, + sprite_models: HashMap<(BlockKind, usize), Vec>>, waves: Texture, phantom: PhantomData, @@ -326,16 +326,24 @@ impl Terrain { // with worker threads that are meshing chunks. let (send, recv) = channel::unbounded(); - let mut make_model = |s, offset| { - renderer - .create_model( - &Meshable::::generate_mesh( - &Segment::from(assets::load_expect::(s).as_ref()), - offset, - ) - .0, - ) - .unwrap() + let mut make_models = |s, offset| { + let scaled = [1.0, 0.75, 0.3, 0.2]; + scaled + .iter() + .map(|lod_scale| Vec3::broadcast(*lod_scale)) + .map(|lod_scale| { + renderer + .create_model( + &Meshable::::generate_mesh( + &Segment::from(assets::load_expect::(s).as_ref()) + .scaled_by(lod_scale), + (offset * lod_scale, Vec3::one() / lod_scale), + ) + .0, + ) + .unwrap() + }) + .collect::>() }; Self { @@ -347,28 +355,28 @@ impl Terrain { // Windows ( (BlockKind::Window1, 0), - make_model( + make_models( "voxygen.voxel.sprite.window.window-0", Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window2, 0), - make_model( + make_models( "voxygen.voxel.sprite.window.window-1", Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window3, 0), - make_model( + make_models( "voxygen.voxel.sprite.window.window-2", Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window4, 0), - make_model( + make_models( "voxygen.voxel.sprite.window.window-3", Vec3::new(-5.5, -5.5, 0.0), ), @@ -376,49 +384,49 @@ impl Terrain { // Cacti ( (BlockKind::LargeCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.large_cactus", Vec3::new(-13.5, -5.5, 0.0), ), ), ( (BlockKind::LargeCactus, 1), - make_model( + make_models( "voxygen.voxel.sprite.cacti.tall", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BarrelCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.barrel_cactus", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::RoundCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.cactus_round", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.cactus_short", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MedFlatCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.flat_cactus_med", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortFlatCactus, 0), - make_model( + make_models( "voxygen.voxel.sprite.cacti.flat_cactus_short", Vec3::new(-6.0, -6.0, 0.0), ), @@ -426,7 +434,7 @@ impl Terrain { // Fruit ( (BlockKind::Apple, 0), - make_model( + make_models( "voxygen.voxel.sprite.fruit.apple", Vec3::new(-6.0, -6.0, 0.0), ), @@ -434,140 +442,140 @@ impl Terrain { // Flowers ( (BlockKind::BlueFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 1), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 2), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 3), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 4), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 5), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_6", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::BlueFlower, 6), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_blue_7", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::PinkFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_pink_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::PinkFlower, 1), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_pink_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::PinkFlower, 2), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_pink_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::PinkFlower, 3), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_pink_4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::PurpleFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_purple_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::RedFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_red_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::RedFlower, 1), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_red_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::RedFlower, 2), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_red_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WhiteFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_white_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WhiteFlower, 1), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_white_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::YellowFlower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.flower_purple_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Sunflower, 0), - make_model( + make_models( "voxygen.voxel.sprite.flowers.sunflower_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Sunflower, 1), - make_model( + make_models( "voxygen.voxel.sprite.flowers.sunflower_2", Vec3::new(-6.0, -6.0, 0.0), ), @@ -575,315 +583,315 @@ impl Terrain { // Grass ( (BlockKind::LongGrass, 0), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 1), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 2), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 3), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 4), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 5), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_6", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::LongGrass, 6), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_long_7", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MediumGrass, 0), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_med_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MediumGrass, 1), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_med_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MediumGrass, 2), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_med_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MediumGrass, 3), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_med_4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::MediumGrass, 4), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_med_5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortGrass, 0), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_short_1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortGrass, 1), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_short_2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortGrass, 2), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_short_3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortGrass, 3), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_short_4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::ShortGrass, 4), - make_model( + make_models( "voxygen.voxel.sprite.grass.grass_short_5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 0), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 1), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 2), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 3), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 4), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 5), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 6), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-6", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 7), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-7", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 8), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-8", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 9), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-9", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Mushroom, 10), - make_model( + make_models( "voxygen.voxel.sprite.mushrooms.mushroom-10", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Liana, 0), - make_model( + make_models( "voxygen.voxel.sprite.lianas.liana-0", Vec3::new(-1.5, -0.5, -88.0), ), ), ( (BlockKind::Liana, 1), - make_model( + make_models( "voxygen.voxel.sprite.lianas.liana-1", Vec3::new(-1.0, -0.5, -55.0), ), ), ( (BlockKind::Velorite, 0), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_ore", Vec3::new(-5.0, -5.0, -5.0), ), ), ( (BlockKind::VeloriteFrag, 0), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_1", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 1), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_2", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 2), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_3", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 3), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_4", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 4), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_5", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 5), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_6", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 6), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_7", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 7), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_8", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 8), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_9", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::VeloriteFrag, 9), - make_model( + make_models( "voxygen.voxel.sprite.velorite.velorite_10", Vec3::new(-3.0, -5.0, 0.0), ), ), ( (BlockKind::Chest, 0), - make_model( + make_models( "voxygen.voxel.sprite.chests.chest", Vec3::new(-7.0, -5.0, -0.0), ), ), ( (BlockKind::Chest, 1), - make_model( + make_models( "voxygen.voxel.sprite.chests.chest_gold", Vec3::new(-7.0, -5.0, -0.0), ), ), ( (BlockKind::Chest, 2), - make_model( + make_models( "voxygen.voxel.sprite.chests.chest_dark", Vec3::new(-7.0, -5.0, -0.0), ), ), ( (BlockKind::Chest, 3), - make_model( + make_models( "voxygen.voxel.sprite.chests.chest_vines", Vec3::new(-7.0, -5.0, -0.0), ), @@ -891,7 +899,7 @@ impl Terrain { //Welwitch ( (BlockKind::Welwitch, 0), - make_model( + make_models( "voxygen.voxel.sprite.welwitch.1", Vec3::new(-15.0, -17.0, -0.0), ), @@ -899,49 +907,49 @@ impl Terrain { //Pumpkins ( (BlockKind::Pumpkin, 0), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.1", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Pumpkin, 1), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.2", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Pumpkin, 2), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.3", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Pumpkin, 3), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.4", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Pumpkin, 4), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.5", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Pumpkin, 5), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.6", Vec3::new(-7.0, -6.5, -0.0), ), ), ( (BlockKind::Pumpkin, 6), - make_model( + make_models( "voxygen.voxel.sprite.pumpkin.7", Vec3::new(-7.0, -9.5, -0.0), ), @@ -949,21 +957,21 @@ impl Terrain { //Lingonberries ( (BlockKind::LingonBerry, 0), - make_model( + make_models( "voxygen.voxel.sprite.lingonberry.1", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LingonBerry, 1), - make_model( + make_models( "voxygen.voxel.sprite.lingonberry.2", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LingonBerry, 2), - make_model( + make_models( "voxygen.voxel.sprite.lingonberry.3", Vec3::new(-6.0, -6.0, -0.0), ), @@ -971,70 +979,70 @@ impl Terrain { // Leafy Plants ( (BlockKind::LeafyPlant, 0), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.1", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 1), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.2", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 2), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.3", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 3), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.4", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 4), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.5", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 5), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.6", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 6), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.7", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 7), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.8", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 8), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.9", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::LeafyPlant, 9), - make_model( + make_models( "voxygen.voxel.sprite.leafy_plant.10", Vec3::new(-6.0, -6.0, -0.0), ), @@ -1042,77 +1050,77 @@ impl Terrain { // Ferns ( (BlockKind::Fern, 0), - make_model("voxygen.voxel.sprite.ferns.1", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.1", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 1), - make_model("voxygen.voxel.sprite.ferns.2", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.2", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 2), - make_model("voxygen.voxel.sprite.ferns.3", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.3", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 3), - make_model("voxygen.voxel.sprite.ferns.4", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.4", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 4), - make_model("voxygen.voxel.sprite.ferns.5", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.5", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 5), - make_model("voxygen.voxel.sprite.ferns.6", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.6", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 6), - make_model("voxygen.voxel.sprite.ferns.7", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.7", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 7), - make_model("voxygen.voxel.sprite.ferns.8", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.8", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 8), - make_model("voxygen.voxel.sprite.ferns.9", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.9", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 9), - make_model("voxygen.voxel.sprite.ferns.10", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.10", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 10), - make_model("voxygen.voxel.sprite.ferns.11", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.11", Vec3::new(-6.0, -6.0, -0.0)), ), ( (BlockKind::Fern, 11), - make_model("voxygen.voxel.sprite.ferns.12", Vec3::new(-6.0, -6.0, -0.0)), + make_models("voxygen.voxel.sprite.ferns.12", Vec3::new(-6.0, -6.0, -0.0)), ), // Dead Bush ( (BlockKind::DeadBush, 0), - make_model( + make_models( "voxygen.voxel.sprite.dead_bush.1", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::DeadBush, 1), - make_model( + make_models( "voxygen.voxel.sprite.dead_bush.2", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::DeadBush, 2), - make_model( + make_models( "voxygen.voxel.sprite.dead_bush.3", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::DeadBush, 3), - make_model( + make_models( "voxygen.voxel.sprite.dead_bush.4", Vec3::new(-6.0, -6.0, -0.0), ), @@ -1120,63 +1128,63 @@ impl Terrain { // Blueberries ( (BlockKind::Blueberry, 0), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.1", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 1), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.2", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 2), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.3", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 3), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.4", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 4), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.5", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 5), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.6", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 6), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.7", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 7), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.8", Vec3::new(-6.0, -6.0, -0.0), ), ), ( (BlockKind::Blueberry, 8), - make_model( + make_models( "voxygen.voxel.sprite.blueberry.9", Vec3::new(-6.0, -6.0, -0.0), ), @@ -1184,47 +1192,47 @@ impl Terrain { // Ember ( (BlockKind::Ember, 0), - make_model("voxygen.voxel.sprite.ember.1", Vec3::new(-7.0, -7.0, -2.9)), + make_models("voxygen.voxel.sprite.ember.1", Vec3::new(-7.0, -7.0, -2.9)), ), // Corn ( (BlockKind::Corn, 0), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Corn, 1), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Corn, 2), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Corn, 3), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Corn, 4), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Corn, 5), - make_model( + make_models( "voxygen.voxel.sprite.corn.corn-5", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1232,70 +1240,70 @@ impl Terrain { // Yellow Wheat ( (BlockKind::WheatYellow, 0), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 1), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 2), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 3), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 4), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 5), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 6), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-6", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 7), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-7", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 8), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-8", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatYellow, 9), - make_model( + make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-9", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1303,70 +1311,70 @@ impl Terrain { // Green Wheat ( (BlockKind::WheatGreen, 0), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 1), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 2), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 3), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 4), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 5), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-5", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 6), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-6", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 7), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-7", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 8), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-8", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::WheatGreen, 9), - make_model( + make_models( "voxygen.voxel.sprite.wheat_green.wheat-9", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1374,21 +1382,21 @@ impl Terrain { // Cabbage ( (BlockKind::Cabbage, 0), - make_model( + make_models( "voxygen.voxel.sprite.cabbage.cabbage-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Cabbage, 1), - make_model( + make_models( "voxygen.voxel.sprite.cabbage.cabbage-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Cabbage, 2), - make_model( + make_models( "voxygen.voxel.sprite.cabbage.cabbage-2", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1396,42 +1404,42 @@ impl Terrain { // Flax ( (BlockKind::Flax, 0), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-0", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Flax, 1), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-1", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Flax, 2), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-2", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Flax, 3), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-3", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Flax, 4), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-4", Vec3::new(-6.0, -6.0, 0.0), ), ), ( (BlockKind::Flax, 5), - make_model( + make_models( "voxygen.voxel.sprite.flax.flax-5", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1439,98 +1447,98 @@ impl Terrain { // Carrot ( (BlockKind::Carrot, 0), - make_model( + make_models( "voxygen.voxel.sprite.carrot.0", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Carrot, 1), - make_model( + make_models( "voxygen.voxel.sprite.carrot.1", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Carrot, 2), - make_model( + make_models( "voxygen.voxel.sprite.carrot.2", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Carrot, 3), - make_model( + make_models( "voxygen.voxel.sprite.carrot.3", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Carrot, 4), - make_model( + make_models( "voxygen.voxel.sprite.carrot.4", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Carrot, 5), - make_model( + make_models( "voxygen.voxel.sprite.carrot.5", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Tomato, 0), - make_model("voxygen.voxel.sprite.tomato.0", Vec3::new(-5.5, -5.5, 0.0)), + make_models("voxygen.voxel.sprite.tomato.0", Vec3::new(-5.5, -5.5, 0.0)), ), ( (BlockKind::Tomato, 1), - make_model("voxygen.voxel.sprite.tomato.1", Vec3::new(-5.5, -5.5, 0.0)), + make_models("voxygen.voxel.sprite.tomato.1", Vec3::new(-5.5, -5.5, 0.0)), ), ( (BlockKind::Tomato, 2), - make_model("voxygen.voxel.sprite.tomato.2", Vec3::new(-5.5, -5.5, 0.0)), + make_models("voxygen.voxel.sprite.tomato.2", Vec3::new(-5.5, -5.5, 0.0)), ), ( (BlockKind::Tomato, 3), - make_model("voxygen.voxel.sprite.tomato.3", Vec3::new(-5.5, -5.5, 0.0)), + make_models("voxygen.voxel.sprite.tomato.3", Vec3::new(-5.5, -5.5, 0.0)), ), ( (BlockKind::Tomato, 4), - make_model("voxygen.voxel.sprite.tomato.4", Vec3::new(-5.5, -5.5, 0.0)), + make_models("voxygen.voxel.sprite.tomato.4", Vec3::new(-5.5, -5.5, 0.0)), ), // Radish ( (BlockKind::Radish, 0), - make_model( + make_models( "voxygen.voxel.sprite.radish.0", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Radish, 1), - make_model( + make_models( "voxygen.voxel.sprite.radish.1", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Radish, 2), - make_model( + make_models( "voxygen.voxel.sprite.radish.2", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Radish, 3), - make_model( + make_models( "voxygen.voxel.sprite.radish.3", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Radish, 4), - make_model( + make_models( "voxygen.voxel.sprite.radish.4", Vec3::new(-5.5, -5.5, -0.25), ), @@ -1538,42 +1546,42 @@ impl Terrain { // Turnip ( (BlockKind::Turnip, 0), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-0", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Turnip, 1), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-1", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Turnip, 2), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-2", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Turnip, 3), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-3", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Turnip, 4), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-4", Vec3::new(-5.5, -5.5, -0.25), ), ), ( (BlockKind::Turnip, 5), - make_model( + make_models( "voxygen.voxel.sprite.turnip.turnip-5", Vec3::new(-5.5, -5.5, -0.25), ), @@ -1581,7 +1589,7 @@ impl Terrain { // Coconut ( (BlockKind::Coconut, 0), - make_model( + make_models( "voxygen.voxel.sprite.fruit.coconut", Vec3::new(-6.0, -6.0, 0.0), ), @@ -1589,7 +1597,7 @@ impl Terrain { // Scarecrow ( (BlockKind::Scarecrow, 0), - make_model( + make_models( "voxygen.voxel.sprite.misc.scarecrow", Vec3::new(-9.5, -3.0, -0.25), ), @@ -1597,7 +1605,7 @@ impl Terrain { // Street Light ( (BlockKind::StreetLamp, 0), - make_model( + make_models( "voxygen.voxel.sprite.misc.street_lamp", Vec3::new(-4.5, -4.5, 0.0), ), @@ -1605,7 +1613,7 @@ impl Terrain { // Door ( (BlockKind::Door, 0), - make_model( + make_models( "voxygen.voxel.sprite.door.door-0", Vec3::new(-5.5, -5.5, 0.0), ), @@ -2001,16 +2009,26 @@ impl Terrain { // Terrain sprites for (pos, chunk) in chunk_iter.clone() { if chunk.visible { - const SPRITE_RENDER_DISTANCE: f32 = 128.0; + const SPRITE_RENDER_DISTANCE: f32 = 200.0; + const SPRITE_DETAIL_LOW_DISTANCE: f32 = 120.0; + const SPRITE_DETAIL_MID_DISTANCE: f32 = 64.0; + const SPRITE_DETAIL_HIGH_DISTANCE: f32 = 32.0; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); - if Vec2::from(focus_pos).distance_squared(chunk_center) - < SPRITE_RENDER_DISTANCE * SPRITE_RENDER_DISTANCE - { + let dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center); + if dist_sqrd < SPRITE_RENDER_DISTANCE.powf(2.0) { for (kind, instances) in &chunk.sprite_instances { renderer.render_sprites( - &self.sprite_models[&kind], + if dist_sqrd < SPRITE_DETAIL_HIGH_DISTANCE.powf(2.0) { + &self.sprite_models[&kind][0] + } else if dist_sqrd < SPRITE_DETAIL_MID_DISTANCE.powf(2.0) { + &self.sprite_models[&kind][1] + } else if dist_sqrd < SPRITE_DETAIL_LOW_DISTANCE.powf(2.0) { + &self.sprite_models[&kind][2] + } else { + &self.sprite_models[&kind][3] + }, globals, &instances, lights, From e84c2aa1dbf201f0d86c16481104f70a9adf5d91 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 15:26:07 +0100 Subject: [PATCH 05/27] Fixed gaps in LoD sprites --- common/src/volumes/scaled.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index 4f70b45538..aa7338352e 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -35,13 +35,13 @@ impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> { fn lower_bound(&self) -> Vec3 { self.inner .lower_bound() - .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32) + .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32) } #[inline(always)] fn upper_bound(&self) -> Vec3 { self.inner .upper_bound() - .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32) + .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32) } } From 59f4161f5cb1eef6a74b45d8243a4df976365a4f Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 15:42:06 +0100 Subject: [PATCH 06/27] Properly fixed all gaps on positive bound for scaled volumes --- common/src/volumes/scaled.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index aa7338352e..e650024f1e 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -35,13 +35,13 @@ impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> { fn lower_bound(&self) -> Vec3 { self.inner .lower_bound() - .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32) + .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32) } #[inline(always)] fn upper_bound(&self) -> Vec3 { self.inner .upper_bound() - .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32) + .map2(self.scale, |e, scale| ((e as f32 - 1.0) * scale).floor() as i32 + 1) } } From e498d78b6c859a563548d3e83dcb7407e1963a80 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 16:01:24 +0100 Subject: [PATCH 07/27] Fixed boundary meshing issue for scaled terrain sprites --- common/src/volumes/scaled.rs | 13 +++++++------ voxygen/src/mesh/segment.rs | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index e650024f1e..c951d5c04c 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -16,10 +16,11 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32); let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32); - (-search_size.x / 2..search_size.x / 2) + let range_iter = |x| std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })).take(x as usize * 2 + 1); + range_iter(search_size.x / 2) .map(|i| { - (-search_size.y / 2..search_size.y / 2).map(move |j| { - (-search_size.z / 2..search_size.z / 2).map(move |k| Vec3::new(i, j, k)) + range_iter(search_size.y / 2).map(move |j| { + range_iter(search_size.z / 2).map(move |k| Vec3::new(i, j, k)) }) }) .flatten() @@ -40,8 +41,8 @@ impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> { #[inline(always)] fn upper_bound(&self) -> Vec3 { - self.inner - .upper_bound() - .map2(self.scale, |e, scale| ((e as f32 - 1.0) * scale).floor() as i32 + 1) + self.inner.upper_bound().map2(self.scale, |e, scale| { + (e as f32 * scale).ceil() as i32 + 1 + }) } } diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index 2d8584442b..fff654f888 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -37,7 +37,7 @@ where }) .flatten() .flatten() - .map(|pos| (pos, self.get(pos).unwrap())); + .map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty()))); for (pos, vox) in vol_iter { if let Some(col) = vox.get_color() { @@ -103,7 +103,7 @@ where }) .flatten() .flatten() - .map(|pos| (pos, self.get(pos).unwrap())); + .map(|pos| (pos, self.get(pos).map(|x| *x).unwrap_or(Vox::empty()))); for (pos, vox) in vol_iter { if let Some(col) = vox.get_color() { From 1d75f4815b74f0d50a6ce24fbcf613e069e077c1 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 16:08:51 +0100 Subject: [PATCH 08/27] Massively reduced 'popping' of LoD terrain sprites --- common/src/volumes/scaled.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index c951d5c04c..19763d3a5f 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -16,12 +16,14 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32); let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32); - let range_iter = |x| std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })).take(x as usize * 2 + 1); + let range_iter = |x| { + std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })) + .take((x as usize * 2).max(1) - 1) + }; range_iter(search_size.x / 2) .map(|i| { - range_iter(search_size.y / 2).map(move |j| { - range_iter(search_size.z / 2).map(move |k| Vec3::new(i, j, k)) - }) + range_iter(search_size.y / 2) + .map(move |j| range_iter(search_size.z / 2).map(move |k| Vec3::new(i, j, k))) }) .flatten() .flatten() @@ -41,8 +43,8 @@ impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> { #[inline(always)] fn upper_bound(&self) -> Vec3 { - self.inner.upper_bound().map2(self.scale, |e, scale| { - (e as f32 * scale).ceil() as i32 + 1 - }) + self.inner + .upper_bound() + .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32 + 1) } } From 3e62f7edc318584d6ca494e7021c1bbb3967ed8a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 16:17:50 +0100 Subject: [PATCH 09/27] Better LoD distance scaling --- assets/voxygen/shaders/sprite-frag.glsl | 2 +- common/src/volumes/scaled.rs | 2 +- voxygen/src/scene/terrain.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 4fd0a975f8..0c08431d52 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -13,7 +13,7 @@ out vec4 tgt_color; #include #include -const float RENDER_DIST = 112.0; +const float RENDER_DIST = 180.0; const float FADE_DIST = 32.0; void main() { diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index 19763d3a5f..d4b8cf3f9c 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -18,7 +18,7 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32); let range_iter = |x| { std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })) - .take((x as usize * 2).max(1) - 1) + .take(x as usize * 2) }; range_iter(search_size.x / 2) .map(|i| { diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1d49269eaa..2b06688797 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -2010,9 +2010,9 @@ impl Terrain { for (pos, chunk) in chunk_iter.clone() { if chunk.visible { const SPRITE_RENDER_DISTANCE: f32 = 200.0; - const SPRITE_DETAIL_LOW_DISTANCE: f32 = 120.0; - const SPRITE_DETAIL_MID_DISTANCE: f32 = 64.0; - const SPRITE_DETAIL_HIGH_DISTANCE: f32 = 32.0; + const SPRITE_DETAIL_LOW_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.65; + const SPRITE_DETAIL_MID_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.4; + const SPRITE_DETAIL_HIGH_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.25; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); From 39b88dbcb1858ad3a91b22daea55ce210491790c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 19:37:45 +0100 Subject: [PATCH 10/27] Added LoD for figures and reduced update rates for far figures --- voxygen/src/scene/figure/cache.rs | 1001 +++++++++++++++-------------- voxygen/src/scene/figure/load.rs | 319 ++++----- voxygen/src/scene/figure/mod.rs | 38 +- voxygen/src/scene/simple.rs | 11 +- 4 files changed, 725 insertions(+), 644 deletions(-) diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 7903b30d3c..66ae5f5f00 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -3,14 +3,18 @@ use crate::{ anim::{self, Skeleton}, render::{FigurePipeline, Mesh, Model, Renderer}, scene::camera::CameraMode, + mesh::Meshable, }; use common::{ + figure::Segment, assets::watch::ReloadIndicator, comp::{ item::{tool::ToolKind, ItemKind}, Body, CharacterState, Item, Loadout, }, + vol::BaseVol, }; +use vek::*; use hashbrown::{hash_map::Entry, HashMap}; use std::{ convert::TryInto, @@ -64,7 +68,7 @@ pub struct FigureModelCache where Skel: Skeleton, { - models: HashMap, Skel::Attr), u64)>, + models: HashMap; 3], Skel::Attr), u64)>, manifest_indicator: ReloadIndicator, } @@ -76,6 +80,479 @@ impl FigureModelCache { } } + fn bone_meshes( + body: Body, + loadout: Option<&Loadout>, + character_state: Option<&CharacterState>, + camera_mode: CameraMode, + manifest_indicator: &mut ReloadIndicator, + generate_mesh: fn(&Segment, Vec3) -> Mesh, + ) -> [Option>; 16] { + match body { + Body::Humanoid(body) => { + let humanoid_head_spec = + HumHeadSpec::load_watched(manifest_indicator); + let humanoid_armor_shoulder_spec = + HumArmorShoulderSpec::load_watched(manifest_indicator); + let humanoid_armor_chest_spec = + HumArmorChestSpec::load_watched(manifest_indicator); + let humanoid_armor_hand_spec = + HumArmorHandSpec::load_watched(manifest_indicator); + let humanoid_armor_belt_spec = + HumArmorBeltSpec::load_watched(manifest_indicator); + let humanoid_armor_back_spec = + HumArmorBackSpec::load_watched(manifest_indicator); + let humanoid_armor_lantern_spec = + HumArmorLanternSpec::load_watched(manifest_indicator); + let humanoid_armor_pants_spec = + HumArmorPantsSpec::load_watched(manifest_indicator); + let humanoid_armor_foot_spec = + HumArmorFootSpec::load_watched(manifest_indicator); + let humanoid_main_weapon_spec = + HumMainWeaponSpec::load_watched(manifest_indicator); + + // TODO: This is bad code, maybe this method should return Option<_> + let default_loadout = Loadout::default(); + let loadout = loadout.unwrap_or(&default_loadout); + + [ + match camera_mode { + CameraMode::ThirdPerson => { + Some(humanoid_head_spec.mesh_head( + body.race, + body.body_type, + body.hair_color, + body.hair_style, + body.beard, + body.eye_color, + body.skin, + body.eyebrows, + body.accessory, + generate_mesh, + )) + }, + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_chest_spec.mesh_chest(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => { + Some(humanoid_armor_belt_spec.mesh_belt(&body, loadout, generate_mesh)) + }, + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => { + Some(humanoid_armor_back_spec.mesh_back(&body, loadout, generate_mesh)) + }, + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_pants_spec.mesh_pants(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + if camera_mode == CameraMode::FirstPerson + && character_state + .map(|cs| cs.is_dodge()) + .unwrap_or_default() + { + None + } else { + Some( + humanoid_armor_hand_spec.mesh_left_hand(&body, loadout, generate_mesh), + ) + }, + if character_state.map(|cs| cs.is_dodge()).unwrap_or_default() { + None + } else { + Some( + humanoid_armor_hand_spec + .mesh_right_hand(&body, loadout, generate_mesh), + ) + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_foot_spec.mesh_left_foot(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_foot_spec + .mesh_right_foot(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_shoulder_spec + .mesh_left_shoulder(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + match camera_mode { + CameraMode::ThirdPerson => Some( + humanoid_armor_shoulder_spec + .mesh_right_shoulder(&body, loadout, generate_mesh), + ), + CameraMode::FirstPerson => None, + }, + Some(mesh_glider(generate_mesh)), + if camera_mode != CameraMode::FirstPerson + || character_state + .map(|cs| { + cs.is_attack() || cs.is_block() || cs.is_wield() + }) + .unwrap_or_default() + { + Some(humanoid_main_weapon_spec.mesh_main_weapon( + loadout.active_item.as_ref().map(|i| &i.item.kind), + generate_mesh, + )) + } else { + None + }, + None, + Some(humanoid_armor_lantern_spec.mesh_lantern(&body, loadout, generate_mesh)), + None, + ] + }, + Body::QuadrupedSmall(body) => { + let quadruped_small_central_spec = + QuadrupedSmallCentralSpec::load_watched(manifest_indicator); + let quadruped_small_lateral_spec = + QuadrupedSmallLateralSpec::load_watched(manifest_indicator); + + [ + Some( + quadruped_small_central_spec + .mesh_head(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_small_central_spec + .mesh_chest(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_small_lateral_spec + .mesh_foot_lf(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_small_lateral_spec + .mesh_foot_rf(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_small_lateral_spec + .mesh_foot_lb(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_small_lateral_spec + .mesh_foot_rb(body.species, body.body_type, generate_mesh), + ), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ] + }, + Body::QuadrupedMedium(body) => { + let quadruped_medium_central_spec = + QuadrupedMediumCentralSpec::load_watched(manifest_indicator); + let quadruped_medium_lateral_spec = + QuadrupedMediumLateralSpec::load_watched(manifest_indicator); + + [ + Some( + quadruped_medium_central_spec + .mesh_head_upper(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_head_lower(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_jaw(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_tail(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_torso_f(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_torso_b(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_central_spec + .mesh_ears(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_lateral_spec + .mesh_foot_lf(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_lateral_spec + .mesh_foot_rf(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_lateral_spec + .mesh_foot_lb(body.species, body.body_type, generate_mesh), + ), + Some( + quadruped_medium_lateral_spec + .mesh_foot_rb(body.species, body.body_type, generate_mesh), + ), + None, + None, + None, + None, + None, + ] + }, + Body::BirdMedium(body) => { + let bird_medium_center_spec = BirdMediumCenterSpec::load_watched(manifest_indicator); + let bird_medium_lateral_spec = BirdMediumLateralSpec::load_watched(manifest_indicator); + + [ + Some( + bird_medium_center_spec + .mesh_head(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_center_spec + .mesh_torso(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_center_spec + .mesh_tail(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_lateral_spec + .mesh_wing_l(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_lateral_spec + .mesh_wing_r(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_lateral_spec + .mesh_foot_l(body.species, body.body_type, generate_mesh), + ), + Some( + bird_medium_lateral_spec + .mesh_foot_r(body.species, body.body_type, generate_mesh), + ), + None, + None, + None, + None, + None, + None, + None, + None, + None, + ] + }, + Body::FishMedium(body) => [ + Some(mesh_fish_medium_head(body.head, generate_mesh)), + Some(mesh_fish_medium_torso(body.torso, generate_mesh)), + Some(mesh_fish_medium_rear(body.rear, generate_mesh)), + Some(mesh_fish_medium_tail(body.tail, generate_mesh)), + Some(mesh_fish_medium_fin_l(body.fin_l, generate_mesh)), + Some(mesh_fish_medium_fin_r(body.fin_r, generate_mesh)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + Body::Dragon(body) => [ + Some(mesh_dragon_head(body.head, generate_mesh)), + Some(mesh_dragon_chest_front(body.chest_front, generate_mesh)), + Some(mesh_dragon_chest_rear(body.chest_rear, generate_mesh)), + Some(mesh_dragon_tail_front(body.tail_front, generate_mesh)), + Some(mesh_dragon_tail_rear(body.tail_rear, generate_mesh)), + Some(mesh_dragon_wing_in_l(body.wing_in_l, generate_mesh)), + Some(mesh_dragon_wing_in_r(body.wing_in_r, generate_mesh)), + Some(mesh_dragon_wing_out_l(body.wing_out_l, generate_mesh)), + Some(mesh_dragon_wing_out_r(body.wing_out_r, generate_mesh)), + Some(mesh_dragon_foot_fl(body.foot_fl, generate_mesh)), + Some(mesh_dragon_foot_fr(body.foot_fr, generate_mesh)), + Some(mesh_dragon_foot_bl(body.foot_bl, generate_mesh)), + Some(mesh_dragon_foot_br(body.foot_br, generate_mesh)), + None, + None, + None, + ], + Body::BirdSmall(body) => [ + Some(mesh_bird_small_head(body.head, generate_mesh)), + Some(mesh_bird_small_torso(body.torso, generate_mesh)), + Some(mesh_bird_small_wing_l(body.wing_l, generate_mesh)), + Some(mesh_bird_small_wing_r(body.wing_r, generate_mesh)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + Body::FishSmall(body) => [ + Some(mesh_fish_small_torso(body.torso, generate_mesh)), + Some(mesh_fish_small_tail(body.tail, generate_mesh)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + Body::BipedLarge(body) => { + let biped_large_center_spec = BipedLargeCenterSpec::load_watched(manifest_indicator); + let biped_large_lateral_spec = BipedLargeLateralSpec::load_watched(manifest_indicator); + + [ + Some( + biped_large_center_spec + .mesh_head(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_center_spec + .mesh_torso_upper(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_center_spec + .mesh_torso_lower(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_shoulder_l(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_shoulder_r(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_hand_l(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_hand_r(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_leg_l(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_leg_r(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_foot_l(body.species, body.body_type, generate_mesh), + ), + Some( + biped_large_lateral_spec + .mesh_foot_r(body.species, body.body_type, generate_mesh), + ), + None, + None, + None, + None, + None, + ] + }, + Body::Critter(body) => { + let critter_center_spec = + CritterCenterSpec::load_watched(manifest_indicator); + + [ + Some( + critter_center_spec.mesh_head(body.species, body.body_type, generate_mesh), + ), + Some( + critter_center_spec + .mesh_chest(body.species, body.body_type, generate_mesh), + ), + Some( + critter_center_spec + .mesh_feet_f(body.species, body.body_type, generate_mesh), + ), + Some( + critter_center_spec + .mesh_feet_b(body.species, body.body_type, generate_mesh), + ), + Some( + critter_center_spec.mesh_tail(body.species, body.body_type, generate_mesh), + ), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ] + }, + Body::Object(object) => [ + Some(mesh_object(object, generate_mesh)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + } + } + pub fn get_or_create_model( &mut self, renderer: &mut Renderer, @@ -84,7 +561,7 @@ impl FigureModelCache { tick: u64, camera_mode: CameraMode, character_state: Option<&CharacterState>, - ) -> &(Model, Skel::Attr) + ) -> &([Model; 3], Skel::Attr) where for<'a> &'a common::comp::Body: std::convert::TryInto, Skel::Attr: Default, @@ -108,501 +585,43 @@ impl FigureModelCache { Entry::Vacant(v) => { &v.insert(( { - let bone_meshes = match body { - Body::Humanoid(body) => { - let humanoid_head_spec = - HumHeadSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_shoulder_spec = - HumArmorShoulderSpec::load_watched( - &mut self.manifest_indicator, - ); - let humanoid_armor_chest_spec = - HumArmorChestSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_hand_spec = - HumArmorHandSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_belt_spec = - HumArmorBeltSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_back_spec = - HumArmorBackSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_lantern_spec = - HumArmorLanternSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_pants_spec = - HumArmorPantsSpec::load_watched(&mut self.manifest_indicator); - let humanoid_armor_foot_spec = - HumArmorFootSpec::load_watched(&mut self.manifest_indicator); - let humanoid_main_weapon_spec = - HumMainWeaponSpec::load_watched(&mut self.manifest_indicator); - - // TODO: This is bad code, maybe this method should return Option<_> - let default_loadout = Loadout::default(); - let loadout = loadout.unwrap_or(&default_loadout); - - [ - match camera_mode { - CameraMode::ThirdPerson => { - Some(humanoid_head_spec.mesh_head( - body.race, - body.body_type, - body.hair_color, - body.hair_style, - body.beard, - body.eye_color, - body.skin, - body.eyebrows, - body.accessory, - )) - }, - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_chest_spec.mesh_chest(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => { - Some(humanoid_armor_belt_spec.mesh_belt(&body, loadout)) - }, - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => { - Some(humanoid_armor_back_spec.mesh_back(&body, loadout)) - }, - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_pants_spec.mesh_pants(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - if camera_mode == CameraMode::FirstPerson - && character_state - .map(|cs| cs.is_dodge()) - .unwrap_or_default() - { - None - } else { - Some( - humanoid_armor_hand_spec.mesh_left_hand(&body, loadout), - ) - }, - if character_state.map(|cs| cs.is_dodge()).unwrap_or_default() { - None - } else { - Some( - humanoid_armor_hand_spec - .mesh_right_hand(&body, loadout), - ) - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_foot_spec.mesh_left_foot(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_foot_spec - .mesh_right_foot(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_shoulder_spec - .mesh_left_shoulder(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_shoulder_spec - .mesh_right_shoulder(&body, loadout), - ), - CameraMode::FirstPerson => None, - }, - Some(mesh_glider()), - if camera_mode != CameraMode::FirstPerson - || character_state - .map(|cs| { - cs.is_attack() || cs.is_block() || cs.is_wield() - }) - .unwrap_or_default() - { - Some(humanoid_main_weapon_spec.mesh_main_weapon( - loadout.active_item.as_ref().map(|i| &i.item.kind), - )) - } else { - None - }, - None, - Some(humanoid_armor_lantern_spec.mesh_lantern(&body, loadout)), - None, - ] - }, - Body::QuadrupedSmall(body) => { - let quadruped_small_central_spec = - QuadrupedSmallCentralSpec::load_watched( - &mut self.manifest_indicator, - ); - let quadruped_small_lateral_spec = - QuadrupedSmallLateralSpec::load_watched( - &mut self.manifest_indicator, - ); - - [ - Some( - quadruped_small_central_spec - .mesh_head(body.species, body.body_type), - ), - Some( - quadruped_small_central_spec - .mesh_chest(body.species, body.body_type), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_lf(body.species, body.body_type), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_rf(body.species, body.body_type), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_lb(body.species, body.body_type), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_rb(body.species, body.body_type), - ), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ] - }, - Body::QuadrupedMedium(body) => { - let quadruped_medium_central_spec = - QuadrupedMediumCentralSpec::load_watched( - &mut self.manifest_indicator, - ); - let quadruped_medium_lateral_spec = - QuadrupedMediumLateralSpec::load_watched( - &mut self.manifest_indicator, - ); - - [ - Some( - quadruped_medium_central_spec - .mesh_head_upper(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_head_lower(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_jaw(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_tail(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_torso_f(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_torso_b(body.species, body.body_type), - ), - Some( - quadruped_medium_central_spec - .mesh_ears(body.species, body.body_type), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_lf(body.species, body.body_type), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_rf(body.species, body.body_type), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_lb(body.species, body.body_type), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_rb(body.species, body.body_type), - ), - None, - None, - None, - None, - None, - ] - }, - Body::BirdMedium(body) => { - let bird_medium_center_spec = BirdMediumCenterSpec::load_watched( - &mut self.manifest_indicator, - ); - let bird_medium_lateral_spec = BirdMediumLateralSpec::load_watched( - &mut self.manifest_indicator, - ); - - [ - Some( - bird_medium_center_spec - .mesh_head(body.species, body.body_type), - ), - Some( - bird_medium_center_spec - .mesh_torso(body.species, body.body_type), - ), - Some( - bird_medium_center_spec - .mesh_tail(body.species, body.body_type), - ), - Some( - bird_medium_lateral_spec - .mesh_wing_l(body.species, body.body_type), - ), - Some( - bird_medium_lateral_spec - .mesh_wing_r(body.species, body.body_type), - ), - Some( - bird_medium_lateral_spec - .mesh_foot_l(body.species, body.body_type), - ), - Some( - bird_medium_lateral_spec - .mesh_foot_r(body.species, body.body_type), - ), - None, - None, - None, - None, - None, - None, - None, - None, - None, - ] - }, - Body::FishMedium(body) => [ - Some(mesh_fish_medium_head(body.head)), - Some(mesh_fish_medium_torso(body.torso)), - Some(mesh_fish_medium_rear(body.rear)), - Some(mesh_fish_medium_tail(body.tail)), - Some(mesh_fish_medium_fin_l(body.fin_l)), - Some(mesh_fish_medium_fin_r(body.fin_r)), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], - Body::Dragon(body) => [ - Some(mesh_dragon_head(body.head)), - Some(mesh_dragon_chest_front(body.chest_front)), - Some(mesh_dragon_chest_rear(body.chest_rear)), - Some(mesh_dragon_tail_front(body.tail_front)), - Some(mesh_dragon_tail_rear(body.tail_rear)), - Some(mesh_dragon_wing_in_l(body.wing_in_l)), - Some(mesh_dragon_wing_in_r(body.wing_in_r)), - Some(mesh_dragon_wing_out_l(body.wing_out_l)), - Some(mesh_dragon_wing_out_r(body.wing_out_r)), - Some(mesh_dragon_foot_fl(body.foot_fl)), - Some(mesh_dragon_foot_fr(body.foot_fr)), - Some(mesh_dragon_foot_bl(body.foot_bl)), - Some(mesh_dragon_foot_br(body.foot_br)), - None, - None, - None, - ], - Body::BirdSmall(body) => [ - Some(mesh_bird_small_head(body.head)), - Some(mesh_bird_small_torso(body.torso)), - Some(mesh_bird_small_wing_l(body.wing_l)), - Some(mesh_bird_small_wing_r(body.wing_r)), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], - Body::FishSmall(body) => [ - Some(mesh_fish_small_torso(body.torso)), - Some(mesh_fish_small_tail(body.tail)), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], - Body::BipedLarge(body) => { - let biped_large_center_spec = BipedLargeCenterSpec::load_watched( - &mut self.manifest_indicator, - ); - let biped_large_lateral_spec = BipedLargeLateralSpec::load_watched( - &mut self.manifest_indicator, - ); - - [ - Some( - biped_large_center_spec - .mesh_head(body.species, body.body_type), - ), - Some( - biped_large_center_spec - .mesh_torso_upper(body.species, body.body_type), - ), - Some( - biped_large_center_spec - .mesh_torso_lower(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_shoulder_l(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_shoulder_r(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_hand_l(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_hand_r(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_leg_l(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_leg_r(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_foot_l(body.species, body.body_type), - ), - Some( - biped_large_lateral_spec - .mesh_foot_r(body.species, body.body_type), - ), - None, - None, - None, - None, - None, - ] - }, - Body::Critter(body) => { - let critter_center_spec = - CritterCenterSpec::load_watched(&mut self.manifest_indicator); - - [ - Some( - critter_center_spec.mesh_head(body.species, body.body_type), - ), - Some( - critter_center_spec - .mesh_chest(body.species, body.body_type), - ), - Some( - critter_center_spec - .mesh_feet_f(body.species, body.body_type), - ), - Some( - critter_center_spec - .mesh_feet_b(body.species, body.body_type), - ), - Some( - critter_center_spec.mesh_tail(body.species, body.body_type), - ), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ] - }, - Body::Object(object) => [ - Some(mesh_object(object)), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], - }; - let skeleton_attr = (&body) .try_into() .ok() .unwrap_or_else(::default); - let mut mesh = Mesh::new(); - bone_meshes - .iter() - .enumerate() - .filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm))) - .for_each(|(i, bone_mesh)| { - mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8)) - }); + let manifest_indicator = &mut self.manifest_indicator; + let mut make_model = |generate_mesh| { + let mut mesh = Mesh::new(); + Self::bone_meshes(body, loadout, character_state, camera_mode, manifest_indicator, generate_mesh) + .iter() + .enumerate() + .filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm))) + .for_each(|(i, bone_mesh)| { + mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8)) + }); + renderer.create_model(&mesh).unwrap() + }; - (renderer.create_model(&mesh).unwrap(), skeleton_attr) + fn generate_mesh(segment: &Segment, offset: Vec3) -> Mesh { + Meshable::::generate_mesh(segment, (offset, Vec3::one())).0 + } + + fn generate_mesh_lod_mid(segment: &Segment, offset: Vec3) -> Mesh { + let lod_scale = Vec3::broadcast(0.6); + Meshable::::generate_mesh(&segment.scaled_by(lod_scale), (offset * lod_scale, Vec3::one() / lod_scale)).0 + } + + fn generate_mesh_lod_low(segment: &Segment, offset: Vec3) -> Mesh { + let lod_scale = Vec3::broadcast(0.3); + Meshable::::generate_mesh(&segment.scaled_by(lod_scale), (offset * lod_scale, Vec3::one() / lod_scale)).0 + } + + ([ + make_model(generate_mesh), + make_model(generate_mesh_lod_mid), + make_model(generate_mesh_lod_low), + ], skeleton_attr) }, tick, )) diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index cfd6e86dc8..b19ab5e004 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -1,7 +1,4 @@ -use crate::{ - mesh::Meshable, - render::{FigurePipeline, Mesh}, -}; +use crate::render::{FigurePipeline, Mesh}; use common::{ assets::{self, watch::ReloadIndicator, Asset}, comp::{ @@ -54,11 +51,7 @@ fn graceful_load_mat_segment_flipped(mesh_name: &str) -> MatSegment { MatSegment::from_vox(graceful_load_vox(mesh_name).as_ref(), true) } -fn generate_mesh(segment: &Segment, offset: Vec3) -> Mesh { - Meshable::::generate_mesh(segment, (offset, Vec3::one())).0 -} - -pub fn load_mesh(mesh_name: &str, position: Vec3) -> Mesh { +pub fn load_mesh(mesh_name: &str, position: Vec3, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { generate_mesh(&load_segment(mesh_name), position) } @@ -159,6 +152,7 @@ impl HumHeadSpec { skin: u8, _eyebrows: Eyebrows, accessory: u8, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(race, body_type)) { Some(spec) => spec, @@ -167,7 +161,7 @@ impl HumHeadSpec { "No head specification exists for the combination of {:?} and {:?}", race, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; @@ -349,7 +343,7 @@ impl HumArmorShoulderSpec { .unwrap() } - fn mesh_shoulder(&self, body: &Body, loadout: &Loadout, flipped: bool) -> Mesh { + fn mesh_shoulder(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Shoulder(shoulder), .. @@ -359,7 +353,7 @@ impl HumArmorShoulderSpec { Some(spec) => spec, None => { error!("No shoulder specification exists for {:?}", shoulder); - return load_mesh("not_found", Vec3::new(-3.0, -3.5, 0.1)); + return load_mesh("not_found", Vec3::new(-3.0, -3.5, 0.1), generate_mesh); }, } } else { @@ -391,12 +385,12 @@ impl HumArmorShoulderSpec { generate_mesh(&shoulder_segment, Vec3::from(offset)) } - pub fn mesh_left_shoulder(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_shoulder(body, loadout, true) + pub fn mesh_left_shoulder(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_shoulder(body, loadout, true, generate_mesh) } - pub fn mesh_right_shoulder(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_shoulder(body, loadout, false) + pub fn mesh_right_shoulder(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_shoulder(body, loadout, false, generate_mesh) } } // Chest @@ -406,7 +400,7 @@ impl HumArmorChestSpec { .unwrap() } - pub fn mesh_chest(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_chest(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Chest(chest), .. @@ -416,7 +410,7 @@ impl HumArmorChestSpec { Some(spec) => spec, None => { error!("No chest specification exists for {:?}", loadout.chest); - return load_mesh("not_found", Vec3::new(-7.0, -3.5, 2.0)); + return load_mesh("not_found", Vec3::new(-7.0, -3.5, 2.0), generate_mesh); }, } } else { @@ -457,7 +451,7 @@ impl HumArmorHandSpec { .unwrap() } - fn mesh_hand(&self, body: &Body, loadout: &Loadout, flipped: bool) -> Mesh { + fn mesh_hand(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Hand(hand), .. @@ -467,7 +461,7 @@ impl HumArmorHandSpec { Some(spec) => spec, None => { error!("No hand specification exists for {:?}", hand); - return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0)); + return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0), generate_mesh); }, } } else { @@ -494,12 +488,12 @@ impl HumArmorHandSpec { generate_mesh(&hand_segment, Vec3::from(offset)) } - pub fn mesh_left_hand(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_hand(body, loadout, true) + pub fn mesh_left_hand(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_hand(body, loadout, true, generate_mesh) } - pub fn mesh_right_hand(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_hand(body, loadout, false) + pub fn mesh_right_hand(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_hand(body, loadout, false, generate_mesh) } } // Belt @@ -509,7 +503,7 @@ impl HumArmorBeltSpec { .unwrap() } - pub fn mesh_belt(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_belt(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Belt(belt), .. @@ -519,7 +513,7 @@ impl HumArmorBeltSpec { Some(spec) => spec, None => { error!("No belt specification exists for {:?}", belt); - return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0)); + return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh); }, } } else { @@ -543,7 +537,7 @@ impl HumArmorBackSpec { .unwrap() } - pub fn mesh_back(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_back(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Back(back), .. @@ -553,7 +547,7 @@ impl HumArmorBackSpec { Some(spec) => spec, None => { error!("No back specification exists for {:?}", back); - return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0)); + return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh); }, } } else { @@ -577,7 +571,7 @@ impl HumArmorPantsSpec { .unwrap() } - pub fn mesh_pants(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_pants(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Pants(pants), .. @@ -587,7 +581,7 @@ impl HumArmorPantsSpec { Some(spec) => spec, None => { error!("No pants specification exists for {:?}", pants); - return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0)); + return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0), generate_mesh); }, } } else { @@ -628,7 +622,7 @@ impl HumArmorFootSpec { .unwrap() } - fn mesh_foot(&self, body: &Body, loadout: &Loadout, flipped: bool) -> Mesh { + fn mesh_foot(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Foot(foot), .. @@ -638,7 +632,7 @@ impl HumArmorFootSpec { Some(spec) => spec, None => { error!("No foot specification exists for {:?}", foot); - return load_mesh("not_found", Vec3::new(-2.5, -3.5, -9.0)); + return load_mesh("not_found", Vec3::new(-2.5, -3.5, -9.0), generate_mesh); }, } } else { @@ -659,12 +653,12 @@ impl HumArmorFootSpec { generate_mesh(&foot_segment, Vec3::from(spec.vox_spec.1)) } - pub fn mesh_left_foot(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_foot(body, loadout, true) + pub fn mesh_left_foot(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_foot(body, loadout, true, generate_mesh) } - pub fn mesh_right_foot(&self, body: &Body, loadout: &Loadout) -> Mesh { - self.mesh_foot(body, loadout, false) + pub fn mesh_right_foot(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + self.mesh_foot(body, loadout, false, generate_mesh) } } @@ -674,7 +668,7 @@ impl HumMainWeaponSpec { .unwrap() } - pub fn mesh_main_weapon(&self, item_kind: Option<&ItemKind>) -> Mesh { + pub fn mesh_main_weapon(&self, item_kind: Option<&ItemKind>, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let tool_kind = if let Some(ItemKind::Tool(Tool { kind, .. })) = item_kind { kind } else { @@ -685,7 +679,7 @@ impl HumMainWeaponSpec { Some(spec) => spec, None => { error!("No hand specification exists for {:?}", tool_kind); - return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0)); + return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0), generate_mesh); }, }; @@ -699,14 +693,14 @@ impl HumArmorLanternSpec { assets::load_watched::("voxygen.voxel.humanoid_lantern_manifest", indicator).unwrap() } - pub fn mesh_lantern(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_lantern(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Lantern(lantern)) = loadout.lantern.as_ref().map(|i| &i.kind) { match self.0.map.get(&lantern) { Some(spec) => spec, None => { error!("No lantern specification exists for {:?}", lantern); - return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0)); + return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh); }, } } else { @@ -729,7 +723,7 @@ impl HumArmorHeadSpec { .unwrap() } - pub fn mesh_head(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_head(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Head(head), .. @@ -739,7 +733,7 @@ impl HumArmorHeadSpec { Some(spec) => spec, None => { error!("No head specification exists for {:?}", head); - return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0)); + return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0), generate_mesh); }, } } else { @@ -779,7 +773,7 @@ impl HumArmorTabardSpec { .unwrap() } - pub fn mesh_tabard(&self, body: &Body, loadout: &Loadout) -> Mesh { + pub fn mesh_tabard(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Tabard(tabard), .. @@ -789,7 +783,7 @@ impl HumArmorTabardSpec { Some(spec) => spec, None => { error!("No tabard specification exists for {:?}", tabard); - return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0)); + return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0), generate_mesh); }, } } else { @@ -824,8 +818,8 @@ impl HumArmorTabardSpec { } } // TODO: Inventory -pub fn mesh_glider() -> Mesh { - load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0)) +pub fn mesh_glider(generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0), generate_mesh) } ///////// @@ -881,7 +875,7 @@ impl QuadrupedSmallCentralSpec { .unwrap() } - pub fn mesh_head(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_head(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -889,7 +883,7 @@ impl QuadrupedSmallCentralSpec { "No head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.head.central.0); @@ -897,7 +891,7 @@ impl QuadrupedSmallCentralSpec { generate_mesh(¢ral, Vec3::from(spec.head.offset)) } - pub fn mesh_chest(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_chest(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -905,7 +899,7 @@ impl QuadrupedSmallCentralSpec { "No chest specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.chest.central.0); @@ -920,7 +914,7 @@ impl QuadrupedSmallLateralSpec { .unwrap() } - pub fn mesh_foot_lf(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_foot_lf(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -928,7 +922,7 @@ impl QuadrupedSmallLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.left_front.lateral.0); @@ -936,7 +930,7 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_front.offset)) } - pub fn mesh_foot_rf(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_foot_rf(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -944,7 +938,7 @@ impl QuadrupedSmallLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.right_front.lateral.0); @@ -952,7 +946,7 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.right_front.offset)) } - pub fn mesh_foot_lb(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_foot_lb(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -960,7 +954,7 @@ impl QuadrupedSmallLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.left_back.lateral.0); @@ -968,7 +962,7 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_back.offset)) } - pub fn mesh_foot_rb(&self, species: QSSpecies, body_type: QSBodyType) -> Mesh { + pub fn mesh_foot_rb(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -976,7 +970,7 @@ impl QuadrupedSmallLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.right_back.lateral.0); @@ -1046,6 +1040,7 @@ impl QuadrupedMediumCentralSpec { &self, species: QMSpecies, body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1054,7 +1049,7 @@ impl QuadrupedMediumCentralSpec { "No upper head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.upper.central.0); @@ -1066,6 +1061,7 @@ impl QuadrupedMediumCentralSpec { &self, species: QMSpecies, body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1074,7 +1070,7 @@ impl QuadrupedMediumCentralSpec { "No lower head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.lower.central.0); @@ -1082,7 +1078,7 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.lower.offset)) } - pub fn mesh_jaw(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_jaw(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1090,7 +1086,7 @@ impl QuadrupedMediumCentralSpec { "No jaw specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.jaw.central.0); @@ -1098,7 +1094,7 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.jaw.offset)) } - pub fn mesh_ears(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_ears(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1106,7 +1102,7 @@ impl QuadrupedMediumCentralSpec { "No ears specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.ears.central.0); @@ -1114,7 +1110,7 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.ears.offset)) } - pub fn mesh_torso_f(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_torso_f(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1122,7 +1118,7 @@ impl QuadrupedMediumCentralSpec { "No torso specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.torso_f.central.0); @@ -1130,7 +1126,7 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.torso_f.offset)) } - pub fn mesh_torso_b(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_torso_b(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1138,7 +1134,7 @@ impl QuadrupedMediumCentralSpec { "No torso specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.torso_b.central.0); @@ -1146,7 +1142,7 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.torso_b.offset)) } - pub fn mesh_tail(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_tail(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1154,7 +1150,7 @@ impl QuadrupedMediumCentralSpec { "No tail specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let central = graceful_load_segment(&spec.tail.central.0); @@ -1169,7 +1165,7 @@ impl QuadrupedMediumLateralSpec { .unwrap() } - pub fn mesh_foot_lf(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_foot_lf(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1177,7 +1173,7 @@ impl QuadrupedMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.left_front.lateral.0); @@ -1185,7 +1181,7 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_front.offset)) } - pub fn mesh_foot_rf(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_foot_rf(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1193,7 +1189,7 @@ impl QuadrupedMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.right_front.lateral.0); @@ -1201,7 +1197,7 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.right_front.offset)) } - pub fn mesh_foot_lb(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_foot_lb(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1209,7 +1205,7 @@ impl QuadrupedMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.left_back.lateral.0); @@ -1217,7 +1213,7 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_back.offset)) } - pub fn mesh_foot_rb(&self, species: QMSpecies, body_type: QMBodyType) -> Mesh { + pub fn mesh_foot_rb(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1225,7 +1221,7 @@ impl QuadrupedMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.right_back.lateral.0); @@ -1288,7 +1284,7 @@ impl BirdMediumCenterSpec { .unwrap() } - pub fn mesh_head(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_head(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1296,7 +1292,7 @@ impl BirdMediumCenterSpec { "No head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.head.center.0); @@ -1304,7 +1300,7 @@ impl BirdMediumCenterSpec { generate_mesh(¢er, Vec3::from(spec.head.offset)) } - pub fn mesh_torso(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_torso(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1312,7 +1308,7 @@ impl BirdMediumCenterSpec { "No torso specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.torso.center.0); @@ -1320,7 +1316,7 @@ impl BirdMediumCenterSpec { generate_mesh(¢er, Vec3::from(spec.torso.offset)) } - pub fn mesh_tail(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_tail(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1328,7 +1324,7 @@ impl BirdMediumCenterSpec { "No tail specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.tail.center.0); @@ -1342,7 +1338,7 @@ impl BirdMediumLateralSpec { .unwrap() } - pub fn mesh_wing_l(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_wing_l(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1350,7 +1346,7 @@ impl BirdMediumLateralSpec { "No wing specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.wing_l.lateral.0); @@ -1358,7 +1354,7 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.wing_l.offset)) } - pub fn mesh_wing_r(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_wing_r(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1366,7 +1362,7 @@ impl BirdMediumLateralSpec { "No wing specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.wing_r.lateral.0); @@ -1374,7 +1370,7 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.wing_r.offset)) } - pub fn mesh_foot_l(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_foot_l(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1382,7 +1378,7 @@ impl BirdMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.foot_l.lateral.0); @@ -1390,7 +1386,7 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.foot_l.offset)) } - pub fn mesh_foot_r(&self, species: BMSpecies, body_type: BMBodyType) -> Mesh { + pub fn mesh_foot_r(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1398,7 +1394,7 @@ impl BirdMediumLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.foot_r.lateral.0); @@ -1437,7 +1433,7 @@ impl CritterCenterSpec { assets::load_watched::("voxygen.voxel.critter_center_manifest", indicator).unwrap() } - pub fn mesh_head(&self, species: CSpecies, body_type: CBodyType) -> Mesh { + pub fn mesh_head(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1445,7 +1441,7 @@ impl CritterCenterSpec { "No head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.head.center.0); @@ -1453,7 +1449,7 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.head.offset)) } - pub fn mesh_chest(&self, species: CSpecies, body_type: CBodyType) -> Mesh { + pub fn mesh_chest(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1461,7 +1457,7 @@ impl CritterCenterSpec { "No chest specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.chest.center.0); @@ -1469,7 +1465,7 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.chest.offset)) } - pub fn mesh_feet_f(&self, species: CSpecies, body_type: CBodyType) -> Mesh { + pub fn mesh_feet_f(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1477,7 +1473,7 @@ impl CritterCenterSpec { "No feet specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.feet_f.center.0); @@ -1485,7 +1481,7 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.feet_f.offset)) } - pub fn mesh_feet_b(&self, species: CSpecies, body_type: CBodyType) -> Mesh { + pub fn mesh_feet_b(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1493,7 +1489,7 @@ impl CritterCenterSpec { "No feet specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.feet_b.center.0); @@ -1501,7 +1497,7 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.feet_b.offset)) } - pub fn mesh_tail(&self, species: CSpecies, body_type: CBodyType) -> Mesh { + pub fn mesh_tail(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1509,7 +1505,7 @@ impl CritterCenterSpec { "No tail specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.tail.center.0); @@ -1518,229 +1514,254 @@ impl CritterCenterSpec { } } //// -pub fn mesh_fish_medium_head(head: fish_medium::Head) -> Mesh { +pub fn mesh_fish_medium_head(head: fish_medium::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match head { fish_medium::Head::Default => "npc.marlin.head", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_medium_torso(torso: fish_medium::Torso) -> Mesh { +pub fn mesh_fish_medium_torso(torso: fish_medium::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match torso { fish_medium::Torso::Default => "npc.marlin.torso", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_medium_rear(rear: fish_medium::Rear) -> Mesh { +pub fn mesh_fish_medium_rear(rear: fish_medium::Rear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match rear { fish_medium::Rear::Default => "npc.marlin.rear", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_medium_tail(tail: fish_medium::Tail) -> Mesh { +pub fn mesh_fish_medium_tail(tail: fish_medium::Tail, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match tail { fish_medium::Tail::Default => "npc.marlin.tail", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_medium_fin_l(fin_l: fish_medium::FinL) -> Mesh { +pub fn mesh_fish_medium_fin_l(fin_l: fish_medium::FinL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match fin_l { fish_medium::FinL::Default => "npc.marlin.fin_l", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_medium_fin_r(fin_r: fish_medium::FinR) -> Mesh { +pub fn mesh_fish_medium_fin_r(fin_r: fish_medium::FinR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match fin_r { fish_medium::FinR::Default => "npc.marlin.fin_r", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_head(head: dragon::Head) -> Mesh { +pub fn mesh_dragon_head(head: dragon::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match head { dragon::Head::Default => "npc.dragon.head", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_chest_front(chest_front: dragon::ChestFront) -> Mesh { +pub fn mesh_dragon_chest_front(chest_front: dragon::ChestFront, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match chest_front { dragon::ChestFront::Default => "npc.dragon.chest_front", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_chest_rear(chest_rear: dragon::ChestRear) -> Mesh { +pub fn mesh_dragon_chest_rear(chest_rear: dragon::ChestRear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match chest_rear { dragon::ChestRear::Default => "npc.dragon.chest_rear", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_tail_front(tail_front: dragon::TailFront) -> Mesh { +pub fn mesh_dragon_tail_front(tail_front: dragon::TailFront, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match tail_front { dragon::TailFront::Default => "npc.dragon.tail_front", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_tail_rear(tail_rear: dragon::TailRear) -> Mesh { +pub fn mesh_dragon_tail_rear(tail_rear: dragon::TailRear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match tail_rear { dragon::TailRear::Default => "npc.dragon.tail_rear", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_wing_in_l(wing_in_l: dragon::WingInL) -> Mesh { +pub fn mesh_dragon_wing_in_l(wing_in_l: dragon::WingInL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_in_l { dragon::WingInL::Default => "npc.dragon.wing_in_l", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_wing_in_r(wing_in_r: dragon::WingInR) -> Mesh { +pub fn mesh_dragon_wing_in_r(wing_in_r: dragon::WingInR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_in_r { dragon::WingInR::Default => "npc.dragon.wing_in_r", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_wing_out_l(wing_out_l: dragon::WingOutL) -> Mesh { +pub fn mesh_dragon_wing_out_l(wing_out_l: dragon::WingOutL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_out_l { dragon::WingOutL::Default => "npc.dragon.wing_out_l", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_wing_out_r(wing_out_r: dragon::WingOutR) -> Mesh { +pub fn mesh_dragon_wing_out_r(wing_out_r: dragon::WingOutR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_out_r { dragon::WingOutR::Default => "npc.dragon.wing_out_r", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_foot_fl(foot_fl: dragon::FootFL) -> Mesh { +pub fn mesh_dragon_foot_fl(foot_fl: dragon::FootFL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match foot_fl { dragon::FootFL::Default => "npc.dragon.foot_fl", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_foot_fr(foot_fr: dragon::FootFR) -> Mesh { +pub fn mesh_dragon_foot_fr(foot_fr: dragon::FootFR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match foot_fr { dragon::FootFR::Default => "npc.dragon.foot_fr", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_foot_bl(foot_bl: dragon::FootBL) -> Mesh { +pub fn mesh_dragon_foot_bl(foot_bl: dragon::FootBL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match foot_bl { dragon::FootBL::Default => "npc.dragon.foot_bl", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_dragon_foot_br(foot_br: dragon::FootBR) -> Mesh { +pub fn mesh_dragon_foot_br(foot_br: dragon::FootBR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match foot_br { dragon::FootBR::Default => "npc.dragon.foot_br", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } //// -pub fn mesh_bird_small_head(head: bird_small::Head) -> Mesh { +pub fn mesh_bird_small_head(head: bird_small::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match head { bird_small::Head::Default => "npc.crow.head", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_bird_small_torso(torso: bird_small::Torso) -> Mesh { +pub fn mesh_bird_small_torso(torso: bird_small::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match torso { bird_small::Torso::Default => "npc.crow.torso", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_bird_small_wing_l(wing_l: bird_small::WingL) -> Mesh { +pub fn mesh_bird_small_wing_l(wing_l: bird_small::WingL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_l { bird_small::WingL::Default => "npc.crow.wing_l", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_bird_small_wing_r(wing_r: bird_small::WingR) -> Mesh { +pub fn mesh_bird_small_wing_r(wing_r: bird_small::WingR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match wing_r { bird_small::WingR::Default => "npc.crow.wing_r", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } //// -pub fn mesh_fish_small_torso(torso: fish_small::Torso) -> Mesh { +pub fn mesh_fish_small_torso(torso: fish_small::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match torso { fish_small::Torso::Default => "npc.cardinalfish.torso", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } -pub fn mesh_fish_small_tail(tail: fish_small::Tail) -> Mesh { +pub fn mesh_fish_small_tail(tail: fish_small::Tail, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { load_mesh( match tail { fish_small::Tail::Default => "npc.cardinalfish.tail", }, Vec3::new(-7.0, -6.0, -6.0), + generate_mesh, ) } //// @@ -1801,7 +1822,7 @@ impl BipedLargeCenterSpec { .unwrap() } - pub fn mesh_head(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_head(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1809,7 +1830,7 @@ impl BipedLargeCenterSpec { "No head specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.head.center.0); @@ -1821,6 +1842,7 @@ impl BipedLargeCenterSpec { &self, species: BLSpecies, body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1829,7 +1851,7 @@ impl BipedLargeCenterSpec { "No torso upper specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.torso_upper.center.0); @@ -1841,6 +1863,7 @@ impl BipedLargeCenterSpec { &self, species: BLSpecies, body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1849,7 +1872,7 @@ impl BipedLargeCenterSpec { "No torso lower specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let center = graceful_load_segment(&spec.torso_lower.center.0); @@ -1867,6 +1890,7 @@ impl BipedLargeLateralSpec { &self, species: BLSpecies, body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1875,7 +1899,7 @@ impl BipedLargeLateralSpec { "No shoulder specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.shoulder_l.lateral.0); @@ -1887,6 +1911,7 @@ impl BipedLargeLateralSpec { &self, species: BLSpecies, body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, @@ -1895,7 +1920,7 @@ impl BipedLargeLateralSpec { "No shoulder specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.shoulder_r.lateral.0); @@ -1903,7 +1928,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.shoulder_r.offset)) } - pub fn mesh_hand_l(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_hand_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1911,7 +1936,7 @@ impl BipedLargeLateralSpec { "No hand specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.hand_l.lateral.0); @@ -1919,7 +1944,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.hand_l.offset)) } - pub fn mesh_hand_r(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_hand_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1927,7 +1952,7 @@ impl BipedLargeLateralSpec { "No hand specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.hand_r.lateral.0); @@ -1935,7 +1960,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.hand_r.offset)) } - pub fn mesh_leg_l(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_leg_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1943,7 +1968,7 @@ impl BipedLargeLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.leg_l.lateral.0); @@ -1951,7 +1976,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.leg_l.offset)) } - pub fn mesh_leg_r(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_leg_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1959,7 +1984,7 @@ impl BipedLargeLateralSpec { "No leg specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.leg_r.lateral.0); @@ -1967,7 +1992,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.leg_r.offset)) } - pub fn mesh_foot_l(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_foot_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1975,7 +2000,7 @@ impl BipedLargeLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.foot_l.lateral.0); @@ -1983,7 +2008,7 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.foot_l.offset)) } - pub fn mesh_foot_r(&self, species: BLSpecies, body_type: BLBodyType) -> Mesh { + pub fn mesh_foot_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1991,7 +2016,7 @@ impl BipedLargeLateralSpec { "No foot specification exists for the combination of {:?} and {:?}", species, body_type ); - return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5)); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); }, }; let lateral = graceful_load_segment(&spec.foot_r.lateral.0); @@ -2000,7 +2025,7 @@ impl BipedLargeLateralSpec { } } //// -pub fn mesh_object(obj: object::Body) -> Mesh { +pub fn mesh_object(obj: object::Body, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { use object::Body; let (name, offset) = match obj { @@ -2064,5 +2089,5 @@ pub fn mesh_object(obj: object::Body) -> Mesh { Body::BoltFire => ("weapon.projectile.fire-bolt-0", Vec3::new(-3.0, -5.5, -3.0)), Body::BoltFireBig => ("weapon.projectile.fire-bolt-1", Vec3::new(-6.0, -6.0, -6.0)), }; - load_mesh(name, offset) + load_mesh(name, offset, generate_mesh) } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 1686f091e6..fc48ded02c 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -117,7 +117,7 @@ impl FigureMgr { .get(scene_data.player_entity) .map_or(Vec3::zero(), |pos| pos.0); - for ( + for (i, ( entity, pos, interpolated, @@ -129,7 +129,7 @@ impl FigureMgr { physics, stats, loadout, - ) in ( + )) in ( &ecs.entities(), &ecs.read_storage::(), ecs.read_storage::().maybe(), @@ -143,7 +143,20 @@ impl FigureMgr { ecs.read_storage::().maybe(), ) .join() + .enumerate() { + // Maintaining figure data and sending new figure data to the GPU turns out to be a + // very expensive operation. We want to avoid doing it as much as possible, so we + // make the assumption that players don't care so much about the update *rate* for far + // away things. As the entity goes further and further away, we start to 'skip' update + // ticks. + // TODO: Investigate passing the velocity into the shader so we can at least + // interpolate motion + const MIN_PERFECT_RATE_DIST: f32 = 96.0; + if (i as u64 + tick) % 1 + ((pos.0.distance(camera.get_focus_pos()).powf(0.5) - MIN_PERFECT_RATE_DIST.powf(0.5)).max(0.0) / 5.0) as u64 != 0 { + continue; + } + let is_player = scene_data.player_entity == entity; let (pos, ori) = interpolated @@ -1385,7 +1398,7 @@ impl FigureMgr { let character_state_storage = state.read_storage::(); let character_state = character_state_storage.get(player_entity); - for (entity, _, _, body, _, loadout, _) in ( + for (entity, pos, _, body, _, loadout, _) in ( &ecs.entities(), &ecs.read_storage::(), ecs.read_storage::().maybe(), @@ -1413,6 +1426,7 @@ impl FigureMgr { body, loadout, false, + pos.0, ); } } @@ -1434,7 +1448,10 @@ impl FigureMgr { let character_state_storage = state.read_storage::(); let character_state = character_state_storage.get(player_entity); - if let Some(body) = ecs.read_storage::().get(player_entity) { + if let (Some(pos), Some(body)) = ( + ecs.read_storage::().get(player_entity), + ecs.read_storage::().get(player_entity), + ) { let stats_storage = state.read_storage::(); let stats = stats_storage.get(player_entity); @@ -1457,6 +1474,7 @@ impl FigureMgr { body, loadout, true, + pos.0, ); } } @@ -1474,6 +1492,7 @@ impl FigureMgr { body: &Body, loadout: Option<&Loadout>, is_player: bool, + pos: Vec3, ) { let player_camera_mode = if is_player { camera.get_mode() @@ -1686,6 +1705,17 @@ impl FigureMgr { ) }), } { + const FIGURE_LOD_LOW_DIST: f32 = 150.0; + const FIGURE_LOD_MID_DIST: f32 = 70.0; + + let model = if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_LOW_DIST.powf(2.0) { + &model[2] + } else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_MID_DIST.powf(2.0) { + &model[1] + } else { + &model[0] + }; + if is_player { renderer.render_player(model, globals, locals, bone_consts, lights, shadows); renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows); diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 77c1dbcf0f..5727ad1aa5 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -7,17 +7,20 @@ use crate::{ render::{ create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline, + Mesh, }, scene::{ camera::{self, Camera, CameraMode}, figure::{load_mesh, FigureModelCache, FigureState}, }, window::{Event, PressState}, + mesh::Meshable, }; use common::{ comp::{humanoid, Body, Loadout}, terrain::BlockKind, vol::{BaseVol, ReadVol, Vox}, + figure::Segment, }; use log::error; use vek::*; @@ -40,6 +43,10 @@ impl ReadVol for VoidVol { fn get<'a>(&'a self, _pos: Vec3) -> Result<&'a Self::Vox, Self::Error> { Ok(&VoidVox) } } +fn generate_mesh(segment: &Segment, offset: Vec3) -> Mesh { + Meshable::::generate_mesh(segment, (offset, Vec3::one())).0 +} + struct Skybox { model: Model, locals: Consts, @@ -107,7 +114,7 @@ impl Scene { backdrop: backdrop.map(|specifier| { ( renderer - .create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0))) + .create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0), generate_mesh)) .unwrap(), FigureState::new(renderer, FixtureSkeleton::new()), ) @@ -229,7 +236,7 @@ impl Scene { .0; renderer.render_figure( - model, + &model[0], &self.globals, self.figure_state.locals(), self.figure_state.bone_consts(), From ebd1537769fcd83d00be2221fec87ff0091c2dab Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 24 Apr 2020 19:52:44 +0100 Subject: [PATCH 11/27] Fixed figure update rate at a distance --- voxygen/src/scene/figure/cache.rs | 572 +++++++++++++++++------------- voxygen/src/scene/figure/load.rs | 505 +++++++++++++++++++++----- voxygen/src/scene/figure/mod.rs | 53 +-- voxygen/src/scene/simple.rs | 13 +- 4 files changed, 788 insertions(+), 355 deletions(-) diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 66ae5f5f00..67f4830554 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -1,25 +1,25 @@ use super::load::*; use crate::{ anim::{self, Skeleton}, + mesh::Meshable, render::{FigurePipeline, Mesh, Model, Renderer}, scene::camera::CameraMode, - mesh::Meshable, }; use common::{ - figure::Segment, assets::watch::ReloadIndicator, comp::{ item::{tool::ToolKind, ItemKind}, Body, CharacterState, Item, Loadout, }, + figure::Segment, vol::BaseVol, }; -use vek::*; use hashbrown::{hash_map::Entry, HashMap}; use std::{ convert::TryInto, mem::{discriminant, Discriminant}, }; +use vek::*; #[derive(PartialEq, Eq, Hash, Clone)] enum FigureKey { @@ -90,26 +90,18 @@ impl FigureModelCache { ) -> [Option>; 16] { match body { Body::Humanoid(body) => { - let humanoid_head_spec = - HumHeadSpec::load_watched(manifest_indicator); + let humanoid_head_spec = HumHeadSpec::load_watched(manifest_indicator); let humanoid_armor_shoulder_spec = HumArmorShoulderSpec::load_watched(manifest_indicator); - let humanoid_armor_chest_spec = - HumArmorChestSpec::load_watched(manifest_indicator); - let humanoid_armor_hand_spec = - HumArmorHandSpec::load_watched(manifest_indicator); - let humanoid_armor_belt_spec = - HumArmorBeltSpec::load_watched(manifest_indicator); - let humanoid_armor_back_spec = - HumArmorBackSpec::load_watched(manifest_indicator); + let humanoid_armor_chest_spec = HumArmorChestSpec::load_watched(manifest_indicator); + let humanoid_armor_hand_spec = HumArmorHandSpec::load_watched(manifest_indicator); + let humanoid_armor_belt_spec = HumArmorBeltSpec::load_watched(manifest_indicator); + let humanoid_armor_back_spec = HumArmorBackSpec::load_watched(manifest_indicator); let humanoid_armor_lantern_spec = HumArmorLanternSpec::load_watched(manifest_indicator); - let humanoid_armor_pants_spec = - HumArmorPantsSpec::load_watched(manifest_indicator); - let humanoid_armor_foot_spec = - HumArmorFootSpec::load_watched(manifest_indicator); - let humanoid_main_weapon_spec = - HumMainWeaponSpec::load_watched(manifest_indicator); + let humanoid_armor_pants_spec = HumArmorPantsSpec::load_watched(manifest_indicator); + let humanoid_armor_foot_spec = HumArmorFootSpec::load_watched(manifest_indicator); + let humanoid_main_weapon_spec = HumMainWeaponSpec::load_watched(manifest_indicator); // TODO: This is bad code, maybe this method should return Option<_> let default_loadout = Loadout::default(); @@ -117,26 +109,26 @@ impl FigureModelCache { [ match camera_mode { - CameraMode::ThirdPerson => { - Some(humanoid_head_spec.mesh_head( - body.race, - body.body_type, - body.hair_color, - body.hair_style, - body.beard, - body.eye_color, - body.skin, - body.eyebrows, - body.accessory, - generate_mesh, - )) - }, + CameraMode::ThirdPerson => Some(humanoid_head_spec.mesh_head( + body.race, + body.body_type, + body.hair_color, + body.hair_style, + body.beard, + body.eye_color, + body.skin, + body.eyebrows, + body.accessory, + generate_mesh, + )), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_chest_spec.mesh_chest(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => Some(humanoid_armor_chest_spec.mesh_chest( + &body, + loadout, + generate_mesh, + )), CameraMode::FirstPerson => None, }, match camera_mode { @@ -152,63 +144,69 @@ impl FigureModelCache { CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_pants_spec.mesh_pants(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => Some(humanoid_armor_pants_spec.mesh_pants( + &body, + loadout, + generate_mesh, + )), CameraMode::FirstPerson => None, }, if camera_mode == CameraMode::FirstPerson - && character_state - .map(|cs| cs.is_dodge()) - .unwrap_or_default() + && character_state.map(|cs| cs.is_dodge()).unwrap_or_default() { None } else { - Some( - humanoid_armor_hand_spec.mesh_left_hand(&body, loadout, generate_mesh), - ) + Some(humanoid_armor_hand_spec.mesh_left_hand(&body, loadout, generate_mesh)) }, if character_state.map(|cs| cs.is_dodge()).unwrap_or_default() { None } else { - Some( - humanoid_armor_hand_spec - .mesh_right_hand(&body, loadout, generate_mesh), - ) + Some(humanoid_armor_hand_spec.mesh_right_hand( + &body, + loadout, + generate_mesh, + )) }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_foot_spec.mesh_left_foot(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => Some(humanoid_armor_foot_spec.mesh_left_foot( + &body, + loadout, + generate_mesh, + )), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_foot_spec - .mesh_right_foot(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => Some(humanoid_armor_foot_spec.mesh_right_foot( + &body, + loadout, + generate_mesh, + )), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_shoulder_spec - .mesh_left_shoulder(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => { + Some(humanoid_armor_shoulder_spec.mesh_left_shoulder( + &body, + loadout, + generate_mesh, + )) + }, CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some( - humanoid_armor_shoulder_spec - .mesh_right_shoulder(&body, loadout, generate_mesh), - ), + CameraMode::ThirdPerson => { + Some(humanoid_armor_shoulder_spec.mesh_right_shoulder( + &body, + loadout, + generate_mesh, + )) + }, CameraMode::FirstPerson => None, }, Some(mesh_glider(generate_mesh)), if camera_mode != CameraMode::FirstPerson || character_state - .map(|cs| { - cs.is_attack() || cs.is_block() || cs.is_wield() - }) + .map(|cs| cs.is_attack() || cs.is_block() || cs.is_wield()) .unwrap_or_default() { Some(humanoid_main_weapon_spec.mesh_main_weapon( @@ -230,30 +228,36 @@ impl FigureModelCache { QuadrupedSmallLateralSpec::load_watched(manifest_indicator); [ - Some( - quadruped_small_central_spec - .mesh_head(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_small_central_spec - .mesh_chest(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_lf(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_rf(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_lb(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_small_lateral_spec - .mesh_foot_rb(body.species, body.body_type, generate_mesh), - ), + Some(quadruped_small_central_spec.mesh_head( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_small_central_spec.mesh_chest( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_small_lateral_spec.mesh_foot_lf( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_small_lateral_spec.mesh_foot_rf( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_small_lateral_spec.mesh_foot_lb( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_small_lateral_spec.mesh_foot_rb( + body.species, + body.body_type, + generate_mesh, + )), None, None, None, @@ -273,50 +277,61 @@ impl FigureModelCache { QuadrupedMediumLateralSpec::load_watched(manifest_indicator); [ - Some( - quadruped_medium_central_spec - .mesh_head_upper(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_head_lower(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_jaw(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_tail(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_torso_f(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_torso_b(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_central_spec - .mesh_ears(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_lf(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_rf(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_lb(body.species, body.body_type, generate_mesh), - ), - Some( - quadruped_medium_lateral_spec - .mesh_foot_rb(body.species, body.body_type, generate_mesh), - ), + Some(quadruped_medium_central_spec.mesh_head_upper( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_head_lower( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_jaw( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_tail( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_torso_f( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_torso_b( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_central_spec.mesh_ears( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_lateral_spec.mesh_foot_lf( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_lateral_spec.mesh_foot_rf( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_lateral_spec.mesh_foot_lb( + body.species, + body.body_type, + generate_mesh, + )), + Some(quadruped_medium_lateral_spec.mesh_foot_rb( + body.species, + body.body_type, + generate_mesh, + )), None, None, None, @@ -325,38 +340,47 @@ impl FigureModelCache { ] }, Body::BirdMedium(body) => { - let bird_medium_center_spec = BirdMediumCenterSpec::load_watched(manifest_indicator); - let bird_medium_lateral_spec = BirdMediumLateralSpec::load_watched(manifest_indicator); + let bird_medium_center_spec = + BirdMediumCenterSpec::load_watched(manifest_indicator); + let bird_medium_lateral_spec = + BirdMediumLateralSpec::load_watched(manifest_indicator); [ - Some( - bird_medium_center_spec - .mesh_head(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_center_spec - .mesh_torso(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_center_spec - .mesh_tail(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_lateral_spec - .mesh_wing_l(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_lateral_spec - .mesh_wing_r(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_lateral_spec - .mesh_foot_l(body.species, body.body_type, generate_mesh), - ), - Some( - bird_medium_lateral_spec - .mesh_foot_r(body.species, body.body_type, generate_mesh), - ), + Some(bird_medium_center_spec.mesh_head( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_center_spec.mesh_torso( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_center_spec.mesh_tail( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_lateral_spec.mesh_wing_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_lateral_spec.mesh_wing_r( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_lateral_spec.mesh_foot_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(bird_medium_lateral_spec.mesh_foot_r( + body.species, + body.body_type, + generate_mesh, + )), None, None, None, @@ -441,54 +465,67 @@ impl FigureModelCache { None, ], Body::BipedLarge(body) => { - let biped_large_center_spec = BipedLargeCenterSpec::load_watched(manifest_indicator); - let biped_large_lateral_spec = BipedLargeLateralSpec::load_watched(manifest_indicator); + let biped_large_center_spec = + BipedLargeCenterSpec::load_watched(manifest_indicator); + let biped_large_lateral_spec = + BipedLargeLateralSpec::load_watched(manifest_indicator); [ - Some( - biped_large_center_spec - .mesh_head(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_center_spec - .mesh_torso_upper(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_center_spec - .mesh_torso_lower(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_shoulder_l(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_shoulder_r(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_hand_l(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_hand_r(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_leg_l(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_leg_r(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_foot_l(body.species, body.body_type, generate_mesh), - ), - Some( - biped_large_lateral_spec - .mesh_foot_r(body.species, body.body_type, generate_mesh), - ), + Some(biped_large_center_spec.mesh_head( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_center_spec.mesh_torso_upper( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_center_spec.mesh_torso_lower( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_shoulder_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_shoulder_r( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_hand_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_hand_r( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_leg_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_leg_r( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_foot_l( + body.species, + body.body_type, + generate_mesh, + )), + Some(biped_large_lateral_spec.mesh_foot_r( + body.species, + body.body_type, + generate_mesh, + )), None, None, None, @@ -497,28 +534,34 @@ impl FigureModelCache { ] }, Body::Critter(body) => { - let critter_center_spec = - CritterCenterSpec::load_watched(manifest_indicator); + let critter_center_spec = CritterCenterSpec::load_watched(manifest_indicator); [ - Some( - critter_center_spec.mesh_head(body.species, body.body_type, generate_mesh), - ), - Some( - critter_center_spec - .mesh_chest(body.species, body.body_type, generate_mesh), - ), - Some( - critter_center_spec - .mesh_feet_f(body.species, body.body_type, generate_mesh), - ), - Some( - critter_center_spec - .mesh_feet_b(body.species, body.body_type, generate_mesh), - ), - Some( - critter_center_spec.mesh_tail(body.species, body.body_type, generate_mesh), - ), + Some(critter_center_spec.mesh_head( + body.species, + body.body_type, + generate_mesh, + )), + Some(critter_center_spec.mesh_chest( + body.species, + body.body_type, + generate_mesh, + )), + Some(critter_center_spec.mesh_feet_f( + body.species, + body.body_type, + generate_mesh, + )), + Some(critter_center_spec.mesh_feet_b( + body.species, + body.body_type, + generate_mesh, + )), + Some(critter_center_spec.mesh_tail( + body.species, + body.body_type, + generate_mesh, + )), None, None, None, @@ -593,35 +636,66 @@ impl FigureModelCache { let manifest_indicator = &mut self.manifest_indicator; let mut make_model = |generate_mesh| { let mut mesh = Mesh::new(); - Self::bone_meshes(body, loadout, character_state, camera_mode, manifest_indicator, generate_mesh) - .iter() - .enumerate() - .filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm))) - .for_each(|(i, bone_mesh)| { - mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8)) - }); + Self::bone_meshes( + body, + loadout, + character_state, + camera_mode, + manifest_indicator, + generate_mesh, + ) + .iter() + .enumerate() + .filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm))) + .for_each(|(i, bone_mesh)| { + mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8)) + }); renderer.create_model(&mesh).unwrap() }; - fn generate_mesh(segment: &Segment, offset: Vec3) -> Mesh { - Meshable::::generate_mesh(segment, (offset, Vec3::one())).0 + fn generate_mesh( + segment: &Segment, + offset: Vec3, + ) -> Mesh { + Meshable::::generate_mesh( + segment, + (offset, Vec3::one()), + ) + .0 } - fn generate_mesh_lod_mid(segment: &Segment, offset: Vec3) -> Mesh { + fn generate_mesh_lod_mid( + segment: &Segment, + offset: Vec3, + ) -> Mesh { let lod_scale = Vec3::broadcast(0.6); - Meshable::::generate_mesh(&segment.scaled_by(lod_scale), (offset * lod_scale, Vec3::one() / lod_scale)).0 + Meshable::::generate_mesh( + &segment.scaled_by(lod_scale), + (offset * lod_scale, Vec3::one() / lod_scale), + ) + .0 } - fn generate_mesh_lod_low(segment: &Segment, offset: Vec3) -> Mesh { + fn generate_mesh_lod_low( + segment: &Segment, + offset: Vec3, + ) -> Mesh { let lod_scale = Vec3::broadcast(0.3); - Meshable::::generate_mesh(&segment.scaled_by(lod_scale), (offset * lod_scale, Vec3::one() / lod_scale)).0 + Meshable::::generate_mesh( + &segment.scaled_by(lod_scale), + (offset * lod_scale, Vec3::one() / lod_scale), + ) + .0 } - ([ - make_model(generate_mesh), - make_model(generate_mesh_lod_mid), - make_model(generate_mesh_lod_low), - ], skeleton_attr) + ( + [ + make_model(generate_mesh), + make_model(generate_mesh_lod_mid), + make_model(generate_mesh_lod_low), + ], + skeleton_attr, + ) }, tick, )) diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index b19ab5e004..904ccfbb43 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -51,7 +51,11 @@ fn graceful_load_mat_segment_flipped(mesh_name: &str) -> MatSegment { MatSegment::from_vox(graceful_load_vox(mesh_name).as_ref(), true) } -pub fn load_mesh(mesh_name: &str, position: Vec3, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn load_mesh( + mesh_name: &str, + position: Vec3, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { generate_mesh(&load_segment(mesh_name), position) } @@ -343,7 +347,13 @@ impl HumArmorShoulderSpec { .unwrap() } - fn mesh_shoulder(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + fn mesh_shoulder( + &self, + body: &Body, + loadout: &Loadout, + flipped: bool, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Shoulder(shoulder), .. @@ -385,11 +395,21 @@ impl HumArmorShoulderSpec { generate_mesh(&shoulder_segment, Vec3::from(offset)) } - pub fn mesh_left_shoulder(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_left_shoulder( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_shoulder(body, loadout, true, generate_mesh) } - pub fn mesh_right_shoulder(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_right_shoulder( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_shoulder(body, loadout, false, generate_mesh) } } @@ -400,7 +420,12 @@ impl HumArmorChestSpec { .unwrap() } - pub fn mesh_chest(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_chest( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Chest(chest), .. @@ -451,7 +476,13 @@ impl HumArmorHandSpec { .unwrap() } - fn mesh_hand(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + fn mesh_hand( + &self, + body: &Body, + loadout: &Loadout, + flipped: bool, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Hand(hand), .. @@ -488,11 +519,21 @@ impl HumArmorHandSpec { generate_mesh(&hand_segment, Vec3::from(offset)) } - pub fn mesh_left_hand(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_left_hand( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_hand(body, loadout, true, generate_mesh) } - pub fn mesh_right_hand(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_right_hand( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_hand(body, loadout, false, generate_mesh) } } @@ -503,7 +544,12 @@ impl HumArmorBeltSpec { .unwrap() } - pub fn mesh_belt(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_belt( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Belt(belt), .. @@ -537,7 +583,12 @@ impl HumArmorBackSpec { .unwrap() } - pub fn mesh_back(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_back( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Back(back), .. @@ -571,7 +622,12 @@ impl HumArmorPantsSpec { .unwrap() } - pub fn mesh_pants(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_pants( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Pants(pants), .. @@ -622,7 +678,13 @@ impl HumArmorFootSpec { .unwrap() } - fn mesh_foot(&self, body: &Body, loadout: &Loadout, flipped: bool, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + fn mesh_foot( + &self, + body: &Body, + loadout: &Loadout, + flipped: bool, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Foot(foot), .. @@ -653,11 +715,21 @@ impl HumArmorFootSpec { generate_mesh(&foot_segment, Vec3::from(spec.vox_spec.1)) } - pub fn mesh_left_foot(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_left_foot( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_foot(body, loadout, true, generate_mesh) } - pub fn mesh_right_foot(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_right_foot( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { self.mesh_foot(body, loadout, false, generate_mesh) } } @@ -668,7 +740,11 @@ impl HumMainWeaponSpec { .unwrap() } - pub fn mesh_main_weapon(&self, item_kind: Option<&ItemKind>, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_main_weapon( + &self, + item_kind: Option<&ItemKind>, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let tool_kind = if let Some(ItemKind::Tool(Tool { kind, .. })) = item_kind { kind } else { @@ -693,7 +769,12 @@ impl HumArmorLanternSpec { assets::load_watched::("voxygen.voxel.humanoid_lantern_manifest", indicator).unwrap() } - pub fn mesh_lantern(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_lantern( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Lantern(lantern)) = loadout.lantern.as_ref().map(|i| &i.kind) { match self.0.map.get(&lantern) { @@ -723,7 +804,12 @@ impl HumArmorHeadSpec { .unwrap() } - pub fn mesh_head(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_head( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Head(head), .. @@ -773,7 +859,12 @@ impl HumArmorTabardSpec { .unwrap() } - pub fn mesh_tabard(&self, body: &Body, loadout: &Loadout, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_tabard( + &self, + body: &Body, + loadout: &Loadout, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = if let Some(ItemKind::Armor { kind: Armor::Tabard(tabard), .. @@ -818,8 +909,14 @@ impl HumArmorTabardSpec { } } // TODO: Inventory -pub fn mesh_glider(generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { - load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0), generate_mesh) +pub fn mesh_glider( + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { + load_mesh( + "object.glider", + Vec3::new(-26.0, -26.0, -5.0), + generate_mesh, + ) } ///////// @@ -875,7 +972,12 @@ impl QuadrupedSmallCentralSpec { .unwrap() } - pub fn mesh_head(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_head( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -891,7 +993,12 @@ impl QuadrupedSmallCentralSpec { generate_mesh(¢ral, Vec3::from(spec.head.offset)) } - pub fn mesh_chest(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_chest( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -914,7 +1021,12 @@ impl QuadrupedSmallLateralSpec { .unwrap() } - pub fn mesh_foot_lf(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_lf( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -930,7 +1042,12 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_front.offset)) } - pub fn mesh_foot_rf(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_rf( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -946,7 +1063,12 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.right_front.offset)) } - pub fn mesh_foot_lb(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_lb( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -962,7 +1084,12 @@ impl QuadrupedSmallLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_back.offset)) } - pub fn mesh_foot_rb(&self, species: QSSpecies, body_type: QSBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_rb( + &self, + species: QSSpecies, + body_type: QSBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1078,7 +1205,12 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.lower.offset)) } - pub fn mesh_jaw(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_jaw( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1094,7 +1226,12 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.jaw.offset)) } - pub fn mesh_ears(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_ears( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1110,7 +1247,12 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.ears.offset)) } - pub fn mesh_torso_f(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_torso_f( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1126,7 +1268,12 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.torso_f.offset)) } - pub fn mesh_torso_b(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_torso_b( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1142,7 +1289,12 @@ impl QuadrupedMediumCentralSpec { generate_mesh(¢ral, Vec3::from(spec.torso_b.offset)) } - pub fn mesh_tail(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_tail( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1165,7 +1317,12 @@ impl QuadrupedMediumLateralSpec { .unwrap() } - pub fn mesh_foot_lf(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_lf( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1181,7 +1338,12 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_front.offset)) } - pub fn mesh_foot_rf(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_rf( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1197,7 +1359,12 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.right_front.offset)) } - pub fn mesh_foot_lb(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_lb( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1213,7 +1380,12 @@ impl QuadrupedMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.left_back.offset)) } - pub fn mesh_foot_rb(&self, species: QMSpecies, body_type: QMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_rb( + &self, + species: QMSpecies, + body_type: QMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1284,7 +1456,12 @@ impl BirdMediumCenterSpec { .unwrap() } - pub fn mesh_head(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_head( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1300,7 +1477,12 @@ impl BirdMediumCenterSpec { generate_mesh(¢er, Vec3::from(spec.head.offset)) } - pub fn mesh_torso(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_torso( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1316,7 +1498,12 @@ impl BirdMediumCenterSpec { generate_mesh(¢er, Vec3::from(spec.torso.offset)) } - pub fn mesh_tail(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_tail( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1338,7 +1525,12 @@ impl BirdMediumLateralSpec { .unwrap() } - pub fn mesh_wing_l(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_wing_l( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1354,7 +1546,12 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.wing_l.offset)) } - pub fn mesh_wing_r(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_wing_r( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1370,7 +1567,12 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.wing_r.offset)) } - pub fn mesh_foot_l(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_l( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1386,7 +1588,12 @@ impl BirdMediumLateralSpec { generate_mesh(&lateral, Vec3::from(spec.foot_l.offset)) } - pub fn mesh_foot_r(&self, species: BMSpecies, body_type: BMBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_r( + &self, + species: BMSpecies, + body_type: BMBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1433,7 +1640,12 @@ impl CritterCenterSpec { assets::load_watched::("voxygen.voxel.critter_center_manifest", indicator).unwrap() } - pub fn mesh_head(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_head( + &self, + species: CSpecies, + body_type: CBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1449,7 +1661,12 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.head.offset)) } - pub fn mesh_chest(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_chest( + &self, + species: CSpecies, + body_type: CBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1465,7 +1682,12 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.chest.offset)) } - pub fn mesh_feet_f(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_feet_f( + &self, + species: CSpecies, + body_type: CBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1481,7 +1703,12 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.feet_f.offset)) } - pub fn mesh_feet_b(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_feet_b( + &self, + species: CSpecies, + body_type: CBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1497,7 +1724,12 @@ impl CritterCenterSpec { generate_mesh(¢er, Vec3::from(spec.feet_b.offset)) } - pub fn mesh_tail(&self, species: CSpecies, body_type: CBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_tail( + &self, + species: CSpecies, + body_type: CBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1514,7 +1746,10 @@ impl CritterCenterSpec { } } //// -pub fn mesh_fish_medium_head(head: fish_medium::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_head( + head: fish_medium::Head, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match head { fish_medium::Head::Default => "npc.marlin.head", @@ -1524,7 +1759,10 @@ pub fn mesh_fish_medium_head(head: fish_medium::Head, generate_mesh: impl FnOnce ) } -pub fn mesh_fish_medium_torso(torso: fish_medium::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_torso( + torso: fish_medium::Torso, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match torso { fish_medium::Torso::Default => "npc.marlin.torso", @@ -1534,7 +1772,10 @@ pub fn mesh_fish_medium_torso(torso: fish_medium::Torso, generate_mesh: impl FnO ) } -pub fn mesh_fish_medium_rear(rear: fish_medium::Rear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_rear( + rear: fish_medium::Rear, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match rear { fish_medium::Rear::Default => "npc.marlin.rear", @@ -1544,7 +1785,10 @@ pub fn mesh_fish_medium_rear(rear: fish_medium::Rear, generate_mesh: impl FnOnce ) } -pub fn mesh_fish_medium_tail(tail: fish_medium::Tail, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_tail( + tail: fish_medium::Tail, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match tail { fish_medium::Tail::Default => "npc.marlin.tail", @@ -1554,7 +1798,10 @@ pub fn mesh_fish_medium_tail(tail: fish_medium::Tail, generate_mesh: impl FnOnce ) } -pub fn mesh_fish_medium_fin_l(fin_l: fish_medium::FinL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_fin_l( + fin_l: fish_medium::FinL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match fin_l { fish_medium::FinL::Default => "npc.marlin.fin_l", @@ -1564,7 +1811,10 @@ pub fn mesh_fish_medium_fin_l(fin_l: fish_medium::FinL, generate_mesh: impl FnOn ) } -pub fn mesh_fish_medium_fin_r(fin_r: fish_medium::FinR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_medium_fin_r( + fin_r: fish_medium::FinR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match fin_r { fish_medium::FinR::Default => "npc.marlin.fin_r", @@ -1574,7 +1824,10 @@ pub fn mesh_fish_medium_fin_r(fin_r: fish_medium::FinR, generate_mesh: impl FnOn ) } -pub fn mesh_dragon_head(head: dragon::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_head( + head: dragon::Head, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match head { dragon::Head::Default => "npc.dragon.head", @@ -1584,7 +1837,10 @@ pub fn mesh_dragon_head(head: dragon::Head, generate_mesh: impl FnOnce(&Segment, ) } -pub fn mesh_dragon_chest_front(chest_front: dragon::ChestFront, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_chest_front( + chest_front: dragon::ChestFront, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match chest_front { dragon::ChestFront::Default => "npc.dragon.chest_front", @@ -1594,7 +1850,10 @@ pub fn mesh_dragon_chest_front(chest_front: dragon::ChestFront, generate_mesh: i ) } -pub fn mesh_dragon_chest_rear(chest_rear: dragon::ChestRear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_chest_rear( + chest_rear: dragon::ChestRear, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match chest_rear { dragon::ChestRear::Default => "npc.dragon.chest_rear", @@ -1604,7 +1863,10 @@ pub fn mesh_dragon_chest_rear(chest_rear: dragon::ChestRear, generate_mesh: impl ) } -pub fn mesh_dragon_tail_front(tail_front: dragon::TailFront, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_tail_front( + tail_front: dragon::TailFront, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match tail_front { dragon::TailFront::Default => "npc.dragon.tail_front", @@ -1614,7 +1876,10 @@ pub fn mesh_dragon_tail_front(tail_front: dragon::TailFront, generate_mesh: impl ) } -pub fn mesh_dragon_tail_rear(tail_rear: dragon::TailRear, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_tail_rear( + tail_rear: dragon::TailRear, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match tail_rear { dragon::TailRear::Default => "npc.dragon.tail_rear", @@ -1624,7 +1889,10 @@ pub fn mesh_dragon_tail_rear(tail_rear: dragon::TailRear, generate_mesh: impl Fn ) } -pub fn mesh_dragon_wing_in_l(wing_in_l: dragon::WingInL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_wing_in_l( + wing_in_l: dragon::WingInL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_in_l { dragon::WingInL::Default => "npc.dragon.wing_in_l", @@ -1634,7 +1902,10 @@ pub fn mesh_dragon_wing_in_l(wing_in_l: dragon::WingInL, generate_mesh: impl FnO ) } -pub fn mesh_dragon_wing_in_r(wing_in_r: dragon::WingInR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_wing_in_r( + wing_in_r: dragon::WingInR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_in_r { dragon::WingInR::Default => "npc.dragon.wing_in_r", @@ -1644,7 +1915,10 @@ pub fn mesh_dragon_wing_in_r(wing_in_r: dragon::WingInR, generate_mesh: impl FnO ) } -pub fn mesh_dragon_wing_out_l(wing_out_l: dragon::WingOutL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_wing_out_l( + wing_out_l: dragon::WingOutL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_out_l { dragon::WingOutL::Default => "npc.dragon.wing_out_l", @@ -1654,7 +1928,10 @@ pub fn mesh_dragon_wing_out_l(wing_out_l: dragon::WingOutL, generate_mesh: impl ) } -pub fn mesh_dragon_wing_out_r(wing_out_r: dragon::WingOutR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_wing_out_r( + wing_out_r: dragon::WingOutR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_out_r { dragon::WingOutR::Default => "npc.dragon.wing_out_r", @@ -1664,7 +1941,10 @@ pub fn mesh_dragon_wing_out_r(wing_out_r: dragon::WingOutR, generate_mesh: impl ) } -pub fn mesh_dragon_foot_fl(foot_fl: dragon::FootFL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_foot_fl( + foot_fl: dragon::FootFL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match foot_fl { dragon::FootFL::Default => "npc.dragon.foot_fl", @@ -1674,7 +1954,10 @@ pub fn mesh_dragon_foot_fl(foot_fl: dragon::FootFL, generate_mesh: impl FnOnce(& ) } -pub fn mesh_dragon_foot_fr(foot_fr: dragon::FootFR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_foot_fr( + foot_fr: dragon::FootFR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match foot_fr { dragon::FootFR::Default => "npc.dragon.foot_fr", @@ -1684,7 +1967,10 @@ pub fn mesh_dragon_foot_fr(foot_fr: dragon::FootFR, generate_mesh: impl FnOnce(& ) } -pub fn mesh_dragon_foot_bl(foot_bl: dragon::FootBL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_foot_bl( + foot_bl: dragon::FootBL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match foot_bl { dragon::FootBL::Default => "npc.dragon.foot_bl", @@ -1694,7 +1980,10 @@ pub fn mesh_dragon_foot_bl(foot_bl: dragon::FootBL, generate_mesh: impl FnOnce(& ) } -pub fn mesh_dragon_foot_br(foot_br: dragon::FootBR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_dragon_foot_br( + foot_br: dragon::FootBR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match foot_br { dragon::FootBR::Default => "npc.dragon.foot_br", @@ -1705,7 +1994,10 @@ pub fn mesh_dragon_foot_br(foot_br: dragon::FootBR, generate_mesh: impl FnOnce(& } //// -pub fn mesh_bird_small_head(head: bird_small::Head, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_bird_small_head( + head: bird_small::Head, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match head { bird_small::Head::Default => "npc.crow.head", @@ -1715,7 +2007,10 @@ pub fn mesh_bird_small_head(head: bird_small::Head, generate_mesh: impl FnOnce(& ) } -pub fn mesh_bird_small_torso(torso: bird_small::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_bird_small_torso( + torso: bird_small::Torso, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match torso { bird_small::Torso::Default => "npc.crow.torso", @@ -1725,7 +2020,10 @@ pub fn mesh_bird_small_torso(torso: bird_small::Torso, generate_mesh: impl FnOnc ) } -pub fn mesh_bird_small_wing_l(wing_l: bird_small::WingL, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_bird_small_wing_l( + wing_l: bird_small::WingL, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_l { bird_small::WingL::Default => "npc.crow.wing_l", @@ -1735,7 +2033,10 @@ pub fn mesh_bird_small_wing_l(wing_l: bird_small::WingL, generate_mesh: impl FnO ) } -pub fn mesh_bird_small_wing_r(wing_r: bird_small::WingR, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_bird_small_wing_r( + wing_r: bird_small::WingR, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match wing_r { bird_small::WingR::Default => "npc.crow.wing_r", @@ -1745,7 +2046,10 @@ pub fn mesh_bird_small_wing_r(wing_r: bird_small::WingR, generate_mesh: impl FnO ) } //// -pub fn mesh_fish_small_torso(torso: fish_small::Torso, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_small_torso( + torso: fish_small::Torso, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match torso { fish_small::Torso::Default => "npc.cardinalfish.torso", @@ -1755,7 +2059,10 @@ pub fn mesh_fish_small_torso(torso: fish_small::Torso, generate_mesh: impl FnOnc ) } -pub fn mesh_fish_small_tail(tail: fish_small::Tail, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_fish_small_tail( + tail: fish_small::Tail, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { load_mesh( match tail { fish_small::Tail::Default => "npc.cardinalfish.tail", @@ -1822,7 +2129,12 @@ impl BipedLargeCenterSpec { .unwrap() } - pub fn mesh_head(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_head( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1928,7 +2240,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.shoulder_r.offset)) } - pub fn mesh_hand_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_hand_l( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1944,7 +2261,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.hand_l.offset)) } - pub fn mesh_hand_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_hand_r( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1960,7 +2282,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.hand_r.offset)) } - pub fn mesh_leg_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_leg_l( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1976,7 +2303,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.leg_l.offset)) } - pub fn mesh_leg_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_leg_r( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -1992,7 +2324,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.leg_r.offset)) } - pub fn mesh_foot_l(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_l( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -2008,7 +2345,12 @@ impl BipedLargeLateralSpec { generate_mesh(&lateral, Vec3::from(spec.foot_l.offset)) } - pub fn mesh_foot_r(&self, species: BLSpecies, body_type: BLBodyType, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { + pub fn mesh_foot_r( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { let spec = match self.0.get(&(species, body_type)) { Some(spec) => spec, None => { @@ -2025,7 +2367,10 @@ impl BipedLargeLateralSpec { } } //// -pub fn mesh_object(obj: object::Body, generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh) -> Mesh { +pub fn mesh_object( + obj: object::Body, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, +) -> Mesh { use object::Body; let (name, offset) = match obj { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index fc48ded02c..8f228bb773 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -117,19 +117,22 @@ impl FigureMgr { .get(scene_data.player_entity) .map_or(Vec3::zero(), |pos| pos.0); - for (i, ( - entity, - pos, - interpolated, - vel, - scale, - body, - character, - last_character, - physics, - stats, - loadout, - )) in ( + for ( + i, + ( + entity, + pos, + interpolated, + vel, + scale, + body, + character, + last_character, + physics, + stats, + loadout, + ), + ) in ( &ecs.entities(), &ecs.read_storage::(), ecs.read_storage::().maybe(), @@ -145,15 +148,21 @@ impl FigureMgr { .join() .enumerate() { - // Maintaining figure data and sending new figure data to the GPU turns out to be a - // very expensive operation. We want to avoid doing it as much as possible, so we - // make the assumption that players don't care so much about the update *rate* for far - // away things. As the entity goes further and further away, we start to 'skip' update - // ticks. + // Maintaining figure data and sending new figure data to the GPU turns out to + // be a very expensive operation. We want to avoid doing it as much + // as possible, so we make the assumption that players don't care so + // much about the update *rate* for far away things. As the entity + // goes further and further away, we start to 'skip' update ticks. // TODO: Investigate passing the velocity into the shader so we can at least // interpolate motion - const MIN_PERFECT_RATE_DIST: f32 = 96.0; - if (i as u64 + tick) % 1 + ((pos.0.distance(camera.get_focus_pos()).powf(0.5) - MIN_PERFECT_RATE_DIST.powf(0.5)).max(0.0) / 5.0) as u64 != 0 { + const MIN_PERFECT_RATE_DIST: f32 = 50.0; + if (i as u64 + tick) % (1 + + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25) + - MIN_PERFECT_RATE_DIST.powf(0.5)) + .max(0.0) + / 3.0) as u64) + != 0 + { continue; } @@ -1708,7 +1717,9 @@ impl FigureMgr { const FIGURE_LOD_LOW_DIST: f32 = 150.0; const FIGURE_LOD_MID_DIST: f32 = 70.0; - let model = if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_LOW_DIST.powf(2.0) { + let model = if pos.distance_squared(camera.get_focus_pos()) + > FIGURE_LOD_LOW_DIST.powf(2.0) + { &model[2] } else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_MID_DIST.powf(2.0) { &model[1] diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 5727ad1aa5..8abf6be9a7 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -4,23 +4,22 @@ use crate::{ fixture::FixtureSkeleton, Animation, Skeleton, }, + mesh::Meshable, render::{ - create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model, + create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Mesh, Model, PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline, - Mesh, }, scene::{ camera::{self, Camera, CameraMode}, figure::{load_mesh, FigureModelCache, FigureState}, }, window::{Event, PressState}, - mesh::Meshable, }; use common::{ comp::{humanoid, Body, Loadout}, + figure::Segment, terrain::BlockKind, vol::{BaseVol, ReadVol, Vox}, - figure::Segment, }; use log::error; use vek::*; @@ -114,7 +113,11 @@ impl Scene { backdrop: backdrop.map(|specifier| { ( renderer - .create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0), generate_mesh)) + .create_model(&load_mesh( + specifier, + Vec3::new(-55.0, -49.5, -2.0), + generate_mesh, + )) .unwrap(), FigureState::new(renderer, FixtureSkeleton::new()), ) From feca113c86a7bac0e7fa3cbe95f3f7f843f6ee05 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 24 Apr 2020 18:08:59 -0400 Subject: [PATCH 12/27] fix for hollow chests --- assets/voxygen/voxel/sprite/chests/chest.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_dark.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_demon.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_gold.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_light.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_skull.vox | 4 ++-- assets/voxygen/voxel/sprite/chests/chest_vines.vox | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/assets/voxygen/voxel/sprite/chests/chest.vox b/assets/voxygen/voxel/sprite/chests/chest.vox index 5e6fe09e6d..a53f8947d6 100644 --- a/assets/voxygen/voxel/sprite/chests/chest.vox +++ b/assets/voxygen/voxel/sprite/chests/chest.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:964619ec04d1d799d37fd4f7e6f7a9ff330cf10172baed9d551542172e7be84e -size 5092 +oid sha256:f89820cd9b32bd4e9cd84f1f3d43530c0bbec1aa14649c9b5ef5f67b13fe458b +size 7516 diff --git a/assets/voxygen/voxel/sprite/chests/chest_dark.vox b/assets/voxygen/voxel/sprite/chests/chest_dark.vox index d46c0c1563..32c2519e09 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_dark.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_dark.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e31c3e53a5df23ac194dee70496d73d56a12966889acfb87ac94173a5672f83e -size 4720 +oid sha256:aa0d381595de0624a7ea3f6e0115836d3aa97344d537bee7d56ec237724411e1 +size 7516 diff --git a/assets/voxygen/voxel/sprite/chests/chest_demon.vox b/assets/voxygen/voxel/sprite/chests/chest_demon.vox index aa213775bf..389f97748c 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_demon.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_demon.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1e58917b892e8209484b8f0596b97ad0a6b7dee17916eac06d66fa4fdeac332 -size 4712 +oid sha256:ad4452aa4e64713bb5c9f92ff2e91f1567c55fa8e11b6ce1583903ef6135d5d5 +size 7508 diff --git a/assets/voxygen/voxel/sprite/chests/chest_gold.vox b/assets/voxygen/voxel/sprite/chests/chest_gold.vox index 78f23a17bc..7b33d85c83 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_gold.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_gold.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9e3e07cbcd142777f0ffbfc5a1d03ed278c37a7f15bf28052146d50376135d0 -size 4720 +oid sha256:324624d423c4b627923096e936dda4f496cd1306363a8f14a07d10e8ede30eb2 +size 7516 diff --git a/assets/voxygen/voxel/sprite/chests/chest_light.vox b/assets/voxygen/voxel/sprite/chests/chest_light.vox index fdb9bc30c3..91a258f479 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_light.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_light.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97c3df0823abea550fae4a8346961e5ced496629328c476391c8f2c2d6410075 -size 4720 +oid sha256:5705ae83a952b8cfcbe2d945c43c663cc8fb99af0d7be55530a3ca1c0453ce75 +size 7516 diff --git a/assets/voxygen/voxel/sprite/chests/chest_skull.vox b/assets/voxygen/voxel/sprite/chests/chest_skull.vox index 36bbba84aa..ac5f2d23d6 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_skull.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_skull.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:597406e569312f237439d8c6b51fe1ace98b499dfe2cbc95566dee3ad1c037d4 -size 4708 +oid sha256:ab10e8033706d30681733c2329c6a0ab86242a358041f3aa39f4302463feada6 +size 7504 diff --git a/assets/voxygen/voxel/sprite/chests/chest_vines.vox b/assets/voxygen/voxel/sprite/chests/chest_vines.vox index 418c3cb5dc..ae5ca39aa2 100644 --- a/assets/voxygen/voxel/sprite/chests/chest_vines.vox +++ b/assets/voxygen/voxel/sprite/chests/chest_vines.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e0fc1699b25c1ac778001d6a9c498700abbe2a5a1ce9ef9ac7b0136c8db0043 -size 4996 +oid sha256:939eae713abcbc364ed6a4dda765a4752d54b2f0f69873f8d6fb75ad3952a76a +size 7792 From 3421b3d8da64b0ad2c687c8e851b25e1a96adf07 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Sat, 25 Apr 2020 00:35:40 +0200 Subject: [PATCH 13/27] sprites VD slider visuals --- assets/voxygen/i18n/de_DE.ron | 3 ++- assets/voxygen/i18n/en.ron | 1 + voxygen/src/hud/settings_window.rs | 39 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/assets/voxygen/i18n/de_DE.ron b/assets/voxygen/i18n/de_DE.ron index 5c9e7b21d8..c2b672e579 100644 --- a/assets/voxygen/i18n/de_DE.ron +++ b/assets/voxygen/i18n/de_DE.ron @@ -252,7 +252,8 @@ Viel Spaß in der Welt von Veloren, Abenteurer!"#, "hud.settings.invert_mouse_y_axis": "Maus Y-Achse invertieren", "hud.settings.free_look_behavior": "Freies Umsehen", - "hud.settings.view_distance": "Sichtweite", + "hud.settings.view_distance": "Gelände Sichtweite", + "hud.settings.sprites_view_distance": "Objekt Sichtweite", "hud.settings.maximum_fps": "Maximale FPS", "hud.settings.fov": "Sichtfeld (Grad)", "hud.settings.gamma": "Gamma", diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron index 6e39d56c43..ef5b00b544 100644 --- a/assets/voxygen/i18n/en.ron +++ b/assets/voxygen/i18n/en.ron @@ -250,6 +250,7 @@ Enjoy your stay in the World of Veloren."#, "hud.settings.free_look_behavior": "Free look behavior", "hud.settings.view_distance": "View Distance", + "hud.settings.sprites_view_distance": "Sprites View Distance", "hud.settings.maximum_fps": "Maximum FPS", "hud.settings.fov": "Field of View (deg)", "hud.settings.gamma": "Gamma", diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index 7f2e517c51..fac506bc54 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -89,6 +89,9 @@ widget_ids! { vd_slider, vd_text, vd_value, + sprite_dist_slider, + sprite_dist_text, + sprite_dist_value, max_fps_slider, max_fps_text, max_fps_value, @@ -1612,7 +1615,43 @@ impl<'a> Widget for SettingsWindow<'a> { .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) .set(state.ids.gamma_value, ui); + // Sprites VD + if let Some(new_val) = ImageSlider::discrete( + self.global_state.settings.graphics.view_distance, + 1, + 65, + self.imgs.slider_indicator, + self.imgs.slider, + ) + .w_h(104.0, 22.0) + .right_from(state.ids.vd_slider, 50.0) + .track_breadth(12.0) + .slider_length(10.0) + .pad_track((5.0, 5.0)) + .set(state.ids.sprite_dist_slider, ui) + { + events.push(Event::AdjustViewDistance(new_val)); + } + Text::new( + &self + .localized_strings + .get("hud.settings.sprites_view_distance"), + ) + .up_from(state.ids.sprite_dist_slider, 8.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.sprite_dist_text, ui); + Text::new(&format!( + "{}", + self.global_state.settings.graphics.view_distance + )) + .right_from(state.ids.sprite_dist_slider, 8.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.sprite_dist_value, ui); // AaMode Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode")) .down_from(state.ids.gamma_slider, 8.0) From 1feae79243c8e00db772ab7ab67f6dc772ece447 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 11:23:46 +0100 Subject: [PATCH 14/27] Added reseeding for sites --- voxygen/src/scene/figure/mod.rs | 4 ++-- world/src/civ/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 8f228bb773..497d8077fe 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -156,8 +156,8 @@ impl FigureMgr { // TODO: Investigate passing the velocity into the shader so we can at least // interpolate motion const MIN_PERFECT_RATE_DIST: f32 = 50.0; - if (i as u64 + tick) % (1 - + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25) + if (i as u64 + tick) + % (1 + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25) - MIN_PERFECT_RATE_DIST.powf(0.5)) .max(0.0) / 3.0) as u64) diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index a8a9d83846..ec945e0d13 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -142,10 +142,10 @@ impl Civs { let world_site = match &site.kind { SiteKind::Settlement => { - WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut ctx.rng)) + WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut ctx.reseed().rng)) }, SiteKind::Dungeon => { - WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut ctx.rng)) + WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut ctx.reseed().rng)) }, }; From 5bdc42072633ce897fdd8d60e29ce3969a965972 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 11:24:51 +0100 Subject: [PATCH 15/27] Harbarboofarfoobar --- world/src/civ/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index ec945e0d13..4cf4479b24 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -141,12 +141,16 @@ impl Civs { }); let world_site = match &site.kind { - SiteKind::Settlement => { - WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut ctx.reseed().rng)) - }, - SiteKind::Dungeon => { - WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut ctx.reseed().rng)) - }, + SiteKind::Settlement => WorldSite::from(Settlement::generate( + wpos, + Some(ctx.sim), + &mut ctx.reseed().rng, + )), + SiteKind::Dungeon => WorldSite::from(Dungeon::generate( + wpos, + Some(ctx.sim), + &mut ctx.reseed().rng, + )), }; let radius_chunks = From 8bf5709ddf632711d4f021bcf57fb3583f939c6e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 13:26:09 +0100 Subject: [PATCH 16/27] Implemented Treeco's z-only LoD suggestion --- voxygen/src/scene/terrain.rs | 285 ++++++++++++++++-- world/src/civ/mod.rs | 5 +- .../settlement/building/archetype/house.rs | 2 +- 3 files changed, 268 insertions(+), 24 deletions(-) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 2b06688797..5b33dd2cc2 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -326,11 +326,15 @@ impl Terrain { // with worker threads that are meshing chunks. let (send, recv) = channel::unbounded(); - let mut make_models = |s, offset| { - let scaled = [1.0, 0.75, 0.3, 0.2]; + let mut make_models = |s, offset, lod_axes: Vec3| { + let scaled = [1.0, 0.6, 0.4, 0.2]; scaled .iter() - .map(|lod_scale| Vec3::broadcast(*lod_scale)) + .map(|lod_scale| if *lod_scale == 1.0 { + Vec3::broadcast(1.0) + } else { + lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + }) .map(|lod_scale| { renderer .create_model( @@ -358,6 +362,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.window.window-0", Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), ), ), ( @@ -365,6 +370,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.window.window-1", Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), ), ), ( @@ -372,6 +378,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.window.window-2", Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), ), ), ( @@ -379,6 +386,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.window.window-3", Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), ), ), // Cacti @@ -387,6 +395,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.large_cactus", Vec3::new(-13.5, -5.5, 0.0), + Vec3::one(), ), ), ( @@ -394,6 +403,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.tall", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -401,6 +411,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.barrel_cactus", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -408,6 +419,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.cactus_round", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -415,6 +427,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.cactus_short", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -422,6 +435,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.flat_cactus_med", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -429,6 +443,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cacti.flat_cactus_short", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), // Fruit @@ -437,6 +452,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.fruit.apple", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), // Flowers @@ -445,6 +461,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -452,6 +469,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -459,6 +477,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -466,6 +485,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -473,6 +493,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -480,6 +501,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_6", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -487,6 +509,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_blue_7", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -494,6 +517,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_pink_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -501,6 +525,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_pink_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -508,6 +533,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_pink_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -515,6 +541,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_pink_4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -522,6 +549,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_purple_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -529,6 +557,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_red_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -536,6 +565,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_red_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -543,6 +573,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_red_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -550,6 +581,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_white_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -557,6 +589,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_white_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -564,6 +597,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.flower_purple_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -571,6 +605,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.sunflower_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -578,6 +613,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flowers.sunflower_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), // Grass @@ -586,6 +622,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -593,6 +630,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -600,6 +638,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -607,6 +646,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -614,6 +654,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -621,6 +662,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_6", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -628,6 +670,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_long_7", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -635,6 +678,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_med_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -642,6 +686,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_med_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -649,6 +694,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_med_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -656,6 +702,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_med_4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -663,6 +710,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_med_5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -670,6 +718,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_short_1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -677,6 +726,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_short_2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -684,6 +734,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_short_3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -691,6 +742,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_short_4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -698,6 +750,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.grass.grass_short_5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -705,6 +758,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -712,6 +766,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -719,6 +774,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -726,6 +782,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -733,6 +790,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -740,6 +798,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -747,6 +806,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-6", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -754,6 +814,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-7", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -761,6 +822,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-8", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -768,6 +830,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-9", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -775,6 +838,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.mushrooms.mushroom-10", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -782,6 +846,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.lianas.liana-0", Vec3::new(-1.5, -0.5, -88.0), + Vec3::unit_z() * 0.5, ), ), ( @@ -789,6 +854,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.lianas.liana-1", Vec3::new(-1.0, -0.5, -55.0), + Vec3::unit_z() * 0.5, ), ), ( @@ -796,6 +862,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_ore", Vec3::new(-5.0, -5.0, -5.0), + Vec3::one(), ), ), ( @@ -803,6 +870,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_1", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -810,6 +878,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_2", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -817,6 +886,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_3", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -824,6 +894,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_4", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -831,6 +902,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_5", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -838,6 +910,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_6", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -845,6 +918,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_7", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -852,6 +926,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_8", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -859,6 +934,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_9", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -866,6 +942,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.velorite.velorite_10", Vec3::new(-3.0, -5.0, 0.0), + Vec3::one(), ), ), ( @@ -873,6 +950,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.chests.chest", Vec3::new(-7.0, -5.0, -0.0), + Vec3::one(), ), ), ( @@ -880,6 +958,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.chests.chest_gold", Vec3::new(-7.0, -5.0, -0.0), + Vec3::one(), ), ), ( @@ -887,6 +966,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.chests.chest_dark", Vec3::new(-7.0, -5.0, -0.0), + Vec3::one(), ), ), ( @@ -894,6 +974,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.chests.chest_vines", Vec3::new(-7.0, -5.0, -0.0), + Vec3::one(), ), ), //Welwitch @@ -902,6 +983,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.welwitch.1", Vec3::new(-15.0, -17.0, -0.0), + Vec3::unit_z() * 0.7, ), ), //Pumpkins @@ -910,6 +992,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.1", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -917,6 +1000,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.2", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -924,6 +1008,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.3", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -931,6 +1016,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.4", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -938,6 +1024,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.5", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -945,6 +1032,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.6", Vec3::new(-7.0, -6.5, -0.0), + Vec3::one(), ), ), ( @@ -952,6 +1040,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.pumpkin.7", Vec3::new(-7.0, -9.5, -0.0), + Vec3::one(), ), ), //Lingonberries @@ -960,6 +1049,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.lingonberry.1", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -967,6 +1057,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.lingonberry.2", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -974,6 +1065,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.lingonberry.3", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), // Leafy Plants @@ -982,6 +1074,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.1", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -989,6 +1082,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.2", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -996,6 +1090,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.3", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1003,6 +1098,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.4", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1010,6 +1106,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.5", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1017,6 +1114,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.6", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1024,6 +1122,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.7", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1031,6 +1130,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.8", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1038,6 +1138,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.9", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1045,56 +1146,105 @@ impl Terrain { make_models( "voxygen.voxel.sprite.leafy_plant.10", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), // Ferns ( (BlockKind::Fern, 0), - make_models("voxygen.voxel.sprite.ferns.1", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.1", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 1), - make_models("voxygen.voxel.sprite.ferns.2", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.2", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 2), - make_models("voxygen.voxel.sprite.ferns.3", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.3", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 3), - make_models("voxygen.voxel.sprite.ferns.4", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.4", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 4), - make_models("voxygen.voxel.sprite.ferns.5", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.5", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 5), - make_models("voxygen.voxel.sprite.ferns.6", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.6", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 6), - make_models("voxygen.voxel.sprite.ferns.7", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.7", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 7), - make_models("voxygen.voxel.sprite.ferns.8", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.8", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 8), - make_models("voxygen.voxel.sprite.ferns.9", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.9", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 9), - make_models("voxygen.voxel.sprite.ferns.10", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.10", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 10), - make_models("voxygen.voxel.sprite.ferns.11", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.11", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), ( (BlockKind::Fern, 11), - make_models("voxygen.voxel.sprite.ferns.12", Vec3::new(-6.0, -6.0, -0.0)), + make_models( + "voxygen.voxel.sprite.ferns.12", + Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), + ), ), // Dead Bush ( @@ -1102,6 +1252,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.dead_bush.1", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1109,6 +1260,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.dead_bush.2", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1116,6 +1268,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.dead_bush.3", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1123,6 +1276,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.dead_bush.4", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), // Blueberries @@ -1131,6 +1285,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.1", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1138,6 +1293,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.2", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1145,6 +1301,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.3", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1152,6 +1309,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.4", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1159,6 +1317,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.5", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1166,6 +1325,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.6", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1173,6 +1333,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.7", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1180,6 +1341,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.8", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), ( @@ -1187,12 +1349,17 @@ impl Terrain { make_models( "voxygen.voxel.sprite.blueberry.9", Vec3::new(-6.0, -6.0, -0.0), + Vec3::one(), ), ), // Ember ( (BlockKind::Ember, 0), - make_models("voxygen.voxel.sprite.ember.1", Vec3::new(-7.0, -7.0, -2.9)), + make_models( + "voxygen.voxel.sprite.ember.1", + Vec3::new(-7.0, -7.0, -2.9), + Vec3::new(1.0, 1.0, 0.0), + ), ), // Corn ( @@ -1200,6 +1367,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1207,6 +1375,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1214,6 +1383,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1221,6 +1391,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1228,6 +1399,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1235,6 +1407,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.corn.corn-5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), // Yellow Wheat @@ -1243,6 +1416,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1250,6 +1424,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1257,6 +1432,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1264,6 +1440,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1271,6 +1448,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1278,6 +1456,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1285,6 +1464,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-6", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1292,6 +1472,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-7", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1299,6 +1480,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-8", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1306,6 +1488,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_yellow.wheat-9", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), // Green Wheat @@ -1314,6 +1497,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1321,6 +1505,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1328,6 +1513,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1335,6 +1521,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1342,6 +1529,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1349,6 +1537,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1356,6 +1545,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-6", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1363,6 +1553,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-7", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1370,6 +1561,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-8", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1377,6 +1569,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.wheat_green.wheat-9", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), // Cabbage @@ -1385,6 +1578,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cabbage.cabbage-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -1392,6 +1586,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cabbage.cabbage-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), ( @@ -1399,6 +1594,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.cabbage.cabbage-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), // Flax @@ -1407,6 +1603,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-0", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1414,6 +1611,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-1", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1421,6 +1619,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-2", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1428,6 +1627,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-3", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1435,6 +1635,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-4", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), ( @@ -1442,6 +1643,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.flax.flax-5", Vec3::new(-6.0, -6.0, 0.0), + Vec3::unit_z() * 0.7, ), ), // Carrot @@ -1450,6 +1652,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.0", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1457,6 +1660,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.1", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1464,6 +1668,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.2", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1471,6 +1676,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.3", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1478,6 +1684,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.4", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1485,27 +1692,48 @@ impl Terrain { make_models( "voxygen.voxel.sprite.carrot.5", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( (BlockKind::Tomato, 0), - make_models("voxygen.voxel.sprite.tomato.0", Vec3::new(-5.5, -5.5, 0.0)), + make_models( + "voxygen.voxel.sprite.tomato.0", + Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), + ), ), ( (BlockKind::Tomato, 1), - make_models("voxygen.voxel.sprite.tomato.1", Vec3::new(-5.5, -5.5, 0.0)), + make_models( + "voxygen.voxel.sprite.tomato.1", + Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), + ), ), ( (BlockKind::Tomato, 2), - make_models("voxygen.voxel.sprite.tomato.2", Vec3::new(-5.5, -5.5, 0.0)), + make_models( + "voxygen.voxel.sprite.tomato.2", + Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), + ), ), ( (BlockKind::Tomato, 3), - make_models("voxygen.voxel.sprite.tomato.3", Vec3::new(-5.5, -5.5, 0.0)), + make_models( + "voxygen.voxel.sprite.tomato.3", + Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), + ), ), ( (BlockKind::Tomato, 4), - make_models("voxygen.voxel.sprite.tomato.4", Vec3::new(-5.5, -5.5, 0.0)), + make_models( + "voxygen.voxel.sprite.tomato.4", + Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), + ), ), // Radish ( @@ -1513,6 +1741,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.radish.0", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1520,6 +1749,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.radish.1", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1527,6 +1757,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.radish.2", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1534,6 +1765,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.radish.3", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1541,6 +1773,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.radish.4", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), // Turnip @@ -1549,6 +1782,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-0", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1556,6 +1790,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-1", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1563,6 +1798,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-2", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1570,6 +1806,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-3", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1577,6 +1814,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-4", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), ( @@ -1584,6 +1822,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.turnip.turnip-5", Vec3::new(-5.5, -5.5, -0.25), + Vec3::one(), ), ), // Coconut @@ -1592,6 +1831,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.fruit.coconut", Vec3::new(-6.0, -6.0, 0.0), + Vec3::one(), ), ), // Scarecrow @@ -1600,6 +1840,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.misc.scarecrow", Vec3::new(-9.5, -3.0, -0.25), + Vec3::unit_z(), ), ), // Street Light @@ -1608,6 +1849,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.misc.street_lamp", Vec3::new(-4.5, -4.5, 0.0), + Vec3::unit_z(), ), ), // Door @@ -1616,6 +1858,7 @@ impl Terrain { make_models( "voxygen.voxel.sprite.door.door-0", Vec3::new(-5.5, -5.5, 0.0), + Vec3::one(), ), ), ] diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 4cf4479b24..49954a02df 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -140,16 +140,17 @@ impl Civs { e * sz as i32 + sz as i32 / 2 }); + let mut rng = ctx.reseed().rng; let world_site = match &site.kind { SiteKind::Settlement => WorldSite::from(Settlement::generate( wpos, Some(ctx.sim), - &mut ctx.reseed().rng, + &mut rng, )), SiteKind::Dungeon => WorldSite::from(Dungeon::generate( wpos, Some(ctx.sim), - &mut ctx.reseed().rng, + &mut rng, )), }; diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index cc499d61e2..c75e34b2c9 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -207,7 +207,7 @@ impl Archetype for House { let floor = make_block(100, 75, 50); let wall = make_block(200, 180, 150).with_priority(facade_layer); let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b) - .with_priority(facade_layer); + .with_priority(facade_layer - 1); let empty = BlockMask::nothing(); let internal = BlockMask::new(Block::empty(), structural_layer); let end_window = BlockMask::new( From c05f4fe00927aeb9ba8a1c8b5bdb31a0a17ebe57 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 14:04:30 +0100 Subject: [PATCH 17/27] Added configurable sprite view distance, minor bug fixes --- assets/voxygen/shaders/include/globals.glsl | 3 +- assets/voxygen/shaders/sprite-frag.glsl | 3 +- assets/voxygen/shaders/sprite-vert.glsl | 1 + voxygen/src/hud/mod.rs | 4 ++ voxygen/src/hud/settings_window.rs | 11 ++-- voxygen/src/render/pipelines/mod.rs | 4 ++ voxygen/src/scene/mod.rs | 4 ++ voxygen/src/scene/simple.rs | 1 + voxygen/src/scene/terrain.rs | 26 ++++----- voxygen/src/session.rs | 58 +++++++++------------ voxygen/src/settings.rs | 2 + world/src/civ/mod.rs | 16 +++--- 12 files changed, 71 insertions(+), 62 deletions(-) diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index b35fab1228..895492a23a 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -16,6 +16,7 @@ uniform u_globals { // 0 - FirstPerson // 1 - ThirdPerson uint cam_mode; + float sprite_render_distance; }; // Specifies the pattern used in the player dithering @@ -26,4 +27,4 @@ mat4 threshold_matrix = mat4( vec4(16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0) ); float distance_divider = 2; -float shadow_dithering = 0.5; \ No newline at end of file +float shadow_dithering = 0.5; diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 0c08431d52..4b983e5ae7 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -13,7 +13,6 @@ out vec4 tgt_color; #include #include -const float RENDER_DIST = 180.0; const float FADE_DIST = 32.0; void main() { @@ -35,5 +34,5 @@ void main() { vec3 fog_color = get_sky_color(normalize(f_pos - cam_pos.xyz), time_of_day.x, cam_pos.xyz, f_pos, 0.5, true, clouds); vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a); - tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (RENDER_DIST - FADE_DIST)) / FADE_DIST, 0, 1)); + tgt_color = vec4(color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 45b3d60dea..214b66a460 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -32,6 +32,7 @@ void main() { vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz; f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz; + f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0); // Wind waving f_pos += inst_wind_sway * vec3( diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index cf1b4a174a..8f59fef80f 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -210,6 +210,7 @@ pub enum Event { ToggleMouseYInvert(bool), ToggleSmoothPan(bool), AdjustViewDistance(u32), + AdjustSpriteRenderDistance(u32), AdjustMusicVolume(f32), AdjustSfxVolume(f32), ChangeAudioDevice(String), @@ -1801,6 +1802,9 @@ impl Hud { settings_window::Event::AdjustViewDistance(view_distance) => { events.push(Event::AdjustViewDistance(view_distance)); }, + settings_window::Event::AdjustSpriteRenderDistance(view_distance) => { + events.push(Event::AdjustSpriteRenderDistance(view_distance)); + }, settings_window::Event::CrosshairTransp(crosshair_transp) => { events.push(Event::CrosshairTransp(crosshair_transp)); }, diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index fac506bc54..d37a053b7f 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -212,6 +212,7 @@ pub enum Event { ToggleMouseYInvert(bool), ToggleSmoothPan(bool), AdjustViewDistance(u32), + AdjustSpriteRenderDistance(u32), AdjustFOV(u16), AdjustGamma(f32), AdjustWindowSize([u16; 2]), @@ -1617,9 +1618,9 @@ impl<'a> Widget for SettingsWindow<'a> { .set(state.ids.gamma_value, ui); // Sprites VD if let Some(new_val) = ImageSlider::discrete( - self.global_state.settings.graphics.view_distance, - 1, - 65, + self.global_state.settings.graphics.sprite_render_distance, + 50, + 500, self.imgs.slider_indicator, self.imgs.slider, ) @@ -1630,7 +1631,7 @@ impl<'a> Widget for SettingsWindow<'a> { .pad_track((5.0, 5.0)) .set(state.ids.sprite_dist_slider, ui) { - events.push(Event::AdjustViewDistance(new_val)); + events.push(Event::AdjustSpriteRenderDistance(new_val)); } Text::new( &self @@ -1645,7 +1646,7 @@ impl<'a> Widget for SettingsWindow<'a> { Text::new(&format!( "{}", - self.global_state.settings.graphics.view_distance + self.global_state.settings.graphics.sprite_render_distance )) .right_from(state.ids.sprite_dist_slider, 8.0) .font_size(self.fonts.cyri.scale(14)) diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index a4edd0e598..5ca7182521 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -29,6 +29,7 @@ gfx_defines! { select_pos: [i32; 4] = "select_pos", gamma: [f32; 4] = "gamma", cam_mode: u32 = "cam_mode", + sprite_render_distance: f32 = "sprite_render_distance", } constant Light { @@ -58,6 +59,7 @@ impl Globals { select_pos: Option>, gamma: f32, cam_mode: CameraMode, + sprite_render_distance: f32, ) -> Self { Self { view_mat: arr_to_mat(view_mat.into_col_array()), @@ -77,6 +79,7 @@ impl Globals { .into_array(), gamma: [gamma; 4], cam_mode: cam_mode as u32, + sprite_render_distance, } } } @@ -98,6 +101,7 @@ impl Default for Globals { None, 1.0, CameraMode::ThirdPerson, + 250.0, ) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f3b7771e2d..44c55e2617 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -76,6 +76,7 @@ pub struct SceneData<'a> { pub thread_pool: &'a uvth::ThreadPool, pub gamma: f32, pub mouse_smoothing: bool, + pub sprite_render_distance: f32, } impl Scene { @@ -353,6 +354,7 @@ impl Scene { self.select_pos, scene_data.gamma, self.camera.get_mode(), + scene_data.sprite_render_distance as f32 - 20.0, )]) .expect("Failed to update global constants"); @@ -385,6 +387,7 @@ impl Scene { state: &State, player_entity: EcsEntity, tick: u64, + scene_data: &SceneData, ) { // Render terrain and figures. self.terrain.render( @@ -425,6 +428,7 @@ impl Scene { &self.lights, &self.shadows, self.camera.get_focus_pos(), + scene_data.sprite_render_distance, ); renderer.render_post_process( diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 8abf6be9a7..2f53408569 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -183,6 +183,7 @@ impl Scene { None, scene_data.gamma, self.camera.get_mode(), + 250.0, )]) { error!("Renderer failed to update: {:?}", err); } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 5b33dd2cc2..6598fde00b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -330,10 +330,12 @@ impl Terrain { let scaled = [1.0, 0.6, 0.4, 0.2]; scaled .iter() - .map(|lod_scale| if *lod_scale == 1.0 { - Vec3::broadcast(1.0) - } else { - lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + .map(|lod_scale| { + if *lod_scale == 1.0 { + Vec3::broadcast(1.0) + } else { + lod_axes * *lod_scale + lod_axes.map(|e| if e == 0.0 { 1.0 } else { 0.0 }) + } }) .map(|lod_scale| { renderer @@ -2229,6 +2231,7 @@ impl Terrain { lights: &Consts, shadows: &Consts, focus_pos: Vec3, + sprite_render_distance: f32, ) { let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { (e as i32).div_euclid(sz as i32) @@ -2252,22 +2255,21 @@ impl Terrain { // Terrain sprites for (pos, chunk) in chunk_iter.clone() { if chunk.visible { - const SPRITE_RENDER_DISTANCE: f32 = 200.0; - const SPRITE_DETAIL_LOW_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.65; - const SPRITE_DETAIL_MID_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.4; - const SPRITE_DETAIL_HIGH_DISTANCE: f32 = SPRITE_RENDER_DISTANCE * 0.25; + let sprite_detail_low_distance = sprite_render_distance * 0.65; + let sprite_detail_mid_distance = sprite_render_distance * 0.4; + let sprite_detail_high_distance = sprite_render_distance * 0.25; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); let dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center); - if dist_sqrd < SPRITE_RENDER_DISTANCE.powf(2.0) { + if dist_sqrd < sprite_render_distance.powf(2.0) { for (kind, instances) in &chunk.sprite_instances { renderer.render_sprites( - if dist_sqrd < SPRITE_DETAIL_HIGH_DISTANCE.powf(2.0) { + if dist_sqrd < sprite_detail_high_distance.powf(2.0) { &self.sprite_models[&kind][0] - } else if dist_sqrd < SPRITE_DETAIL_MID_DISTANCE.powf(2.0) { + } else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) { &self.sprite_models[&kind][1] - } else if dist_sqrd < SPRITE_DETAIL_LOW_DISTANCE.powf(2.0) { + } else if dist_sqrd < sprite_detail_low_distance.powf(2.0) { &self.sprite_models[&kind][2] } else { &self.sprite_models[&kind][3] diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 25b8f7e1df..9c63cf3895 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -4,7 +4,6 @@ use crate::{ i18n::{i18n_asset_key, VoxygenLocalization}, key_state::KeyState, menu::char_selection::CharSelectionState, - render::Renderer, scene::{camera, Scene, SceneData}, settings::AudioOutput, window::{AnalogGameInput, Event, GameInput}, @@ -111,26 +110,6 @@ impl SessionState { /// Clean up the session (and the client attached to it) after a tick. pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); } - - /// Render the session to the screen. - /// - /// This method should be called once per frame. - pub fn render(&mut self, renderer: &mut Renderer) { - // Clear the screen - renderer.clear(); - - // Render the screen using the global renderer - { - let client = self.client.borrow(); - self.scene - .render(renderer, client.state(), client.entity(), client.get_tick()); - } - // Draw the UI to the screen - self.hud.render(renderer, self.scene.globals()); - - // Finish the frame - renderer.flush(); - } } impl PlayState for SessionState { @@ -589,6 +568,10 @@ impl PlayState for SessionState { global_state.settings.graphics.view_distance = view_distance; global_state.settings.save_to_file_warn(); }, + HudEvent::AdjustSpriteRenderDistance(sprite_render_distance) => { + global_state.settings.graphics.sprite_render_distance = sprite_render_distance; + global_state.settings.save_to_file_warn(); + }, HudEvent::CrosshairTransp(crosshair_transp) => { global_state.settings.gameplay.crosshair_transp = crosshair_transp; global_state.settings.save_to_file_warn(); @@ -720,9 +703,6 @@ impl PlayState for SessionState { } } - // Runs if either in a multiplayer server or the singleplayer server is unpaused - if global_state.singleplayer.is_none() - || !global_state.singleplayer.as_ref().unwrap().is_paused() { let client = self.client.borrow(); let scene_data = SceneData { @@ -734,16 +714,30 @@ impl PlayState for SessionState { thread_pool: client.thread_pool(), gamma: global_state.settings.graphics.gamma, mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, + sprite_render_distance: global_state.settings.graphics.sprite_render_distance as f32, }; - self.scene.maintain( - global_state.window.renderer_mut(), - &mut global_state.audio, - &scene_data, - ); - } - // Render the session. - self.render(global_state.window.renderer_mut()); + // Runs if either in a multiplayer server or the singleplayer server is unpaused + if global_state.singleplayer.is_none() + || !global_state.singleplayer.as_ref().unwrap().is_paused() + { + self.scene.maintain( + global_state.window.renderer_mut(), + &mut global_state.audio, + &scene_data, + ); + } + + let renderer = global_state.window.renderer_mut(); + // Clear the screen + renderer.clear(); + // Render the screen using the global renderer + self.scene.render(renderer, client.state(), client.entity(), client.get_tick(), &scene_data); + // Draw the UI to the screen + self.hud.render(renderer, self.scene.globals()); + // Finish the frame + renderer.flush(); + } // Display the frame on the window. global_state diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 11ac56aa6c..3c4f44c19a 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -548,6 +548,7 @@ impl Default for Log { #[serde(default)] pub struct GraphicsSettings { pub view_distance: u32, + pub sprite_render_distance: u32, pub max_fps: u32, pub fov: u16, pub gamma: f32, @@ -562,6 +563,7 @@ impl Default for GraphicsSettings { fn default() -> Self { Self { view_distance: 10, + sprite_render_distance: 250, max_fps: 60, fov: 50, gamma: 1.0, diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 49954a02df..1d1515159a 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -142,16 +142,12 @@ impl Civs { let mut rng = ctx.reseed().rng; let world_site = match &site.kind { - SiteKind::Settlement => WorldSite::from(Settlement::generate( - wpos, - Some(ctx.sim), - &mut rng, - )), - SiteKind::Dungeon => WorldSite::from(Dungeon::generate( - wpos, - Some(ctx.sim), - &mut rng, - )), + SiteKind::Settlement => { + WorldSite::from(Settlement::generate(wpos, Some(ctx.sim), &mut rng)) + }, + SiteKind::Dungeon => { + WorldSite::from(Dungeon::generate(wpos, Some(ctx.sim), &mut rng)) + }, }; let radius_chunks = From 37301706d4a4c9a0ae12cbb8071aeae2365bd36a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 14:37:08 +0100 Subject: [PATCH 18/27] Reduced size of terrain sprite vertices --- assets/voxygen/shaders/sprite-vert.glsl | 14 ++++++++------ voxygen/src/render/pipelines/sprite.rs | 22 ++++++++++++++++------ voxygen/src/session.rs | 14 +++++++++++--- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 214b66a460..f22018bef3 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -4,9 +4,8 @@ #include in vec3 v_pos; -in vec3 v_norm; -in vec3 v_col; -in float v_ao; +in uint v_col; +in uint v_norm_ao; in vec4 inst_mat0; in vec4 inst_mat1; in vec4 inst_mat2; @@ -41,10 +40,13 @@ void main() { 0.0 ) * pow(abs(v_pos.z) * SCALE, 1.3) * 0.2; - f_norm = (inst_mat * vec4(v_norm, 0)).xyz; + // First 3 normals are negative, next 3 are positive + vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1)); + f_norm = (inst_mat * vec4(normals[(v_norm_ao >> 0) & 0x7u], 0)).xyz; - f_col = srgb_to_linear(v_col) * srgb_to_linear(inst_col); - f_ao = v_ao; + vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0; + f_col = srgb_to_linear(col) * srgb_to_linear(inst_col); + f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0; // Select glowing if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) { diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 74091e3bd5..08d2004a18 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -12,9 +12,12 @@ use vek::*; gfx_defines! { vertex Vertex { pos: [f32; 3] = "v_pos", - norm: [f32; 3] = "v_norm", - col: [f32; 3] = "v_col", - ao: f32 = "v_ao", + // ____BBBBBBBBGGGGGGGGRRRRRRRR + col: u32 = "v_col", + // ...AANNN + // A = AO + // N = Normal + norm_ao: u32 = "v_norm_ao", } vertex Instance { @@ -43,11 +46,18 @@ gfx_defines! { impl Vertex { pub fn new(pos: Vec3, norm: Vec3, col: Rgb, ao: f32) -> Self { + let norm_bits = if norm.x != 0.0 { + if norm.x < 0.0 { 0 } else { 1 } + } else if norm.y != 0.0 { + if norm.y < 0.0 { 2 } else { 3 } + } else { + if norm.z < 0.0 { 4 } else { 5 } + }; + Self { pos: pos.into_array(), - col: col.into_array(), - norm: norm.into_array(), - ao, + col: col.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift).reduce_bitor(), + norm_ao: norm_bits | (((ao * 3.9999) as u32) << 3), } } } diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 9c63cf3895..c0e725a43e 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -569,7 +569,8 @@ impl PlayState for SessionState { global_state.settings.save_to_file_warn(); }, HudEvent::AdjustSpriteRenderDistance(sprite_render_distance) => { - global_state.settings.graphics.sprite_render_distance = sprite_render_distance; + global_state.settings.graphics.sprite_render_distance = + sprite_render_distance; global_state.settings.save_to_file_warn(); }, HudEvent::CrosshairTransp(crosshair_transp) => { @@ -714,7 +715,8 @@ impl PlayState for SessionState { thread_pool: client.thread_pool(), gamma: global_state.settings.graphics.gamma, mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable, - sprite_render_distance: global_state.settings.graphics.sprite_render_distance as f32, + sprite_render_distance: global_state.settings.graphics.sprite_render_distance + as f32, }; // Runs if either in a multiplayer server or the singleplayer server is unpaused @@ -732,7 +734,13 @@ impl PlayState for SessionState { // Clear the screen renderer.clear(); // Render the screen using the global renderer - self.scene.render(renderer, client.state(), client.entity(), client.get_tick(), &scene_data); + self.scene.render( + renderer, + client.state(), + client.entity(), + client.get_tick(), + &scene_data, + ); // Draw the UI to the screen self.hud.render(renderer, self.scene.globals()); // Finish the frame From 7208b37dc5151f34922f13a27b99730d182d93af Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 15:07:58 +0100 Subject: [PATCH 19/27] Squashed figure vertices for better performance --- assets/voxygen/shaders/figure-vert.glsl | 24 ++++++++++++------- voxygen/src/render/pipelines/figure.rs | 32 ++++++++++++++++--------- voxygen/src/render/pipelines/sprite.rs | 4 +++- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index b9fa68bf15..bc22f0c68c 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -2,11 +2,10 @@ #include -in vec3 v_pos; +in uint v_pos_norm; in vec3 v_norm; -in vec3 v_col; -in float v_ao; -in uint v_bone_idx; +in uint v_col; +in uint v_ao_bone; layout (std140) uniform u_locals { @@ -33,20 +32,27 @@ flat out vec3 f_norm; void main() { // Pre-calculate bone matrix - mat4 combined_mat = model_mat * bones[v_bone_idx].bone_mat; + uint bone_idx = (v_ao_bone >> 2) & 0x3Fu; + mat4 combined_mat = model_mat * bones[bone_idx].bone_mat; + + vec3 pos = vec3((uvec3(v_pos_norm) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) - 128.0; f_pos = ( combined_mat * - vec4(v_pos, 1)).xyz; + vec4(pos, 1)).xyz; - f_col = v_col; + f_col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0; - f_ao = v_ao; + f_ao = float(v_ao_bone & 0x3u) / 4.0; + + // First 3 normals are negative, next 3 are positive + vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1)); + vec3 norm = normals[(v_pos_norm >> 24) & 0x7u]; // Calculate normal here rather than for each pixel in the fragment shader f_norm = normalize(( combined_mat * - vec4(v_norm, 0.0) + vec4(norm, 0.0) ).xyz); gl_Position = all_mat * vec4(f_pos, 1); diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 2fa38cbc1d..d87edef5fb 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -11,11 +11,12 @@ use vek::*; gfx_defines! { vertex Vertex { - pos: [f32; 3] = "v_pos", - norm: [f32; 3] = "v_norm", - col: [f32; 3] = "v_col", - ao: f32 = "v_ao", - bone_idx: u8 = "v_bone_idx", + pos_norm: u32 = "v_pos_norm", + col: u32 = "v_col", + // BBBBBBAA + // B = Bone + // A = AO + ao_bone: u8 = "v_ao_bone", } constant Locals { @@ -46,17 +47,26 @@ gfx_defines! { impl Vertex { pub fn new(pos: Vec3, norm: Vec3, col: Rgb, ao: f32, bone_idx: u8) -> Self { + let norm_bits = if norm.x != 0.0 { + if norm.x < 0.0 { 0 } else { 1 } + } else if norm.y != 0.0 { + if norm.y < 0.0 { 2 } else { 3 } + } else { + if norm.z < 0.0 { 4 } else { 5 } + }; Self { - pos: pos.into_array(), - col: col.into_array(), - norm: norm.into_array(), - ao, - bone_idx, + pos_norm: pos + .map2(Vec3::new(0, 8, 16), |e, shift| ((e + 128.0) as u32) << shift) + .reduce_bitor() | (norm_bits << 24), + col: col + .map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift) + .reduce_bitor(), + ao_bone: (bone_idx << 2) | ((ao * 3.9999) as u8), } } pub fn with_bone_idx(mut self, bone_idx: u8) -> Self { - self.bone_idx = bone_idx; + self.ao_bone = (self.ao_bone & 0b11) | (bone_idx << 2); self } } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 08d2004a18..f5ef6e8d2e 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -56,7 +56,9 @@ impl Vertex { Self { pos: pos.into_array(), - col: col.map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift).reduce_bitor(), + col: col + .map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift) + .reduce_bitor(), norm_ao: norm_bits | (((ao * 3.9999) as u32) << 3), } } From 8e95444d85320e3ee8befa7da0bbf9e6bd0ae967 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 15:38:17 +0100 Subject: [PATCH 20/27] Made GPU bone updates more conservative for moar fps --- assets/voxygen/shaders/figure-vert.glsl | 1 + voxygen/src/anim/biped_large/mod.rs | 2 ++ voxygen/src/anim/bird_medium/mod.rs | 2 ++ voxygen/src/anim/bird_small/mod.rs | 2 ++ voxygen/src/anim/character/mod.rs | 2 ++ voxygen/src/anim/critter/mod.rs | 2 ++ voxygen/src/anim/dragon/mod.rs | 2 ++ voxygen/src/anim/fish_medium/mod.rs | 2 ++ voxygen/src/anim/fish_small/mod.rs | 2 ++ voxygen/src/anim/fixture/mod.rs | 4 ++- voxygen/src/anim/mod.rs | 2 ++ voxygen/src/anim/object/mod.rs | 32 +++++++++++++----------- voxygen/src/anim/quadruped_medium/mod.rs | 2 ++ voxygen/src/anim/quadruped_small/mod.rs | 2 ++ voxygen/src/render/pipelines/figure.rs | 7 ++++-- voxygen/src/scene/figure/mod.rs | 2 +- 16 files changed, 49 insertions(+), 19 deletions(-) diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index bc22f0c68c..b1ec6a4b41 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -22,6 +22,7 @@ struct BoneData { layout (std140) uniform u_bones { + // Warning: might not actually be 16 elements long. Don't index out of bounds! BoneData bones[16]; }; diff --git a/voxygen/src/anim/biped_large/mod.rs b/voxygen/src/anim/biped_large/mod.rs index ba73161fb7..34768b1a66 100644 --- a/voxygen/src/anim/biped_large/mod.rs +++ b/voxygen/src/anim/biped_large/mod.rs @@ -47,6 +47,8 @@ impl BipedLargeSkeleton { impl Skeleton for BipedLargeSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 11 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let upper_torso_mat = self.upper_torso.compute_base_matrix(); let shoulder_l_mat = self.shoulder_l.compute_base_matrix(); diff --git a/voxygen/src/anim/bird_medium/mod.rs b/voxygen/src/anim/bird_medium/mod.rs index 64e2d400e3..2e3d3350c9 100644 --- a/voxygen/src/anim/bird_medium/mod.rs +++ b/voxygen/src/anim/bird_medium/mod.rs @@ -27,6 +27,8 @@ impl BirdMediumSkeleton { impl Skeleton for BirdMediumSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 7 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let torso_mat = self.torso.compute_base_matrix(); diff --git a/voxygen/src/anim/bird_small/mod.rs b/voxygen/src/anim/bird_small/mod.rs index 610b63122a..de36727d8d 100644 --- a/voxygen/src/anim/bird_small/mod.rs +++ b/voxygen/src/anim/bird_small/mod.rs @@ -31,6 +31,8 @@ impl BirdSmallSkeleton { impl Skeleton for BirdSmallSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 4 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let torso_mat = self.torso.compute_base_matrix(); diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 9f50a3bd06..db01ba11ad 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -62,6 +62,8 @@ impl CharacterSkeleton { impl Skeleton for CharacterSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 15 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let chest_mat = self.chest.compute_base_matrix(); let torso_mat = self.torso.compute_base_matrix(); diff --git a/voxygen/src/anim/critter/mod.rs b/voxygen/src/anim/critter/mod.rs index 9677461239..bce32cf380 100644 --- a/voxygen/src/anim/critter/mod.rs +++ b/voxygen/src/anim/critter/mod.rs @@ -32,6 +32,8 @@ impl CritterSkeleton { impl Skeleton for CritterSkeleton { type Attr = CritterAttr; + fn bone_count(&self) -> usize { 5 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { [ FigureBoneData::new(self.head.compute_base_matrix()), diff --git a/voxygen/src/anim/dragon/mod.rs b/voxygen/src/anim/dragon/mod.rs index c3bfec7e61..86bd013b9b 100644 --- a/voxygen/src/anim/dragon/mod.rs +++ b/voxygen/src/anim/dragon/mod.rs @@ -49,6 +49,8 @@ impl DragonSkeleton { impl Skeleton for DragonSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 13 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let chest_front_mat = self.chest_front.compute_base_matrix(); let wing_in_l_mat = self.wing_in_l.compute_base_matrix(); diff --git a/voxygen/src/anim/fish_medium/mod.rs b/voxygen/src/anim/fish_medium/mod.rs index b085ed7220..f7f8519a2a 100644 --- a/voxygen/src/anim/fish_medium/mod.rs +++ b/voxygen/src/anim/fish_medium/mod.rs @@ -35,6 +35,8 @@ impl FishMediumSkeleton { impl Skeleton for FishMediumSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 6 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let torso_mat = self.torso.compute_base_matrix(); let rear_mat = self.rear.compute_base_matrix(); diff --git a/voxygen/src/anim/fish_small/mod.rs b/voxygen/src/anim/fish_small/mod.rs index ed26ef0247..1b3618b892 100644 --- a/voxygen/src/anim/fish_small/mod.rs +++ b/voxygen/src/anim/fish_small/mod.rs @@ -27,6 +27,8 @@ impl FishSmallSkeleton { impl Skeleton for FishSmallSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 2 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let torso_mat = self.torso.compute_base_matrix(); diff --git a/voxygen/src/anim/fixture/mod.rs b/voxygen/src/anim/fixture/mod.rs index 92a68d0125..b3426286df 100644 --- a/voxygen/src/anim/fixture/mod.rs +++ b/voxygen/src/anim/fixture/mod.rs @@ -13,9 +13,11 @@ impl FixtureSkeleton { impl Skeleton for FixtureSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 1 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { [ - FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), // <-- This is actually a bone! FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()), diff --git a/voxygen/src/anim/mod.rs b/voxygen/src/anim/mod.rs index de57de2c81..1e556aac9f 100644 --- a/voxygen/src/anim/mod.rs +++ b/voxygen/src/anim/mod.rs @@ -52,6 +52,8 @@ impl Bone { pub trait Skeleton: Send + Sync + 'static { type Attr; + fn bone_count(&self) -> usize { 16 } + fn compute_matrices(&self) -> [FigureBoneData; 16]; /// Change the current skeleton to be more like `target`. diff --git a/voxygen/src/anim/object/mod.rs b/voxygen/src/anim/object/mod.rs index d6f3ac510e..1b552d0485 100644 --- a/voxygen/src/anim/object/mod.rs +++ b/voxygen/src/anim/object/mod.rs @@ -15,24 +15,26 @@ const SCALE: f32 = 1.0 / 11.0; impl Skeleton for ObjectSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 1 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { [ FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), - FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), + FigureBoneData::new(vek::Mat4::identity()), ] } diff --git a/voxygen/src/anim/quadruped_medium/mod.rs b/voxygen/src/anim/quadruped_medium/mod.rs index 57f36c9c1f..a23e8f1793 100644 --- a/voxygen/src/anim/quadruped_medium/mod.rs +++ b/voxygen/src/anim/quadruped_medium/mod.rs @@ -31,6 +31,8 @@ impl QuadrupedMediumSkeleton { impl Skeleton for QuadrupedMediumSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 11 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { let ears_mat = self.ears.compute_base_matrix(); let head_upper_mat = self.head_upper.compute_base_matrix(); diff --git a/voxygen/src/anim/quadruped_small/mod.rs b/voxygen/src/anim/quadruped_small/mod.rs index fb4c559fbf..b043d01751 100644 --- a/voxygen/src/anim/quadruped_small/mod.rs +++ b/voxygen/src/anim/quadruped_small/mod.rs @@ -26,6 +26,8 @@ impl QuadrupedSmallSkeleton { impl Skeleton for QuadrupedSmallSkeleton { type Attr = SkeletonAttr; + fn bone_count(&self) -> usize { 6 } + fn compute_matrices(&self) -> [FigureBoneData; 16] { [ FigureBoneData::new(self.head.compute_base_matrix()), diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index d87edef5fb..dbd8e5161c 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -56,8 +56,11 @@ impl Vertex { }; Self { pos_norm: pos - .map2(Vec3::new(0, 8, 16), |e, shift| ((e + 128.0) as u32) << shift) - .reduce_bitor() | (norm_bits << 24), + .map2(Vec3::new(0, 8, 16), |e, shift| { + ((e + 128.0) as u32) << shift + }) + .reduce_bitor() + | (norm_bits << 24), col: col .map2(Rgb::new(0, 8, 16), |e, shift| ((e * 255.0) as u32) << shift) .reduce_bitor(), diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 497d8077fe..7da07e4d9f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1859,7 +1859,7 @@ impl FigureState { renderer.update_consts(&mut self.locals, &[locals]).unwrap(); renderer - .update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()) + .update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()[0..self.skeleton.bone_count()]) .unwrap(); } From f34175a5a85b7c33557ca21963a854cc9339e59b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 15:48:46 +0100 Subject: [PATCH 21/27] Reduced scaling size inflation --- common/src/volumes/scaled.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index d4b8cf3f9c..29cd1baf29 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -15,7 +15,7 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { #[inline(always)] fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32); - let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32); + let search_size = (Vec3::one() / self.scale).map(|e: f32| e.round() as i32); let range_iter = |x| { std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })) .take(x as usize * 2) From 93105105e0e2218669020ffab4d3b86140de34a0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 15:49:06 +0100 Subject: [PATCH 22/27] Added extra LoD level to terrain sprites --- voxygen/src/scene/figure/mod.rs | 5 ++++- voxygen/src/scene/terrain.rs | 17 ++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 7da07e4d9f..fbe62e0069 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1859,7 +1859,10 @@ impl FigureState { renderer.update_consts(&mut self.locals, &[locals]).unwrap(); renderer - .update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()[0..self.skeleton.bone_count()]) + .update_consts( + &mut self.bone_consts, + &self.skeleton.compute_matrices()[0..self.skeleton.bone_count()], + ) .unwrap(); } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 6598fde00b..9486b788f4 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -327,7 +327,7 @@ impl Terrain { let (send, recv) = channel::unbounded(); let mut make_models = |s, offset, lod_axes: Vec3| { - let scaled = [1.0, 0.6, 0.4, 0.2]; + let scaled = [1.0, 0.8, 0.6, 0.4, 0.2]; scaled .iter() .map(|lod_scale| { @@ -2255,9 +2255,10 @@ impl Terrain { // Terrain sprites for (pos, chunk) in chunk_iter.clone() { if chunk.visible { - let sprite_detail_low_distance = sprite_render_distance * 0.65; - let sprite_detail_mid_distance = sprite_render_distance * 0.4; - let sprite_detail_high_distance = sprite_render_distance * 0.25; + let sprite_detail_low_distance = sprite_render_distance * 0.75; + let sprite_detail_mid_distance = sprite_render_distance * 0.5; + let sprite_detail_hid_distance = sprite_render_distance * 0.35; + let sprite_detail_high_distance = sprite_render_distance * 0.15; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); @@ -2267,12 +2268,14 @@ impl Terrain { renderer.render_sprites( if dist_sqrd < sprite_detail_high_distance.powf(2.0) { &self.sprite_models[&kind][0] - } else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) { + } else if dist_sqrd < sprite_detail_hid_distance.powf(2.0) { &self.sprite_models[&kind][1] - } else if dist_sqrd < sprite_detail_low_distance.powf(2.0) { + } else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) { &self.sprite_models[&kind][2] - } else { + } else if dist_sqrd < sprite_detail_low_distance.powf(2.0) { &self.sprite_models[&kind][3] + } else { + &self.sprite_models[&kind][4] }, globals, &instances, From 8871cb2d29f8bcf8efe41436dc09080e140f3c77 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 16:06:52 +0100 Subject: [PATCH 23/27] Better scaled rounding --- common/src/volumes/scaled.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index 29cd1baf29..242ed21a8a 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -14,16 +14,20 @@ impl<'a, V: BaseVol> BaseVol for Scaled<'a, V> { impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { #[inline(always)] fn get(&self, pos: Vec3) -> Result<&Self::Vox, Self::Error> { - let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32); - let search_size = (Vec3::one() / self.scale).map(|e: f32| e.round() as i32); - let range_iter = |x| { - std::iter::successors(Some(0), |x| Some(if *x < 0 { -*x } else { -(*x + 1) })) - .take(x as usize * 2) + let ideal_pos = pos.map2(self.scale, |e, scale| e as f32 / scale); + let pos = ideal_pos.map(|e| e.trunc() as i32); + + let ideal_search_size = Vec3::::one() / self.scale; + let range_iter = |i: usize| { + std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) })) + .take_while(move |p| ( + (ideal_pos[i] - ideal_search_size[i] / 2.0).round() as i32..(ideal_pos[i] + ideal_search_size[i] / 2.0).round() as i32 + ).contains(&(pos[i] + *p))) }; - range_iter(search_size.x / 2) + range_iter(0) .map(|i| { - range_iter(search_size.y / 2) - .map(move |j| range_iter(search_size.z / 2).map(move |k| Vec3::new(i, j, k))) + range_iter(1) + .map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k))) }) .flatten() .flatten() From 90de77955911985f37435af5078cab65e5e30644 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 19:42:42 +0100 Subject: [PATCH 24/27] Better LoD variable names --- common/src/volumes/scaled.rs | 13 ++++++------- voxygen/src/scene/figure/mod.rs | 8 ++++---- voxygen/src/scene/terrain.rs | 16 ++++++++-------- .../site/settlement/building/archetype/house.rs | 2 +- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/common/src/volumes/scaled.rs b/common/src/volumes/scaled.rs index 242ed21a8a..44caa0bf51 100644 --- a/common/src/volumes/scaled.rs +++ b/common/src/volumes/scaled.rs @@ -20,15 +20,14 @@ impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> { let ideal_search_size = Vec3::::one() / self.scale; let range_iter = |i: usize| { std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) })) - .take_while(move |p| ( - (ideal_pos[i] - ideal_search_size[i] / 2.0).round() as i32..(ideal_pos[i] + ideal_search_size[i] / 2.0).round() as i32 - ).contains(&(pos[i] + *p))) + .take_while(move |p| { + ((ideal_pos[i] - ideal_search_size[i] / 2.0).round() as i32 + ..(ideal_pos[i] + ideal_search_size[i] / 2.0).round() as i32) + .contains(&(pos[i] + *p)) + }) }; range_iter(0) - .map(|i| { - range_iter(1) - .map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k))) - }) + .map(|i| range_iter(1).map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k)))) .flatten() .flatten() .map(|offs| self.inner.get(pos + offs)) diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index fbe62e0069..5bee0eb0bb 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1714,14 +1714,14 @@ impl FigureMgr { ) }), } { - const FIGURE_LOD_LOW_DIST: f32 = 150.0; - const FIGURE_LOD_MID_DIST: f32 = 70.0; + const FIGURE_LOW_LOD_DIST: f32 = 150.0; + const FIGURE_MID_LOD_DIST: f32 = 85.0; let model = if pos.distance_squared(camera.get_focus_pos()) - > FIGURE_LOD_LOW_DIST.powf(2.0) + > FIGURE_LOW_LOD_DIST.powf(2.0) { &model[2] - } else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_MID_DIST.powf(2.0) { + } else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_MID_LOD_DIST.powf(2.0) { &model[1] } else { &model[0] diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 9486b788f4..9370c0f7a8 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -2255,10 +2255,10 @@ impl Terrain { // Terrain sprites for (pos, chunk) in chunk_iter.clone() { if chunk.visible { - let sprite_detail_low_distance = sprite_render_distance * 0.75; - let sprite_detail_mid_distance = sprite_render_distance * 0.5; - let sprite_detail_hid_distance = sprite_render_distance * 0.35; - let sprite_detail_high_distance = sprite_render_distance * 0.15; + let sprite_low_detail_distance = sprite_render_distance * 0.75; + let sprite_mid_detail_distance = sprite_render_distance * 0.5; + let sprite_hid_detail_distance = sprite_render_distance * 0.35; + let sprite_high_detail_distance = sprite_render_distance * 0.15; let chunk_center = pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32); @@ -2266,13 +2266,13 @@ impl Terrain { if dist_sqrd < sprite_render_distance.powf(2.0) { for (kind, instances) in &chunk.sprite_instances { renderer.render_sprites( - if dist_sqrd < sprite_detail_high_distance.powf(2.0) { + if dist_sqrd < sprite_high_detail_distance.powf(2.0) { &self.sprite_models[&kind][0] - } else if dist_sqrd < sprite_detail_hid_distance.powf(2.0) { + } else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) { &self.sprite_models[&kind][1] - } else if dist_sqrd < sprite_detail_mid_distance.powf(2.0) { + } else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) { &self.sprite_models[&kind][2] - } else if dist_sqrd < sprite_detail_low_distance.powf(2.0) { + } else if dist_sqrd < sprite_low_detail_distance.powf(2.0) { &self.sprite_models[&kind][3] } else { &self.sprite_models[&kind][4] diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index c75e34b2c9..1ef6416d09 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -116,7 +116,7 @@ impl Archetype for House { storey_fill: StoreyFill::All, mansard: 0, pillar: match rng.gen_range(0, 3) { - 0 => Pillar::Chimney(9 + locus + rng.gen_range(0, 4)), + 0 => Pillar::Chimney(10 + locus + rng.gen_range(0, 4)), 1 => Pillar::Tower(15 + locus + rng.gen_range(0, 4)), _ => Pillar::None, }, From a1983712d32d938448c7d182deba1b8534accec4 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 20:12:59 +0100 Subject: [PATCH 25/27] Prevented windows spawning inside houses --- world/src/site/settlement/building/archetype/house.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 1ef6416d09..ebe671f544 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -199,7 +199,8 @@ impl Archetype for House { let facade_layer = 3; let structural_layer = facade_layer + 1; - let foundation_layer = structural_layer + 1; + let internal_layer = structural_layer + 1; + let foundation_layer = internal_layer + 1; let floor_layer = foundation_layer + 1; let foundation = make_block(100, 100, 100).with_priority(foundation_layer); @@ -209,7 +210,7 @@ impl Archetype for House { let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b) .with_priority(facade_layer - 1); let empty = BlockMask::nothing(); - let internal = BlockMask::new(Block::empty(), structural_layer); + let internal = BlockMask::new(Block::empty(), internal_layer); let end_window = BlockMask::new( Block::new(BlockKind::Window1, make_meta(ori.flip())), structural_layer, From d2ab29b8bd107b0d8771c7b789fd074567997cd9 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 21:28:41 +0100 Subject: [PATCH 26/27] Clean up reexport --- common/src/figure/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/src/figure/mod.rs b/common/src/figure/mod.rs index 12b5e05d32..4fb39425cd 100644 --- a/common/src/figure/mod.rs +++ b/common/src/figure/mod.rs @@ -2,7 +2,9 @@ pub mod cell; pub mod mat_cell; pub use mat_cell::Material; +// Reexport pub use self::{cell::Cell, mat_cell::MatCell}; + use crate::{ vol::{IntoFullPosIterator, IntoFullVolIterator, ReadVol, SizedVol, Vox, WriteVol}, volumes::dyna::Dyna, From 237da2134d3f936f597bdcf72c8a65496eb0cc78 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 25 Apr 2020 21:37:45 +0100 Subject: [PATCH 27/27] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 075a366cc9..31e03ccaf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Made players spawn in towns - Added non-uniform block heights - Added `/sudo` command +- Added a Level of Detail (LoD) system for terrain sprites and entities ### Changed