godot: AnimationTree: Add2 in BlendTree does not seem to be additive

Godot version: 3.2 df876601c8

OS/device including version: Manjaro Linux

Issue description: I was building a blendtree expecting to see the pose of my root bone to be added together. This node seems to blend between two poses rather than produce a sum of poses.

Steps to reproduce: I have a jumping animation and a running animation both with the root bone controlling the motion. As in the attached video, you can see that the forward motion is reduced as the jump is increased.

Is this the expected result? Am I doing something wrong?

I read the documentation and expected this node to produce additive results.

Example: https://www.youtube.com/watch?v=bkDDoQMfCoc

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 9
  • Comments: 33 (12 by maintainers)

Most upvoted comments

Of course it is far from good, but it can help with something.

cc @reduz, as he implemented the animation state machine.

https://github.com/godotengine/godot/blob/50582446ad13a7ce034bdd8695409bf26c1abac3/scene/animation/animation_tree.h#L70-L73

...
                const Vector<float> *track_blends; 
		float blend;
		bool seeked;
		bool add_directly;
...

https://github.com/godotengine/godot/blob/50582446ad13a7ce034bdd8695409bf26c1abac3/scene/animation/animation_tree.h#L98-L99

        HashMap<NodePath, bool> filter;
        bool filter_enabled;
        bool add_directly;

https://github.com/godotengine/godot/blob/50582446ad13a7ce034bdd8695409bf26c1abac3/scene/animation/animation_tree.cpp#L116-L119

        anim_state.animation = animation;
	anim_state.seeked = p_seeked;
	anim_state.add_directly = add_directly;

	if (add_directly) add_directly = !add_directly;

	state->animation_states.push_back(anim_state);

https://github.com/godotengine/godot/blob/50582446ad13a7ce034bdd8695409bf26c1abac3/scene/animation/animation_tree.cpp#L958-L970

        if (err != OK)
	        continue;

	if (!as.add_directly) {
	        t->loc = t->loc.linear_interpolate(loc, blend);
	        if (t->rot_blend_accum == 0) {
		        t->rot = rot;
		        t->rot_blend_accum = blend;
	        } else {
		       float rot_total = t->rot_blend_accum + blend;
		        t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
		        t->rot_blend_accum = rot_total;
	       }
		t->scale = t->scale.linear_interpolate(scale, blend);
	} else {
		t->loc += (loc)*blend;
		t->scale = t->scale.linear_interpolate(scale, blend);
		Quat q = Quat().slerp(rot.normalized(), blend).normalized();
		t->rot = (t->rot*q).normalized();
	}

I added a new blend_input_add function in “animation_tree.cpp”

float AnimationNode::blend_input_add(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
	float ret = blend_input(p_input, p_time, p_seek,p_blend, p_filter,p_optimize);
	if (ret != 0) {
		if (parent) {
			AnimationNodeBlendTree *blend_tree = Object::cast_to<AnimationNodeBlendTree>(parent);
			ERR_FAIL_COND_V(!blend_tree, 0);

			StringName node_name = connections[1];

			if (blend_tree->has_node(node_name)) {
				Ref<AnimationNode> node = blend_tree->get_node(node_name);
				node->add_directly = true;
			}
		}
	}
	
	return ret;
}

https://github.com/godotengine/godot/blob/50582446ad13a7ce034bdd8695409bf26c1abac3/scene/animation/animation_blend_tree.cpp#L406-L413

float AnimationNodeAdd2::process(float p_time, bool p_seek) {

	float amount = get_parameter(add_amount);
	float rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
	blend_input_add(1, p_time, p_seek, amount, FILTER_PASS, !sync);

	return rem0;
}

Is this getting fixed anytime soon?

Closed by #57675.

Is a fix for 3.x planned? I feel this is important enough to warrant a 3.x backport, considering how long this issue was open for.

This is useful thanks for this.

I think the final solution for this will look a bit different but this is a good boost in the right direction.

Yeah there are ways around this but I find without this node that my animation workload increases significantly without it. I’m mostly struggling with the activity map and this COW array for the blend data. There has to be a way to combine two tracks in an additive method. I’m busy for today but might have some time tonight to keep cracking at it.

I’m also not a core dev so I hope I can slap something together that’s half decent tonight, but no guarantees.

I am hoping that Juan sees this at some point though, because he wrote that file and hasn’t changed it much as well as it lacks enough comments for me to understand it quickly. I imagine he might be able to whip this node up pretty quick.

@jedStevens It would be great. I really need this. Thanks for helping.

I modified the source code of the existing nodes Add2 and Add3 and managed to make them work as in blender. But I don’t think it should be a good thing to do that. But, for my purposes, I think it will be enough. I can show it later so you can see if it has anything useful.