Account for model translation in the physics. The voxel collider still needs to be north-aligned for now.

This commit is contained in:
Avi Weinstock 2021-03-11 23:42:53 -05:00
parent a70e569396
commit d98efb391b
6 changed files with 90 additions and 41 deletions

View File

@ -1,18 +1,23 @@
({ ({
DefaultAirship: ( DefaultAirship: (
bone0: ( bone0: (
//offset: (-20.0, -35.0, 1.0),
//offset: (3.0, 7.0, 1.0), //offset: (3.0, 7.0, 1.0),
offset: (0.25, 0.25, 0.25), //offset: (-20.75, -34.75, 1.25),
central: ("object.Human_Airship"), //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: ( bone1: (
offset: (0.0, 40.0, -8.0), offset: (0.0, 40.0, -8.0),
central: ("object.propeller-l"), phys_offset: (0.0, 0.0, 0.0),
central: ("propeller-l"),
), ),
bone2: ( bone2: (
offset: (0.0, 0.0, -4.0), offset: (0.0, 0.0, -4.0),
central: ("object.propeller-r"), phys_offset: (0.0, 0.0, 0.0),
central: ("propeller-r"),
), ),
), ),
}) })

View File

@ -17,7 +17,7 @@ impl From<Body> for super::Body {
impl Body { impl Body {
pub fn manifest_entry(&self) -> &'static str { pub fn manifest_entry(&self) -> &'static str {
match self { match self {
Body::DefaultAirship => "object.Human_Airship", Body::DefaultAirship => "Human_Airship",
} }
} }
} }
@ -38,6 +38,7 @@ pub mod figuredata {
use hashbrown::HashMap; use hashbrown::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde::Deserialize; use serde::Deserialize;
use vek::Vec3;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct VoxSimple(pub String); pub struct VoxSimple(pub String);
@ -55,6 +56,7 @@ pub mod figuredata {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct ShipCentralSubSpec { pub struct ShipCentralSubSpec {
pub offset: [f32; 3], pub offset: [f32; 3],
pub phys_offset: [f32; 3],
pub central: VoxSimple, pub central: VoxSimple,
} }
@ -62,7 +64,13 @@ pub mod figuredata {
#[derive(Clone)] #[derive(Clone)]
pub struct ShipSpec { pub struct ShipSpec {
pub central: AssetHandle<Ron<ShipCentralSpec>>, pub central: AssetHandle<Ron<ShipCentralSpec>>,
pub voxes: HashMap<String, Dyna<Block, (), ColumnAccess>>, pub colliders: HashMap<String, VoxelCollider>,
}
#[derive(Clone)]
pub struct VoxelCollider {
pub dyna: Dyna<Block, (), ColumnAccess>,
pub translation: Vec3<f32>,
} }
impl assets::Compound for ShipSpec { impl assets::Compound for ShipSpec {
@ -71,26 +79,31 @@ pub mod figuredata {
_: &str, _: &str,
) -> Result<Self, assets::Error> { ) -> Result<Self, assets::Error> {
let manifest: AssetHandle<Ron<ShipCentralSpec>> = AssetExt::load("server.manifests.ship_manifest")?; let manifest: AssetHandle<Ron<ShipCentralSpec>> = 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 (_, spec) in (manifest.read().0).0.iter() {
for bone in [&spec.bone0, &spec.bone1, &spec.bone2].iter() { for bone in [&spec.bone0, &spec.bone1, &spec.bone2].iter() {
// TODO: avoid the requirement for symlinks in "voxygen.voxel.object.", and load // TODO: avoid the requirement for symlinks in "voxygen.voxel.object.", and load
// the models from "server.voxel." instead // the models from "server.voxel." instead
let vox = let vox =
cache.load::<DotVoxAsset>(&["voxygen.voxel.", &bone.central.0].concat())?; cache.load::<DotVoxAsset>(&["server.voxel.", &bone.central.0].concat())?;
let dyna = Dyna::<Cell, (), ColumnAccess>::from_vox(&vox.read().0, false); let dyna = Dyna::<Cell, (), ColumnAccess>::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() { if let Some(rgb) = cell.get_color() {
Block::new(BlockKind::Misc, rgb) Block::new(BlockKind::Misc, rgb)
} else { } else {
Block::air(SpriteKind::Empty) 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 { Ok(ShipSpec {
central: manifest, 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 // 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 // (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) // 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<ShipSpec> = AssetExt::load_expect("server.manifests.ship_manifest");
} }
} }

View File

@ -9,7 +9,7 @@ use vek::{Quaternion, Vec2, Vec3};
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(into = "SerdeOri")] #[serde(into = "SerdeOri")]
#[serde(from = "SerdeOri")] #[serde(from = "SerdeOri")]
pub struct Ori(Quaternion<f32>); pub struct Ori(pub Quaternion<f32>);
impl Default for Ori { impl Default for Ori {
/// Returns the default orientation (no rotation; default Dir) /// Returns the default orientation (no rotation; default Dir)

View File

@ -364,7 +364,7 @@ impl<'a> PhysicsSystemData<'a> {
} = self; } = self;
// Apply movement inputs // Apply movement inputs
span!(guard, "Apply movement and terrain collision"); 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) = ( let (pos_writes, land_on_grounds) = (
&psdr.entities, &psdr.entities,
psdr.scales.maybe(), psdr.scales.maybe(),
@ -372,7 +372,7 @@ impl<'a> PhysicsSystemData<'a> {
&psdr.colliders, &psdr.colliders,
positions, positions,
&mut psdw.velocities, &mut psdw.velocities,
&psdw.orientations, orientations,
&mut psdw.physics_states, &mut psdw.physics_states,
previous_phys_cache, previous_phys_cache,
!&psdr.mountings, !&psdr.mountings,
@ -548,6 +548,7 @@ impl<'a> PhysicsSystemData<'a> {
previous_cache_other, previous_cache_other,
mass_other, mass_other,
collider_other, collider_other,
ori_other,
_, _,
_, _,
_, _,
@ -560,6 +561,7 @@ impl<'a> PhysicsSystemData<'a> {
previous_phys_cache, previous_phys_cache,
psdr.masses.maybe(), psdr.masses.maybe(),
&psdr.colliders, &psdr.colliders,
orientations,
!&psdr.projectiles, !&psdr.projectiles,
!&psdr.mountings, !&psdr.mountings,
!&psdr.beams, !&psdr.beams,
@ -574,10 +576,12 @@ impl<'a> PhysicsSystemData<'a> {
.center .center
.distance_squared(previous_cache_other.center) .distance_squared(previous_cache_other.center)
> collision_boundary.powi(2) > collision_boundary.powi(2)
|| entity == entity_other
{ {
continue; continue;
}*/ }*/
if entity == entity_other {
continue;
}
if let Collider::Voxel { id } = collider_other { if let Collider::Voxel { id } = collider_other {
// use bounding cylinder regardless of our collider // use bounding cylinder regardless of our collider
@ -589,13 +593,31 @@ impl<'a> PhysicsSystemData<'a> {
let z_min = z_min * scale; let z_min = z_min * scale;
let z_max = z_max.clamped(1.2, 1.95) * scale; let z_max = z_max.clamped(1.2, 1.95) * scale;
if let Some(voxel_collider) = VOXEL_COLLIDER_MANIFEST.read().colliders.get(id) {
let mut physics_state_delta = physics_state.clone(); let mut physics_state_delta = physics_state.clone();
pos.0 -= pos_other.0; //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); let cylinder = (radius, z_min, z_max);
if let Some(dyna) = VOXEL_COLLIDER_MANIFEST.voxes.get(id) {
cylinder_voxel_collision( cylinder_voxel_collision(
cylinder, cylinder,
&*dyna, &voxel_collider.dyna,
entity, entity,
&mut pos, &mut pos,
pos_delta, pos_delta,
@ -603,8 +625,10 @@ impl<'a> PhysicsSystemData<'a> {
&mut physics_state_delta, &mut physics_state_delta,
&mut land_on_grounds, &mut land_on_grounds,
); );
}
pos.0 += pos_other.0; 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 // union in the state updates, so that the state isn't just based on
// the most recent terrain that collision was attempted with // the most recent terrain that collision was attempted with
physics_state.on_ground |= physics_state_delta.on_ground; physics_state.on_ground |= physics_state_delta.on_ground;
@ -623,6 +647,7 @@ impl<'a> PhysicsSystemData<'a> {
}; };
} }
} }
}
if pos != old_pos { if pos != old_pos {
pos_writes.push((entity, pos)); pos_writes.push((entity, pos));
} }

View File

@ -1972,7 +1972,7 @@ fn create_pipelines(
&shaders.figure_vert.read().0, &shaders.figure_vert.read().0,
&shaders.figure_frag.read().0, &shaders.figure_frag.read().0,
&include_ctx, &include_ctx,
gfx::state::CullFace::Nothing, gfx::state::CullFace::Back,
)?; )?;
// Construct a pipeline for rendering terrain // Construct a pipeline for rendering terrain

View File

@ -35,6 +35,9 @@ fn load_segment(mesh_name: &str) -> Segment {
} }
fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVoxAsset> { fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVoxAsset> {
let full_specifier: String = ["voxygen.voxel.", mesh_name].concat(); let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
graceful_load_vox_fullspec(&full_specifier)
}
fn graceful_load_vox_fullspec(full_specifier: &str) -> AssetHandle<DotVoxAsset> {
match DotVoxAsset::load(&full_specifier) { match DotVoxAsset::load(&full_specifier) {
Ok(dot_vox) => dot_vox, Ok(dot_vox) => dot_vox,
Err(_) => { Err(_) => {
@ -46,6 +49,9 @@ fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVoxAsset> {
fn graceful_load_segment(mesh_name: &str) -> Segment { fn graceful_load_segment(mesh_name: &str) -> Segment {
Segment::from(&graceful_load_vox(mesh_name).read().0) 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 { fn graceful_load_segment_flipped(mesh_name: &str, flipped: bool) -> Segment {
Segment::from_vox(&graceful_load_vox(mesh_name).read().0, flipped) Segment::from_vox(&graceful_load_vox(mesh_name).read().0, flipped)
} }
@ -4241,7 +4247,7 @@ fn mesh_ship_bone<K: fmt::Debug+Eq+Hash, V, F: Fn(&V) -> &ShipCentralSubSpec>(ma
}, },
}; };
let bone = f(spec); 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)) (central, Vec3::from(bone.offset))
} }