• Runtimes
  • Animation blending with 3.6 runtime [c]

  • تم التحرير
Related Discussions
...

Hi, I just upgraded our runtime to 3.6.39 (actually i have no idea what the old version of the runtime was... is there any cpp/h file to check this?) and most things work fine. What changed is the animation blending as far as i have seen (Set + AddAnimation Behaviour bugged?) and i am not sure what is the best way to fix this. Our setup untill now was to play the movement animation on track 0, weapon change animations (the weapons "build" themselves together) on track 1, weapon attack animations (e.g. a rotating gatling) on track 2 and a weapon effect on bullet creation on track 3 (e.g. when the bullet is actually created) (e.g. https://twitter.com/botlikeGame/status/948670303252635650). This worked fine untill now but with the changes in blending the actor gets stuck if any of those animations also changed the upper body (e.g. a small upper body "shake" if the weapon is selected). Even if the animation is done the keys seem to affect the pose. Now I am looking what is the best way to fix this, untill now our logic was that an animation changes something and the animation then stays in that state (e.g. weapon select) is there an easy way to get the old behaviour back? The suggested fix for 3.5 does not seem to apply to 3.6 or am I missing something?

Edit: Additionally, if iI want to mix into an animation from en empty (or finished) timeline, I could set an empty animation and add the actual one. Now the empty animation mixes in the setup pose how is this case now handled?

foofel wrote

with the changes in blending the actor gets stuck if any of those animations also changed the upper body

Can you better explain or show what this means?

foofel wrote

Even if the animation is done the keys seem to affect the pose

It could be the animation is still playing on the track. Set TrackEntry trackEnd to Animation duration for (at least some of) the old behavior. More info here:
Reset Track animation

foofel wrote

if iI want to mix into an animation from en empty (or finished) timeline

You can continue applying the old animation, then mix to the new animation.

Nate wrote
foofel wrote

with the changes in blending the actor gets stuck if any of those animations also changed the upper body

Can you better explain or show what this means?

foofel wrote

Even if the animation is done the keys seem to affect the pose

It could be the animation is still playing on the track. Set TrackEntry trackEnd to Animation duration for (at least some of) the old behavior. More info here:
Reset Track animation: p44268

This is actally the same. Before if the animation finished it did not affect the other tracks anymore. Now it stays on the track untill cleared. With your suggestion of clearing the track I get the old behavior back, thanks.

Nate wrote
foofel wrote

if iI want to mix into an animation from en empty (or finished) timeline

You can continue applying the old animation, then mix to the new animation.

You are right, just not clearing works!

Sadly I have another problem. We have some aim logic where a bone is rotated to point to a target location, this worked (and still works) but only if there is no scale involved. The problem is that spBone_getWorldScaleX is always positive, even if the actual bone is flipped somewhere in the hierarchy using scale. That way the calculated rotation is wrong, is there an easy fix? And why is the world scale always positive?

Glad that helped! :happy:

There isn't an easy fix for world scale always being positive, unfortunately. World scale is computed from the "local to world" matrix using Math.sqrt(a * a + c * c). A negative square root isn't possible by definition: if x is the square root, consider -x * -x results in a positive. That's the math, but the reason for it is that negative world scale is ambiguous. Is world scaleX = -1, or has the bone been rotated 180 degrees and world scaleY = -1? Both produce the same result.

I know this is super annoying and it has made for some... interesting :bang: challenges in Spine itself. If you are just flipping the character to face left/right, you can keep track of that (or look at the local scale of the bone you are flipping) and adjust your rotation calculation appropriately.

Thanks for the explanation! We use flipping for the general "view direction" but some models still have negatively scaled bones (sadly...). As I just realized this also affects the bounding box generation from attachements :/ ( we are generating box2d shapes that follow the bones to generate hitboxes for large objects). What would be the best way to solve this? In previous versions there seemd to be an worldSignX, is that gone? And how does the editor handle this? It is shown correctly there. I could probably walk up the bone hierarchy and check for local scale but is that the best/only way?

What I ultimately want is the world scale/rotation/position. We are not using shear. Maybe matrix decomposition with a logic for flipping also works?

Edit:
As I do not care why a specific state was reached (e.g. world flip vs. rotate & scale) decomposition seems to work quite well.

auto decomposeScale = [](spBone* bone) -> glm::vec2
{
   auto E = (bone->a + bone->d) / 2;
   auto F = (bone->a - bone->d) / 2;
   auto G = (bone->c + bone->b) / 2;
   auto H = (bone->c - bone->b) / 2;
   auto Q = sqrt(E*E + H*H);
   auto R = sqrt(F*F + G*G);
   auto sx = Q + R;
   auto sy = Q - R;
   return glm::vec2{ sx, sy };
};

Still I am wondering if this is the best way? 🙂

If you only care about flipping for view direction, you can track the direction (or look at the root bone scale) and if flipped, adjust your math.

Matrix decomposition has the same problem. You say you don't care how the state was reached but if you do care about the sign of the world scale X, it is impossible to know. Eg, if decomp tells you it's negative, it could actually be rotation and negative scaleY. If decomp tells you it's positive, it could actually be a negative scaleX.

There was worldSignX, but it wasn't terribly useful. What it did was multiple the signs of the local scales up the hierarchy to the root.

Bounding boxes are a problem with flipping in general, because IIRC box2d doesn't allow them to be flipped. I think the general solution is to have two sets of bounding boxes. It's been a while though, someone please correct me if that is wrong. Another possible workaround is to actually use 3D physics, then you can achieve a "flip" of the physics bodies using a 180 rotation on the Y axis.

Nate wrote

Matrix decomposition has the same problem. You say you don't care how the state was reached but if you do care about the sign of the world scale X, it is impossible to know. Eg, if decomp tells you it's negative, it could actually be rotation and negative scaleY. If decomp tells you it's positive, it could actually be a negative scaleX.

That is true but the endresult is the same isn't it? e.g. rotating something -PI or +PI is different but both show the same end result. So even if it rotated and then scaled on Y, it looks the same as the simple scale on X doesn't it?

Nate wrote

Bounding boxes are a problem with flipping in general, because IIRC box2d doesn't allow them to be flipped. I think the general solution is to have two sets of bounding boxes. It's been a while though, someone please correct me if that is wrong. Another possible workaround is to actually use 3D physics, then you can achieve a "flip" of the physics bodies using a 180 rotation on the Y axis.

Box is quite fast with shape updates. I Simply update the shape with a transformed version. (https://gfycat.com/AfraidObedientFinwhale) One limitation is a point cout <= 8 and convex shapes otherwise we need to start triangulating again and then having two bounding box sets probably makes more sense.

foofel wrote

even if it rotated and then scaled on Y, it looks the same as the simple scale on X doesn't it?

Sure, it just depends if you actually care about the sign itself. Eg, imagine if the Spine editor wanted to show the world scale sign, or if some code was specifically testing is world scale X is negative.