diff --git a/assets/server/manifests/ship_manifest.ron b/assets/server/manifests/ship_manifest.ron index e8e96539ca..6b361aa535 100644 --- a/assets/server/manifests/ship_manifest.ron +++ b/assets/server/manifests/ship_manifest.ron @@ -1,18 +1,23 @@ ({ DefaultAirship: ( bone0: ( - //offset: (-20.0, -35.0, 1.0), //offset: (3.0, 7.0, 1.0), - offset: (0.25, 0.25, 0.25), - central: ("object.Human_Airship"), + //offset: (-20.75, -34.75, 1.25), + //offset: (0.0, 0.0, 0.0), + offset: (-20.0, -35.0, 1.0), + //phys_offset: (0.25, 0.25, 0.25), + phys_offset: (0.0, 0.0, 0.0), + central: ("Human_Airship"), ), bone1: ( offset: (0.0, 40.0, -8.0), - central: ("object.propeller-l"), + phys_offset: (0.0, 0.0, 0.0), + central: ("propeller-l"), ), bone2: ( offset: (0.0, 0.0, -4.0), - central: ("object.propeller-r"), + phys_offset: (0.0, 0.0, 0.0), + central: ("propeller-r"), ), ), }) diff --git a/common/src/comp/body/ship.rs b/common/src/comp/body/ship.rs index f607cf2ae6..3cab7a0ecb 100644 --- a/common/src/comp/body/ship.rs +++ b/common/src/comp/body/ship.rs @@ -17,7 +17,7 @@ impl From for super::Body { impl Body { pub fn manifest_entry(&self) -> &'static str { match self { - Body::DefaultAirship => "object.Human_Airship", + Body::DefaultAirship => "Human_Airship", } } } @@ -38,6 +38,7 @@ pub mod figuredata { use hashbrown::HashMap; use lazy_static::lazy_static; use serde::Deserialize; + use vek::Vec3; #[derive(Deserialize)] pub struct VoxSimple(pub String); @@ -55,6 +56,7 @@ pub mod figuredata { #[derive(Deserialize)] pub struct ShipCentralSubSpec { pub offset: [f32; 3], + pub phys_offset: [f32; 3], pub central: VoxSimple, } @@ -62,7 +64,13 @@ pub mod figuredata { #[derive(Clone)] pub struct ShipSpec { pub central: AssetHandle>, - pub voxes: HashMap>, + pub colliders: HashMap, + } + + #[derive(Clone)] + pub struct VoxelCollider { + pub dyna: Dyna, + pub translation: Vec3, } impl assets::Compound for ShipSpec { @@ -71,26 +79,31 @@ pub mod figuredata { _: &str, ) -> Result { let manifest: AssetHandle> = AssetExt::load("server.manifests.ship_manifest")?; - let mut voxes = HashMap::new(); + let mut colliders = HashMap::new(); for (_, spec) in (manifest.read().0).0.iter() { for bone in [&spec.bone0, &spec.bone1, &spec.bone2].iter() { // TODO: avoid the requirement for symlinks in "voxygen.voxel.object.", and load // the models from "server.voxel." instead let vox = - cache.load::(&["voxygen.voxel.", &bone.central.0].concat())?; + cache.load::(&["server.voxel.", &bone.central.0].concat())?; let dyna = Dyna::::from_vox(&vox.read().0, false); - voxes.insert(bone.central.0.clone(), dyna.map_into(|cell| { + let dyna = dyna.map_into(|cell| { if let Some(rgb) = cell.get_color() { Block::new(BlockKind::Misc, rgb) } else { Block::air(SpriteKind::Empty) } - })); + }); + let collider = VoxelCollider { + dyna, + translation: Vec3::from(bone.offset) + Vec3::from(bone.phys_offset), + }; + colliders.insert(bone.central.0.clone(), collider); } } Ok(ShipSpec { central: manifest, - voxes, + colliders, }) } } @@ -99,6 +112,6 @@ pub mod figuredata { // TODO: load this from the ECS as a resource, and maybe make it more general than ships // (although figuring out how to keep the figure bones in sync with the terrain offsets seems // like a hard problem if they're not the same manifest) - pub static ref VOXEL_COLLIDER_MANIFEST: ShipSpec = AssetExt::load_expect_cloned("server.manifests.ship_manifest"); + pub static ref VOXEL_COLLIDER_MANIFEST: AssetHandle = AssetExt::load_expect("server.manifests.ship_manifest"); } } diff --git a/common/src/comp/ori.rs b/common/src/comp/ori.rs index 351db07066..de9e969bcc 100644 --- a/common/src/comp/ori.rs +++ b/common/src/comp/ori.rs @@ -9,7 +9,7 @@ use vek::{Quaternion, Vec2, Vec3}; #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(into = "SerdeOri")] #[serde(from = "SerdeOri")] -pub struct Ori(Quaternion); +pub struct Ori(pub Quaternion); impl Default for Ori { /// Returns the default orientation (no rotation; default Dir) diff --git a/common/sys/src/phys.rs b/common/sys/src/phys.rs index ebe19689ad..91cfd540df 100644 --- a/common/sys/src/phys.rs +++ b/common/sys/src/phys.rs @@ -364,7 +364,7 @@ impl<'a> PhysicsSystemData<'a> { } = self; // Apply movement inputs span!(guard, "Apply movement and terrain collision"); - let (positions, previous_phys_cache) = (&psdw.positions, &psdw.previous_phys_cache); + let (positions, previous_phys_cache, orientations) = (&psdw.positions, &psdw.previous_phys_cache, &psdw.orientations); let (pos_writes, land_on_grounds) = ( &psdr.entities, psdr.scales.maybe(), @@ -372,7 +372,7 @@ impl<'a> PhysicsSystemData<'a> { &psdr.colliders, positions, &mut psdw.velocities, - &psdw.orientations, + orientations, &mut psdw.physics_states, previous_phys_cache, !&psdr.mountings, @@ -548,6 +548,7 @@ impl<'a> PhysicsSystemData<'a> { previous_cache_other, mass_other, collider_other, + ori_other, _, _, _, @@ -560,6 +561,7 @@ impl<'a> PhysicsSystemData<'a> { previous_phys_cache, psdr.masses.maybe(), &psdr.colliders, + orientations, !&psdr.projectiles, !&psdr.mountings, !&psdr.beams, @@ -574,10 +576,12 @@ impl<'a> PhysicsSystemData<'a> { .center .distance_squared(previous_cache_other.center) > collision_boundary.powi(2) - || entity == entity_other { continue; }*/ + if entity == entity_other { + continue; + } if let Collider::Voxel { id } = collider_other { // use bounding cylinder regardless of our collider @@ -589,13 +593,31 @@ impl<'a> PhysicsSystemData<'a> { let z_min = z_min * scale; let z_max = z_max.clamped(1.2, 1.95) * scale; - let mut physics_state_delta = physics_state.clone(); - pos.0 -= pos_other.0; - let cylinder = (radius, z_min, z_max); - if let Some(dyna) = VOXEL_COLLIDER_MANIFEST.voxes.get(id) { + if let Some(voxel_collider) = VOXEL_COLLIDER_MANIFEST.read().colliders.get(id) { + let mut physics_state_delta = physics_state.clone(); + //let ori_2d = ori_other.look_dir().xy(); + //let ori_2d_quat = Quaternion::rotation_z(ori_2d.y.atan2(ori_2d.x)); + //let ori_2d_quat = Quaternion::from_xyzw(ori_2d.x, ori_2d.y, 0.0, 1.0).normalized(); + // deliberately don't use scale yet here, because the 11.0/0.8 + // thing is in the comp::Scale for visual reasons + let t1 = Mat4::from(Transform { + position: pos_other.0 + voxel_collider.translation, + orientation: Quaternion::identity(), + scale: Vec3::broadcast(1.0), + }); + let t2 = Mat4::from(Transform { + position: Vec3::zero(), + orientation: ori_other.0.normalized(), + scale: Vec3::broadcast(1.0), + }); + //let transform = t2 * t1; + let transform = t1; + pos.0 = transform.inverted().mul_point(pos.0); + //vel.0 = t2.inverted().mul_point(pos.0); + let cylinder = (radius, z_min, z_max); cylinder_voxel_collision( cylinder, - &*dyna, + &voxel_collider.dyna, entity, &mut pos, pos_delta, @@ -603,24 +625,27 @@ impl<'a> PhysicsSystemData<'a> { &mut physics_state_delta, &mut land_on_grounds, ); + + pos.0 = transform.mul_point(pos.0); + //vel.0 = t2.mul_point(vel.0); + + // union in the state updates, so that the state isn't just based on + // the most recent terrain that collision was attempted with + physics_state.on_ground |= physics_state_delta.on_ground; + physics_state.on_ceiling |= physics_state_delta.on_ceiling; + physics_state.on_wall = + physics_state.on_wall.or(physics_state_delta.on_wall); + physics_state + .touch_entities + .append(&mut physics_state_delta.touch_entities); + physics_state.in_liquid = + match (physics_state.in_liquid, physics_state_delta.in_liquid) { + // this match computes `x <|> y <|> liftA2 max x y` + (Some(x), Some(y)) => Some(x.max(y)), + (_, y @ Some(_)) => y, + _ => None, + }; } - pos.0 += pos_other.0; - // union in the state updates, so that the state isn't just based on - // the most recent terrain that collision was attempted with - physics_state.on_ground |= physics_state_delta.on_ground; - physics_state.on_ceiling |= physics_state_delta.on_ceiling; - physics_state.on_wall = - physics_state.on_wall.or(physics_state_delta.on_wall); - physics_state - .touch_entities - .append(&mut physics_state_delta.touch_entities); - physics_state.in_liquid = - match (physics_state.in_liquid, physics_state_delta.in_liquid) { - // this match computes `x <|> y <|> liftA2 max x y` - (Some(x), Some(y)) => Some(x.max(y)), - (_, y @ Some(_)) => y, - _ => None, - }; } } if pos != old_pos { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index eec891e144..6856dbbb4b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1972,7 +1972,7 @@ fn create_pipelines( &shaders.figure_vert.read().0, &shaders.figure_frag.read().0, &include_ctx, - gfx::state::CullFace::Nothing, + gfx::state::CullFace::Back, )?; // Construct a pipeline for rendering terrain diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index a584812462..ff334213e2 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -35,6 +35,9 @@ fn load_segment(mesh_name: &str) -> Segment { } fn graceful_load_vox(mesh_name: &str) -> AssetHandle { let full_specifier: String = ["voxygen.voxel.", mesh_name].concat(); + graceful_load_vox_fullspec(&full_specifier) +} +fn graceful_load_vox_fullspec(full_specifier: &str) -> AssetHandle { match DotVoxAsset::load(&full_specifier) { Ok(dot_vox) => dot_vox, Err(_) => { @@ -46,6 +49,9 @@ fn graceful_load_vox(mesh_name: &str) -> AssetHandle { fn graceful_load_segment(mesh_name: &str) -> Segment { Segment::from(&graceful_load_vox(mesh_name).read().0) } +fn graceful_load_segment_fullspec(full_specifier: &str) -> Segment { + Segment::from(&graceful_load_vox_fullspec(full_specifier).read().0) +} fn graceful_load_segment_flipped(mesh_name: &str, flipped: bool) -> Segment { Segment::from_vox(&graceful_load_vox(mesh_name).read().0, flipped) } @@ -4241,7 +4247,7 @@ fn mesh_ship_bone &ShipCentralSubSpec>(ma }, }; let bone = f(spec); - let central = graceful_load_segment(&bone.central.0); + let central = graceful_load_segment_fullspec(&["server.voxel.", &bone.central.0].concat()); (central, Vec3::from(bone.offset)) }