Rework mounting animation so that full hierarchies of animation transforms can be applied to the mounter, factor out some common code in figure/mod.rs

This commit is contained in:
Imbris 2021-06-26 02:11:50 -04:00
parent fafb344404
commit b2bf83e200
6 changed files with 205 additions and 347 deletions

View File

@ -764,8 +764,8 @@ impl Body {
)
}
// Physical offset relative to the mountee
pub fn mounting_offset(&self) -> Vec3<f32> {
/// Component of the mounting offset specific to the mountee
pub fn mountee_offset(&self) -> Vec3<f32> {
match self {
Body::QuadrupedMedium(quadruped_medium) => {
match (quadruped_medium.species, quadruped_medium.body_type) {
@ -819,6 +819,15 @@ impl Body {
}
.into()
}
/// Component of the mounting offset specific to the mounter
pub fn mounter_offset(&self) -> Vec3<f32> {
match self {
Body::Humanoid(_) => [0.0, 0.0, 0.0],
_ => [0.0, 0.0, 0.0],
}
.into()
}
}
impl Component for Body {

View File

@ -66,8 +66,9 @@ impl<'a> System<'a> for Sys {
let ori = orientations.get(entity).copied();
let vel = velocities.get(entity).copied();
if let (Some(pos), Some(ori), Some(vel)) = (pos, ori, vel) {
let mounting_offset =
body.map_or(Vec3::unit_z(), Body::mounting_offset);
let mounter_body = bodies.get(mounter);
let mounting_offset = body.map_or(Vec3::unit_z(), Body::mountee_offset)
+ mounter_body.map_or(Vec3::zero(), Body::mounter_offset);
let _ = positions.insert(
mounter,
Pos(Vec3 {

View File

@ -73,20 +73,12 @@ skeleton_impls!(struct CharacterSkeleton {
control_r,
:: // Begin non-bone fields
holding_lantern: bool,
offsets: Option<Transform<f32, f32, f32>>,
mountee_body: Option<comp::Body>,
});
impl CharacterSkeleton {
pub fn new(
holding_lantern: bool,
offsets: Option<Transform<f32, f32, f32>>,
mountee_body: Option<comp::Body>,
) -> Self {
pub fn new(holding_lantern: bool) -> Self {
Self {
holding_lantern,
offsets,
mountee_body,
..Self::default()
}
}
@ -107,21 +99,7 @@ impl Skeleton for CharacterSkeleton {
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Offsets {
let torso_mat = base_mat
* if let Some((offset, body)) = self.offsets.zip(self.mountee_body) {
let hitbox_offsets = body.mounting_offset();
let visual_offset = mounting_offset(body);
Mat4::<f32>::from(Transform {
position: offset.position
- Vec3::from([0.0, hitbox_offsets.y, hitbox_offsets.z]),
orientation: offset.orientation,
scale: Vec3::<f32>::one(),
}) * Mat4::<f32>::from(self.torso).translated_3d(visual_offset)
} else {
Mat4::<f32>::from(self.torso)
};
let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
let chest_mat = torso_mat * Mat4::<f32>::from(self.chest);
let head_mat = chest_mat * Mat4::<f32>::from(self.head);
let shorts_mat = chest_mat * Mat4::<f32>::from(self.shorts);
@ -356,53 +334,3 @@ impl<'a> From<&'a Body> for SkeletonAttr {
}
}
}
pub fn mounting_offset(body: comp::Body) -> Vec3<f32> {
match body {
comp::Body::QuadrupedMedium(quadruped_medium) => {
match (quadruped_medium.species, quadruped_medium.body_type) {
(comp::quadruped_medium::Species::Grolgar, _) => Vec3::from([0.0, -0.6, 0.5]),
(comp::quadruped_medium::Species::Saber, _) => Vec3::from([0.0, -0.75, 0.23]),
(comp::quadruped_medium::Species::Tiger, _) => Vec3::from([0.0, -0.75, 0.23]),
(comp::quadruped_medium::Species::Tuskram, _) => Vec3::from([0.0, -0.75, 0.25]),
(comp::quadruped_medium::Species::Lion, _) => Vec3::from([0.0, -0.9, 0.25]),
(comp::quadruped_medium::Species::Tarasque, _) => Vec3::from([0.0, -1.1, 0.3]),
(comp::quadruped_medium::Species::Wolf, _) => Vec3::from([0.0, -0.7, 0.15]),
(comp::quadruped_medium::Species::Frostfang, _) => Vec3::from([0.0, -0.8, 0.1]),
(comp::quadruped_medium::Species::Mouflon, _) => Vec3::from([0.0, -0.8, 0.1]),
(comp::quadruped_medium::Species::Catoblepas, _) => Vec3::from([0.0, -0.4, 0.4]),
(comp::quadruped_medium::Species::Bonerattler, _) => Vec3::from([0.0, -0.3, 0.2]),
(comp::quadruped_medium::Species::Deer, _) => Vec3::from([0.0, -0.9, 0.1]),
(comp::quadruped_medium::Species::Hirdrasil, _) => Vec3::from([0.0, -1.0, 0.0]),
(comp::quadruped_medium::Species::Roshwalr, _) => Vec3::from([0.0, -0.2, 0.7]),
(comp::quadruped_medium::Species::Donkey, _) => Vec3::from([0.0, -0.5, 0.15]),
(comp::quadruped_medium::Species::Camel, _) => Vec3::from([0.0, -1.4, 0.3]),
(comp::quadruped_medium::Species::Zebra, _) => Vec3::from([0.0, -0.6, 0.1]),
(comp::quadruped_medium::Species::Antelope, _) => Vec3::from([0.0, -0.8, 0.1]),
(comp::quadruped_medium::Species::Kelpie, _) => Vec3::from([0.0, -0.8, 0.05]),
(comp::quadruped_medium::Species::Horse, _) => Vec3::from([0.0, -0.8, 0.1]),
(comp::quadruped_medium::Species::Barghest, _) => Vec3::from([0.0, -0.8, 0.6]),
(
comp::quadruped_medium::Species::Cattle,
comp::quadruped_medium::BodyType::Male,
) => Vec3::from([0.0, -0.4, 0.7]),
(
comp::quadruped_medium::Species::Cattle,
comp::quadruped_medium::BodyType::Female,
) => Vec3::from([0.0, -0.3, 0.5]),
(comp::quadruped_medium::Species::Darkhound, _) => Vec3::from([0.0, -0.5, 0.2]),
(comp::quadruped_medium::Species::Highland, _) => Vec3::from([0.0, -0.2, 0.8]),
(comp::quadruped_medium::Species::Yak, _) => Vec3::from([0.0, -0.2, 0.8]),
(comp::quadruped_medium::Species::Panda, _) => Vec3::from([0.0, -0.8, 0.2]),
(comp::quadruped_medium::Species::Bear, _) => Vec3::from([0.0, -1.5, 0.6]),
(comp::quadruped_medium::Species::Dreadhorn, _) => Vec3::from([0.0, -1.5, 1.6]),
(comp::quadruped_medium::Species::Moose, _) => Vec3::from([0.0, -0.9, 0.3]),
(comp::quadruped_medium::Species::Snowleopard, _) => Vec3::from([0.0, -0.9, 0.2]),
}
},
comp::Body::Ship(comp::ship::Body::DefaultAirship) => Vec3::from([0.0, 0.0, 10.0]),
comp::Body::Dragon(_) => Vec3::from([0.0, -0.7, 6.4]),
_ => Vec3::unit_z(),
}
}

View File

@ -81,9 +81,24 @@ impl Skeleton for QuadrupedMediumSkeleton {
make_bone(leg_bl_mat * Mat4::<f32>::from(self.foot_bl)),
make_bone(leg_br_mat * Mat4::<f32>::from(self.foot_br)),
];
// Offset from the mounted bone's origin.
// Note: This could be its own bone if we need to animate it.
let mount_point = Vec3::new(0.0, -7.0, 3.0);
let mount_position = (torso_front_mat * Vec4::from_point(mount_point))
.homogenized()
.xyz();
// NOTE: We apply the ori from base_mat externally so we don't need to worry
// about it here for now.
let mount_orientation = self.torso_front.orientation;
Offsets {
lantern: Vec3::default(),
mount_bone: self.torso_front,
mount_bone: Transform {
position: mount_position,
orientation: mount_orientation,
scale: Vec3::one(),
},
}
}
}

View File

@ -755,15 +755,30 @@ impl FigureMgr {
let hands = (active_tool_hand, second_tool_hand);
// If a mountee exists, get its physical mounting offsets and its body
let (mountee_offsets, mountee_body) = (|| -> Option<_> {
// If a mountee exists, get its animated mounting transform and its position
let mount_transform_pos = (|| -> Option<_> {
let Mounting(entity) = mountings?;
let entity = uid_allocator.retrieve_entity_internal((*entity).into())?;
let body = *bodies.get(entity)?;
let meta = self.states.get_mut(&body, &entity)?;
Some((Some(meta.mountee_offset), Some(body)))
})()
.unwrap_or((None, None));
Some((meta.mount_transform, meta.mount_world_pos))
})();
let common_params = FigureUpdateCommonParameters {
pos: pos.0,
ori,
scale,
mount_transform_pos,
body: Some(*body),
col,
dt,
_lpindex: lpindex,
_visible: in_frustum,
is_player,
_camera: camera,
terrain,
ground_vel: physics.ground_vel,
};
match body {
Body::Humanoid(body) => {
@ -792,14 +807,7 @@ impl FigureMgr {
.character_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(
renderer,
CharacterSkeleton::new(
holding_lantern,
mountee_offsets,
mountee_body,
),
)
FigureState::new(renderer, CharacterSkeleton::new(holding_lantern))
});
// Average velocity relative to the current ground
@ -823,11 +831,7 @@ impl FigureMgr {
// Standing
(true, false, false, false) => {
anim::character::StandAnimation::update_skeleton(
&CharacterSkeleton::new(
holding_lantern,
mountee_offsets,
mountee_body,
),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -846,11 +850,7 @@ impl FigureMgr {
// Running
(true, true, false, false) => {
anim::character::RunAnimation::update_skeleton(
&CharacterSkeleton::new(
holding_lantern,
mountee_offsets,
mountee_body,
),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -871,11 +871,7 @@ impl FigureMgr {
// In air
(false, _, false, false) => {
anim::character::JumpAnimation::update_skeleton(
&CharacterSkeleton::new(
holding_lantern,
mountee_offsets,
mountee_body,
),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -893,7 +889,7 @@ impl FigureMgr {
},
// Swim
(_, _, true, false) => anim::character::SwimAnimation::update_skeleton(
&CharacterSkeleton::new(holding_lantern, mountee_offsets, mountee_body),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -911,7 +907,7 @@ impl FigureMgr {
),
// Mount
(_, _, _, true) => anim::character::MountAnimation::update_skeleton(
&CharacterSkeleton::new(holding_lantern, mountee_offsets, mountee_body),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -1589,20 +1585,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::QuadrupedSmall(body) => {
@ -1787,20 +1773,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::QuadrupedMedium(body) => {
@ -2110,20 +2086,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::QuadrupedLow(body) => {
@ -2466,20 +2432,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::BirdMedium(body) => {
@ -2576,20 +2532,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::FishMedium(body) => {
@ -2665,20 +2611,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::BipedSmall(body) => {
@ -3009,20 +2945,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::Dragon(body) => {
@ -3103,20 +3029,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::Theropod(body) => {
@ -3286,20 +3202,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::BirdLarge(body) => {
@ -3607,20 +3513,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::FishSmall(body) => {
@ -3696,20 +3592,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::BipedLarge(body) => {
@ -4324,20 +4210,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::Golem(body) => {
@ -4572,20 +4448,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::Object(body) => {
@ -4700,20 +4566,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
true,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
Body::Ship(body) => {
@ -4793,20 +4649,10 @@ impl FigureMgr {
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
&mut update_buf,
&common_params,
state_animation_rate,
model,
lpindex,
true,
is_player,
camera,
&mut update_buf,
terrain,
physics.ground_vel,
);
},
}
@ -5392,7 +5238,14 @@ impl FigureColLights {
pub struct FigureStateMeta {
lantern_offset: anim::vek::Vec3<f32>,
mountee_offset: anim::vek::Transform<f32, f32, f32>,
// Animation to be applied to mounter of this entity
mount_transform: anim::vek::Transform<f32, f32, f32>,
// Contains the position of this figure or if it is a mounter it will contain the mountee's
// mount_world_pos
// Unlike the interpolated position stored in the ecs this will be propagated along
// mount chains
// For use if it is mounted by another figure
mount_world_pos: anim::vek::Vec3<f32>,
state_time: f32,
last_ori: anim::vek::Quaternion<f32>,
lpindex: u8,
@ -5430,6 +5283,27 @@ impl<S> DerefMut for FigureState<S> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.meta }
}
/// Parameters that don't depend on the body variant or animation results and
/// are also not mutable
pub struct FigureUpdateCommonParameters<'a> {
pub pos: anim::vek::Vec3<f32>,
pub ori: anim::vek::Quaternion<f32>,
pub scale: f32,
pub mount_transform_pos: Option<(anim::vek::Transform<f32, f32, f32>, anim::vek::Vec3<f32>)>,
pub body: Option<Body>,
pub col: vek::Rgba<f32>,
pub dt: f32,
// TODO: evaluate unused variable
pub _lpindex: u8,
// TODO: evaluate unused variable
pub _visible: bool,
pub is_player: bool,
// TODO: evaluate unused variable
pub _camera: &'a Camera,
pub terrain: Option<&'a Terrain>,
pub ground_vel: Vec3<f32>,
}
impl<S: Skeleton> FigureState<S> {
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
@ -5438,7 +5312,8 @@ impl<S: Skeleton> FigureState<S> {
Self {
meta: FigureStateMeta {
lantern_offset: offsets.lantern,
mountee_offset: offsets.mount_bone,
mount_transform: offsets.mount_bone,
mount_world_pos: anim::vek::Vec3::zero(),
state_time: 0.0,
last_ori: Ori::default().into(),
lpindex: 0,
@ -5455,24 +5330,27 @@ impl<S: Skeleton> FigureState<S> {
}
}
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
pub fn update<const N: usize>(
&mut self,
renderer: &mut Renderer,
pos: anim::vek::Vec3<f32>,
ori: anim::vek::Quaternion<f32>,
scale: f32,
col: vek::Rgba<f32>,
dt: f32,
buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT],
FigureUpdateCommonParameters {
pos,
ori,
scale,
mount_transform_pos,
body,
col,
dt,
_lpindex,
_visible,
is_player,
_camera,
terrain,
ground_vel,
}: &FigureUpdateCommonParameters,
state_animation_rate: f32,
model: Option<&FigureModelEntry<N>>,
_lpindex: u8,
_visible: bool,
is_player: bool,
_camera: &Camera,
buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT],
terrain: Option<&Terrain>,
ground_vel: Vec3<f32>,
) {
// NOTE: As long as update() always gets called after get_or_create_model(), and
// visibility is not set again until after the model is rendered, we
@ -5500,12 +5378,34 @@ impl<S: Skeleton> FigureState<S> {
/* let radius = vek::Extent3::<f32>::from(model.bounds.half_size()).reduce_partial_max();
let _bounds = BoundingSphere::new(pos.into_array(), scale * 0.8 * radius); */
self.last_ori = vek::Lerp::lerp(self.last_ori, ori, 15.0 * dt).normalized();
self.last_ori = vek::Lerp::lerp(self.last_ori, *ori, 15.0 * dt).normalized();
self.state_time += dt * state_animation_rate;
let mat = {
anim::vek::Mat4::from(ori) * anim::vek::Mat4::scaling_3d(anim::vek::Vec3::from(scale))
let ori_scale = anim::vek::Mat4::from(*ori)
* anim::vek::Mat4::scaling_3d(anim::vek::Vec3::from(*scale));
// NOTE: It is kind of a hack to use this entity's ori here if it is
// mounted on another but this happens to match the ori of the
// mountee so it works, change this if it causes jankiness in the future.
if let Some((transform, _)) = *mount_transform_pos {
// Note: if we had a way to compute a "default" transform of the bones then in
// the animations we could make use of the mountee_offset from common by
// computing what the offset of the mounter is from the mounted
// bone in its default position when the mounter has the mount
// offset in common applied to it. Since we don't have this
// right now we instead need to recreate the same effect in the
// animations and keep it in sync.
//
// Component of mounting offset specific to the mounter.
let mounter_offset = anim::vek::Mat4::translation_3d(
body.map_or_else(Vec3::zero, |b| b.mounter_offset()),
);
anim::vek::Mat4::from(transform) * ori_scale * mounter_offset
} else {
ori_scale
}
};
let atlas_offs = model.allocation.rectangle.min;
@ -5555,9 +5455,9 @@ impl<S: Skeleton> FigureState<S> {
let locals = FigureLocals::new(
mat,
col.rgb(),
pos,
mount_transform_pos.map_or(*pos, |(_, pos)| pos),
vek::Vec2::new(atlas_offs.x, atlas_offs.y),
is_player,
*is_player,
self.last_light,
self.last_glow,
);
@ -5569,17 +5469,19 @@ impl<S: Skeleton> FigureState<S> {
renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]);
self.lantern_offset = offsets.lantern;
self.mountee_offset = offsets.mount_bone;
// TODO: compute the mount bone only when it is needed
self.mount_transform = offsets.mount_bone;
self.mount_world_pos = mount_transform_pos.map_or(*pos, |(_, pos)| pos);
let smoothing = (5.0 * dt).min(1.0);
if let Some(last_pos) = self.last_pos {
self.avg_vel = (1.0 - smoothing) * self.avg_vel + smoothing * (pos - last_pos) / dt;
self.avg_vel = (1.0 - smoothing) * self.avg_vel + smoothing * (pos - last_pos) / *dt;
}
self.last_pos = Some(pos);
self.last_pos = Some(*pos);
// Can potentially overflow
if self.avg_vel.magnitude_squared() != 0.0 {
self.acc_vel += (self.avg_vel - ground_vel).magnitude() * dt;
self.acc_vel += (self.avg_vel - *ground_vel).magnitude() * dt;
} else {
self.acc_vel = 0.0;
}

View File

@ -7,7 +7,10 @@ use crate::{
},
scene::{
camera::{self, Camera, CameraMode},
figure::{load_mesh, FigureColLights, FigureModelCache, FigureModelEntry, FigureState},
figure::{
load_mesh, FigureColLights, FigureModelCache, FigureModelEntry, FigureState,
FigureUpdateCommonParameters,
},
},
window::{Event, PressState},
};
@ -144,26 +147,25 @@ impl Scene {
col_lights
.create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range]);
let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
state.update(
renderer,
anim::vek::Vec3::zero(),
anim::vek::Quaternion::rotation_from_to_3d(
let common_params = FigureUpdateCommonParameters {
pos: anim::vek::Vec3::zero(),
ori: anim::vek::Quaternion::rotation_from_to_3d(
anim::vek::Vec3::unit_y(),
anim::vek::Vec3::new(start_angle.sin(), -start_angle.cos(), 0.0),
),
1.0,
Rgba::broadcast(1.0),
15.0, // Want to get there immediately.
1.0,
Some(&model),
0,
true,
false,
&camera,
&mut buf,
None,
Vec3::zero(),
);
scale: 1.0,
mount_transform_pos: None,
body: None,
col: Rgba::broadcast(1.0),
dt: 15.0, // Want to get there immediately.
_lpindex: 0,
_visible: true,
is_player: false,
_camera: &camera,
terrain: None,
ground_vel: Vec3::zero(),
};
state.update(renderer, &mut buf, &common_params, 1.0, Some(&model));
(model, state)
}),
col_lights,
@ -322,26 +324,27 @@ impl Scene {
)
.0;
let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
self.figure_state.update(
renderer,
anim::vek::Vec3::zero(),
anim::vek::Quaternion::rotation_from_to_3d(
let common_params = FigureUpdateCommonParameters {
pos: anim::vek::Vec3::zero(),
ori: anim::vek::Quaternion::rotation_from_to_3d(
anim::vek::Vec3::unit_y(),
anim::vek::Vec3::new(self.char_ori.sin(), -self.char_ori.cos(), 0.0),
),
1.0,
Rgba::broadcast(1.0),
scene_data.delta_time,
1.0,
model,
0,
true,
false,
&self.camera,
&mut buf,
None,
Vec3::zero(),
);
scale: 1.0,
mount_transform_pos: None,
body: None,
col: Rgba::broadcast(1.0),
dt: scene_data.delta_time,
_lpindex: 0,
_visible: true,
is_player: false,
_camera: &self.camera,
terrain: None,
ground_vel: Vec3::zero(),
};
self.figure_state
.update(renderer, &mut buf, &common_params, 1.0, model);
}
}