Fix additive blending of quaternions (#15662)
# Objective Fixes #13832 ## Solution Additively blend quaternions like this: ```rust rotation = Quat::slerp(Quat::IDENTITY, incoming_rotation, weight) * rotation; ``` ## Testing Ran `animation_masks`, which behaves the same as before. (In the context of an animation being blended only onto the base pose, there is no difference.) We should create some examples that actually exercise more of the capabilities of the `AnimationGraph` so that issues like this can become more visible in general. (On the other hand, I'm quite certain this was wrong before.) ## Migration Guide This PR changes the implementation of `Quat: Animatable`, which was not used internally by Bevy prior to this release version. If you relied on the old behavior of additive quaternion blending in manual applications, that code will have to be updated, as the old behavior was incorrect.
This commit is contained in:
parent
25bfa80e60
commit
42e0771633
@ -149,7 +149,8 @@ impl Animatable for Transform {
|
|||||||
if input.additive {
|
if input.additive {
|
||||||
translation += input.weight * Vec3A::from(input.value.translation);
|
translation += input.weight * Vec3A::from(input.value.translation);
|
||||||
scale += input.weight * Vec3A::from(input.value.scale);
|
scale += input.weight * Vec3A::from(input.value.scale);
|
||||||
rotation = rotation.slerp(input.value.rotation, input.weight);
|
rotation =
|
||||||
|
Quat::slerp(Quat::IDENTITY, input.value.rotation, input.weight) * rotation;
|
||||||
} else {
|
} else {
|
||||||
translation = Vec3A::interpolate(
|
translation = Vec3A::interpolate(
|
||||||
&translation,
|
&translation,
|
||||||
@ -181,8 +182,17 @@ impl Animatable for Quat {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn blend(inputs: impl Iterator<Item = BlendInput<Self>>) -> Self {
|
fn blend(inputs: impl Iterator<Item = BlendInput<Self>>) -> Self {
|
||||||
let mut value = Self::IDENTITY;
|
let mut value = Self::IDENTITY;
|
||||||
for input in inputs {
|
for BlendInput {
|
||||||
value = Self::interpolate(&value, &input.value, input.weight);
|
weight,
|
||||||
|
value: incoming_value,
|
||||||
|
additive,
|
||||||
|
} in inputs
|
||||||
|
{
|
||||||
|
if additive {
|
||||||
|
value = Self::slerp(Self::IDENTITY, incoming_value, weight) * value;
|
||||||
|
} else {
|
||||||
|
value = Self::interpolate(&value, &incoming_value, weight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -196,8 +196,7 @@ pub struct AnimatableCurve<P, C> {
|
|||||||
///
|
///
|
||||||
/// You shouldn't ordinarily need to instantiate one of these manually. Bevy
|
/// You shouldn't ordinarily need to instantiate one of these manually. Bevy
|
||||||
/// will automatically do so when you use an [`AnimatableCurve`] instance.
|
/// will automatically do so when you use an [`AnimatableCurve`] instance.
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
pub struct AnimatableCurveEvaluator<P>
|
pub struct AnimatableCurveEvaluator<P>
|
||||||
where
|
where
|
||||||
P: AnimatableProperty,
|
P: AnimatableProperty,
|
||||||
@ -346,8 +345,7 @@ pub struct TranslationCurve<C>(pub C);
|
|||||||
///
|
///
|
||||||
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
||||||
/// so.
|
/// so.
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
pub struct TranslationCurveEvaluator {
|
pub struct TranslationCurveEvaluator {
|
||||||
evaluator: BasicAnimationCurveEvaluator<Vec3>,
|
evaluator: BasicAnimationCurveEvaluator<Vec3>,
|
||||||
}
|
}
|
||||||
@ -444,8 +442,7 @@ pub struct RotationCurve<C>(pub C);
|
|||||||
///
|
///
|
||||||
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
||||||
/// so.
|
/// so.
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
pub struct RotationCurveEvaluator {
|
pub struct RotationCurveEvaluator {
|
||||||
evaluator: BasicAnimationCurveEvaluator<Quat>,
|
evaluator: BasicAnimationCurveEvaluator<Quat>,
|
||||||
}
|
}
|
||||||
@ -542,8 +539,7 @@ pub struct ScaleCurve<C>(pub C);
|
|||||||
///
|
///
|
||||||
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
/// You shouldn't need to instantiate this manually; Bevy will automatically do
|
||||||
/// so.
|
/// so.
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
pub struct ScaleCurveEvaluator {
|
pub struct ScaleCurveEvaluator {
|
||||||
evaluator: BasicAnimationCurveEvaluator<Vec3>,
|
evaluator: BasicAnimationCurveEvaluator<Vec3>,
|
||||||
}
|
}
|
||||||
@ -636,8 +632,7 @@ impl AnimationCurveEvaluator for ScaleCurveEvaluator {
|
|||||||
#[reflect(from_reflect = false)]
|
#[reflect(from_reflect = false)]
|
||||||
pub struct WeightsCurve<C>(pub C);
|
pub struct WeightsCurve<C>(pub C);
|
||||||
|
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
struct WeightsCurveEvaluator {
|
struct WeightsCurveEvaluator {
|
||||||
/// The values of the stack, in which each element is a list of morph target
|
/// The values of the stack, in which each element is a list of morph target
|
||||||
/// weights.
|
/// weights.
|
||||||
@ -825,8 +820,7 @@ impl AnimationCurveEvaluator for WeightsCurveEvaluator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
struct BasicAnimationCurveEvaluator<A>
|
struct BasicAnimationCurveEvaluator<A>
|
||||||
where
|
where
|
||||||
A: Animatable,
|
A: Animatable,
|
||||||
@ -835,8 +829,7 @@ where
|
|||||||
blend_register: Option<(A, f32)>,
|
blend_register: Option<(A, f32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
|
||||||
struct BasicAnimationCurveEvaluatorStackElement<A>
|
struct BasicAnimationCurveEvaluatorStackElement<A>
|
||||||
where
|
where
|
||||||
A: Animatable,
|
A: Animatable,
|
||||||
|
Loading…
Reference in New Issue
Block a user