diff --git a/crates/bevy_animation/src/animation_curves.rs b/crates/bevy_animation/src/animation_curves.rs index 14ee7f24fc..fbe555ca3b 100644 --- a/crates/bevy_animation/src/animation_curves.rs +++ b/crates/bevy_animation/src/animation_curves.rs @@ -746,7 +746,15 @@ impl WeightsCurveEvaluator { None => { self.blend_register_blend_weight = Some(weight_to_blend); self.blend_register_morph_target_weights.clear(); - self.blend_register_morph_target_weights.extend(stack_iter); + + // In the additive case, the values pushed onto the blend register need + // to be scaled by the weight. + if additive { + self.blend_register_morph_target_weights + .extend(stack_iter.map(|m| m * weight_to_blend)); + } else { + self.blend_register_morph_target_weights.extend(stack_iter); + } } Some(ref mut current_weight) => { @@ -877,7 +885,9 @@ where } = self.stack.pop().unwrap(); match self.blend_register.take() { - None => self.blend_register = Some((value_to_blend, weight_to_blend)), + None => { + self.initialize_blend_register(value_to_blend, weight_to_blend, additive); + } Some((mut current_value, mut current_weight)) => { current_weight += weight_to_blend; @@ -912,6 +922,22 @@ where Ok(()) } + fn initialize_blend_register(&mut self, value: A, weight: f32, additive: bool) { + if additive { + let scaled_value = A::blend( + [BlendInput { + weight, + value, + additive: true, + }] + .into_iter(), + ); + self.blend_register = Some((scaled_value, weight)); + } else { + self.blend_register = Some((value, weight)); + } + } + fn push_blend_register( &mut self, weight: f32, diff --git a/crates/bevy_animation/src/graph.rs b/crates/bevy_animation/src/graph.rs index d3bf1cc52d..eb0589c539 100644 --- a/crates/bevy_animation/src/graph.rs +++ b/crates/bevy_animation/src/graph.rs @@ -217,9 +217,8 @@ pub enum AnimationNodeType { /// additively. /// /// The weights of all the children of this node are *not* normalized to - /// 1.0. Rather, the first child is used as a base, ignoring its weight, - /// while the others are multiplied by their respective weights and then - /// added in sequence to the base. + /// 1.0. Rather, each child is multiplied by its respective weight and + /// added in sequence. /// /// Add nodes are primarily useful for superimposing an animation for a /// portion of a rig on top of the main animation. For example, an add node diff --git a/examples/animation/animation_masks.rs b/examples/animation/animation_masks.rs index 08e3b365c9..734b4c1c06 100644 --- a/examples/animation/animation_masks.rs +++ b/examples/animation/animation_masks.rs @@ -361,7 +361,7 @@ fn setup_animation_graph_once_loaded( .from_asset("models/animated/Fox.glb"), ); let mask = if animation_index == 0 { 0 } else { 0x3f }; - animation_graph.add_clip_with_mask(handle, mask, 0.0, blend_node) + animation_graph.add_clip_with_mask(handle, mask, 1.0, blend_node) }); // Create each mask group.