mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Account for model translation in the physics. The voxel collider still needs to be north-aligned for now.
This commit is contained in:
parent
a70e569396
commit
d98efb391b
@ -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"),
|
||||
),
|
||||
),
|
||||
})
|
||||
|
@ -17,7 +17,7 @@ impl From<Body> 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<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 {
|
||||
@ -71,26 +79,31 @@ pub mod figuredata {
|
||||
_: &str,
|
||||
) -> Result<Self, assets::Error> {
|
||||
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 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::<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);
|
||||
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<ShipSpec> = AssetExt::load_expect("server.manifests.ship_manifest");
|
||||
}
|
||||
}
|
||||
|
@ -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<f32>);
|
||||
pub struct Ori(pub Quaternion<f32>);
|
||||
|
||||
impl Default for Ori {
|
||||
/// Returns the default orientation (no rotation; default Dir)
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -35,6 +35,9 @@ fn load_segment(mesh_name: &str) -> Segment {
|
||||
}
|
||||
fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVoxAsset> {
|
||||
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) {
|
||||
Ok(dot_vox) => dot_vox,
|
||||
Err(_) => {
|
||||
@ -46,6 +49,9 @@ fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVoxAsset> {
|
||||
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<K: fmt::Debug+Eq+Hash, V, F: Fn(&V) -> &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))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user