diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 2ff84a99ce..62afb6beae 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -738,7 +738,7 @@ impl ServerChatCommand { None, ), ServerChatCommand::MakeVolume => { - cmd(vec![], "Create a volume (experimental)", Some(Admin)) + cmd(vec![Integer("size", 15, Optional)], "Create a volume (experimental)", Some(Admin)) }, ServerChatCommand::Location => { cmd(vec![Any("name", Required)], "Teleport to a location", None) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 5dc7b0f0a8..3f2a0f20b5 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1690,7 +1690,7 @@ fn handle_make_volume( server: &mut Server, client: EcsEntity, target: EcsEntity, - _args: Vec, + args: Vec, _action: &ServerChatCommand, ) -> CmdResult<()> { use comp::body::ship::figuredata::VoxelCollider; @@ -1698,7 +1698,11 @@ fn handle_make_volume( //let () = parse_args!(args); let pos = position(server, target, "target")?; let ship = comp::ship::Body::Volume; - let sz = Vec3::new(15, 15, 15); + let sz = parse_cmd_args!(args, u32).unwrap_or(15); + if sz < 1 || sz > 127 { + return Err(format!("Size has to be between 1 and 127.")); + }; + let sz = Vec3::broadcast(sz); let collider = { let terrain = server.state().terrain(); comp::Collider::Volume(Arc::new(VoxelCollider::from_fn(sz, |rpos| { @@ -1711,12 +1715,9 @@ fn handle_make_volume( }; server .state - .create_ship( - comp::Pos(pos.0 + Vec3::unit_z() * 50.0), - comp::Ori::default(), - ship, - move |_| collider, - ) + .create_ship(comp::Pos(pos.0 + Vec3::unit_z() * (50.0 + sz.z as f32 / 2.0)), comp::Ori::default(), ship, move |_| { + collider + }) .build(); server.notify_client( diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 48841e4a29..5babe05dfc 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -38,7 +38,7 @@ use common::{ comp::{ inventory::slot::EquipSlot, item::{tool::AbilityContext, Hands, ItemKind, ToolKind}, - ship, Body, CharacterActivity, CharacterState, Collider, Controller, Health, Inventory, + ship::{self, figuredata::VOXEL_COLLIDER_MANIFEST}, Body, CharacterActivity, CharacterState, Collider, Controller, Health, Inventory, Item, ItemKey, Last, LightAnimation, LightEmitter, Ori, PhysicsState, PoiseState, Pos, Scale, SkillSet, Stance, Vel, }, @@ -6329,33 +6329,49 @@ impl FigureMgr { let sprite_hid_detail_distance = sprite_render_distance * 0.35; let sprite_high_detail_distance = sprite_render_distance * 0.15; - for (entity, pos, body, _, collider) in ( + let voxel_colliders_manifest = VOXEL_COLLIDER_MANIFEST.read(); + + for (entity, pos, ori, body, _, collider) in ( &ecs.entities(), &ecs.read_storage::(), + &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), ecs.read_storage::().maybe(), ) .join() // Don't render dead entities - .filter(|(_, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) + .filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) { if let Some((data, sprite_instances)) = self.get_sprite_instances(entity, body, collider) { - let dist_sqrd = cam_pos.distance_squared(pos.0); - let radius = collider.map_or(f32::INFINITY, |collider| collider.bounding_radius()); + let dist = collider.and_then(|collider| { + let vol = collider.get_vol(&voxel_colliders_manifest)?; + + let mat = Mat4::from(ori.to_quat()).translated_3d(pos.0) + * Mat4::translation_3d(vol.translation); - let dist_sqrd = dist_sqrd - radius * radius; + let p = mat.inverted().mul_point(cam_pos); + let aabb = Aabb { + min: Vec3::zero(), + max: vol.volume().sz.as_(), + }; + Some(if aabb.contains_point(p) { + 0.0 + } else { + aabb.distance_to_point(p) + }) + }).unwrap_or_else(|| pos.0.distance(cam_pos)); - if dist_sqrd < sprite_render_distance.powi(2) { - let lod_level = if dist_sqrd < sprite_high_detail_distance.powi(2) { + if dist < sprite_render_distance { + let lod_level = if dist < sprite_high_detail_distance { 0 - } else if dist_sqrd < sprite_hid_detail_distance.powi(2) { + } else if dist < sprite_hid_detail_distance { 1 - } else if dist_sqrd < sprite_mid_detail_distance.powi(2) { + } else if dist < sprite_mid_detail_distance { 2 - } else if dist_sqrd < sprite_low_detail_distance.powi(2) { + } else if dist < sprite_low_detail_distance { 3 } else { 4 diff --git a/voxygen/src/scene/figure/volume.rs b/voxygen/src/scene/figure/volume.rs index 1eeb9f7e59..380bb2e972 100644 --- a/voxygen/src/scene/figure/volume.rs +++ b/voxygen/src/scene/figure/volume.rs @@ -3,7 +3,7 @@ use super::{ load::{BodySpec, ShipBoneMeshes}, EcsEntity, }; -use common::{assets, comp::ship::figuredata::VoxelCollider}; +use common::{assets, comp::ship::{figuredata::VoxelCollider, AIRSHIP_SCALE}}; use std::{convert::TryFrom, sync::Arc}; #[derive(Copy, Clone, PartialEq, Eq, Hash)] @@ -41,9 +41,7 @@ impl anim::Skeleton for VolumeKey { buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT], _: Self::Body, ) -> anim::Offsets { - let scale_mat = anim::vek::Mat4::scaling_3d(1.0 / 11.0); - - let bone = base_mat * scale_mat; + let bone = base_mat; *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ anim::make_bone(bone),