From 7a41d75e607f21999dcef8f31efc2d7951df164b Mon Sep 17 00:00:00 2001 From: A-Walrus Date: Tue, 26 Sep 2023 08:57:40 +0300 Subject: [PATCH 1/4] Fix morph interpolation --- crates/bevy_animation/src/lib.rs | 39 ++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index d108782119cc5..9cf6cf8dbb1f3 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -565,8 +565,17 @@ fn run_animation_player( } } -/// Update `weights` based on weights in `keyframes` at index `key_index` -/// with a linear interpolation on `key_lerp`. +/// Update `weights` based on weights in `keyframe` with a linear interpolation +/// on `key_lerp`. +fn lerp_morph_weights(weights: &mut [f32], key_lerp: f32, keyframe: impl Iterator) { + let zipped = weights.iter_mut().zip(keyframe); + for (morph_weight, keyframe) in zipped { + let minus_lerp = 1.0 - key_lerp; + *morph_weight = (*morph_weight * minus_lerp) + (keyframe * key_lerp); + } +} + +/// Extract a keyframe from a list of keyframes by index. /// /// # Panics /// @@ -575,16 +584,10 @@ fn run_animation_player( /// This happens when `keyframes` is not formatted as described in /// [`Keyframes::Weights`]. A possible cause is [`AnimationClip`] not being /// meant to be used for the [`MorphWeights`] of the entity it's being applied to. -fn lerp_morph_weights(weights: &mut [f32], key_lerp: f32, keyframes: &[f32], key_index: usize) { - let target_count = weights.len(); +fn get_keyframe(target_count: usize, keyframes: &[f32], key_index: usize) -> &[f32] { let start = target_count * key_index; let end = target_count * (key_index + 1); - - let zipped = weights.iter_mut().zip(&keyframes[start..end]); - for (morph_weight, keyframe) in zipped { - let minus_lerp = 1.0 - key_lerp; - *morph_weight = (*morph_weight * minus_lerp) + (keyframe * key_lerp); - } + &keyframes[start..end] } #[allow(clippy::too_many_arguments)] @@ -657,7 +660,12 @@ fn apply_animation( } Keyframes::Weights(keyframes) => { if let Ok(morphs) = &mut morphs { - lerp_morph_weights(morphs.weights_mut(), weight, keyframes, 0); + let target_count = morphs.weights().len(); + lerp_morph_weights( + morphs.weights_mut(), + weight, + get_keyframe(target_count, keyframes, 0).iter().copied(), + ); } } } @@ -707,7 +715,14 @@ fn apply_animation( } Keyframes::Weights(keyframes) => { if let Ok(morphs) = &mut morphs { - lerp_morph_weights(morphs.weights_mut(), weight, keyframes, step_start); + let target_count = morphs.weights().len(); + let morph_start = get_keyframe(target_count, keyframes, step_start); + let morph_end = get_keyframe(target_count, keyframes, step_start + 1); + let result = morph_start + .iter() + .zip(morph_end) + .map(|(a, b)| *a * (1.0 - lerp) + *b * lerp); + lerp_morph_weights(morphs.weights_mut(), weight, result); } } } From e0d1f3d83cc43508c10c26d5cfa202b9644b2699 Mon Sep 17 00:00:00 2001 From: A-Walrus <58790821+A-Walrus@users.noreply.github.com> Date: Tue, 26 Sep 2023 12:53:43 +0300 Subject: [PATCH 2/4] Refactor lerp Co-authored-by: Nicola Papale --- crates/bevy_animation/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 9cf6cf8dbb1f3..38bbcdaa75ecf 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -570,8 +570,7 @@ fn run_animation_player( fn lerp_morph_weights(weights: &mut [f32], key_lerp: f32, keyframe: impl Iterator) { let zipped = weights.iter_mut().zip(keyframe); for (morph_weight, keyframe) in zipped { - let minus_lerp = 1.0 - key_lerp; - *morph_weight = (*morph_weight * minus_lerp) + (keyframe * key_lerp); + *morph_weight += (keyframe - *morph_weight) * key_lerp; } } From e9eab6f827840dc9b93a4c14cd7de0e9611bc8cc Mon Sep 17 00:00:00 2001 From: A-Walrus Date: Tue, 26 Sep 2023 12:56:53 +0300 Subject: [PATCH 3/4] Change argument order --- crates/bevy_animation/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 38bbcdaa75ecf..f810f99363cba 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -567,7 +567,7 @@ fn run_animation_player( /// Update `weights` based on weights in `keyframe` with a linear interpolation /// on `key_lerp`. -fn lerp_morph_weights(weights: &mut [f32], key_lerp: f32, keyframe: impl Iterator) { +fn lerp_morph_weights(weights: &mut [f32], keyframe: impl Iterator, key_lerp: f32) { let zipped = weights.iter_mut().zip(keyframe); for (morph_weight, keyframe) in zipped { *morph_weight += (keyframe - *morph_weight) * key_lerp; @@ -662,8 +662,8 @@ fn apply_animation( let target_count = morphs.weights().len(); lerp_morph_weights( morphs.weights_mut(), - weight, get_keyframe(target_count, keyframes, 0).iter().copied(), + weight, ); } } @@ -721,7 +721,7 @@ fn apply_animation( .iter() .zip(morph_end) .map(|(a, b)| *a * (1.0 - lerp) + *b * lerp); - lerp_morph_weights(morphs.weights_mut(), weight, result); + lerp_morph_weights(morphs.weights_mut(), result, weight); } } } From 4ef3ec72de670fc5721e0fb36929d420ffe10bda Mon Sep 17 00:00:00 2001 From: A-Walrus <58790821+A-Walrus@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:51:33 +0300 Subject: [PATCH 4/4] Refactor lerp Co-authored-by: CGMossa --- crates/bevy_animation/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index f810f99363cba..3c2477bf64f3b 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -720,7 +720,7 @@ fn apply_animation( let result = morph_start .iter() .zip(morph_end) - .map(|(a, b)| *a * (1.0 - lerp) + *b * lerp); + .map(|(a, b)| *a + lerp * (*b - *a)); lerp_morph_weights(morphs.weights_mut(), result, weight); } }