MackeyK24

HUGE Skeleton Animation Problem

Recommended Posts

I have encountered a major issues when doing skeletal animation with dynamic state changing.

 

Scenario: I have player input control coming from game pad to control the player movement... This causes Animation State Changes.. Going from walking to running for example... WITHOUT the enableBlending AND blendingSpeed properties being set on EACH BONE ANIMATION ... you get very SHARP and jerking transitions between animation state. The problem is coming into play when I need to UPDATE the enableBlending and blendingSpeed ON EVERY  animation state change... that way can configure animation timing to interpolate from the last animation to the the one about to be played... So I have to check if the target is a skeleton and loop thru ALL the bones to update the enableBlending and blendingSpeed ... Now I get why we have those properties set on the 'Animation' itself BUT when animating a skeleton as the target we really are setting the SAME blending value on all the bones when transitioning from walk to run animations. This is cause a HUGE performance hit on my xbox ... especially when move TWO fully riggred 65 bone animated characters on the screen.

Now my work around is to MOD the babylon.runtimeAnimatons class to CHECK if enableBlending and blendingSpeed (and loopMode) are specified on the target's metadata, if so use that info... that way I dont have to loop thru all the bones setting blending speed if the code in 'setValue' use the higher lever value IF EXISTS on target.

setValue Code Mod:

var enableBlending = (this._target._skeleton && this._target._skeleton.metadata && this._target._skeleton.metadata.enableBlending) ? this._target._skeleton.metadata.enableBlending : this._animation.enableBlending;

var blendingSpeed = (this._target._skeleton && this._target._skeleton.metadata && this._target._skeleton.metadata.blendingSpeed) ? this._target._skeleton.metadata.blendingSpeed : this._animation.blendingSpeed;

if (enableBlending && this._blendingFactor <= 1.0) {

 ... rest of code ...

}

Now @Deltakosh does not like Unity specific mods to the code but I think this would help ALL folks and not just my unity toolkit...

Either way... I can keep this in my OWN BUILDS of the babylon.js engine and ships MY OWN builds with toolkit 

OR 

I can submit to BabylonJS master

Yo @Deltakosh  Please let me know if this Kool with you (checking for target level blending info) and I will submit... If not, just me know and I will keep in my OWN BUILDS of the engine... No worries wither way, just thought others could benefit from this little mod as well :)

 

 

Share this post


Link to post
Share on other sites

We cannot rely on metadata for sure :)

But I like the idea of having enableBlending and blendingSpeed hosted on the skeleton instead of per bones.

Also as your toolkit is the official unity exporter for babylon.js we cannot ship a custom version of bjs with it.

 

So here is a plan:

- We add enableBlendingOverride and blendingSpeedOverride (and actually to all nodes as well)

- We change the setValue to look for this properties on target and if not present we keep the current behavior

 

Thoughts?

If you like it I'll implement it

Share this post


Link to post
Share on other sites

Thats perfect... same thing i was doing except not on the metadata ... and it keeps us from having to iterate down to each bone animation to set blending speed... can you also do loopMode ... that is another we to iterate all bone animations to set loopmode

Share this post


Link to post
Share on other sites
3 hours ago, Deltakosh said:

Yo @Deltakosh I flipped over to using the new animation Properties override but the BLENDING is not happening... it still just snaps to other animation WITHOUT any blending... I am setting the animationPropertiesOverride... it shows it in console:

 

5a949c2ee7324_ScreenShot2018-02-26at1_42_59PM.thumb.png.690cb00547b2d2d26ef14ac2cfb11806.png

 

But no blending is happening :(

 

Share this post


Link to post
Share on other sites

Yo @Deltakosh  I found the problem:

 

// Blending
let enableBlending = this._target && this._target.animationPropertiesOverride ? this._target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;

let blendingSpeed = this._target && this._target.animationPropertiesOverride ? this._target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;

The 'this._target' is actually the BONE... So we gotta go 'this._target._skeleton'

I fixed it here:

 

// Blending
let enableBlending = (this._target && this._target._skeleton && this._target._skeleton.animationPropertiesOverride) ? this._target._skeleton.animationPropertiesOverride.enableBlending : this._animation.enableBlending;

let blendingSpeed = (this._target && this._target._skeleton && this._target._skeleton.animationPropertiesOverride) ? this._target._skeleton.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;

 

And here:

 

private _getCorrectLoopMode(): number | undefined {
 if (this._target && this._target._skeleton && this._target._skeleton.animationPropertiesOverride) {
   return this._target._skeleton.animationPropertiesOverride.loopMode;
 }

 return this._animation.loopMode;
}

 

I will submit the PR :)

Thanks again bro :)

 

Share this post


Link to post
Share on other sites
10 hours ago, Deltakosh said:

We cannot rely on metadata for sure :)

But I like the idea of having enableBlending and blendingSpeed hosted on the skeleton instead of per bones.

Also as your toolkit is the official unity exporter for babylon.js we cannot ship a custom version of bjs with it.

 

So here is a plan:

- We add enableBlendingOverride and blendingSpeedOverride (and actually to all nodes as well)

- We change the setValue to look for this properties on target and if not present we keep the current behavior

 

Thoughts?

If you like it I'll implement it

 

Yo @Deltakosh I pulled all my code out from custom version... EXCEPT the main reason I started all this skeletal animation stuff... BLENDING TWO OR MORE

skeletal animations together to supper BLEND TREE / BLEND SPACE type behavior ... I needed that info of WHERE to get to the code to do the proper and most performant Bone Matrix Blending.

My custom version was doing that in the RuntimeAnimations.animate function RIGHT AFTER the interpolate and RIGHT BEFORE the setValue...

I called it blendValue...  I still need to do this BUT you say I cant make a custom build of the engine... So I propose to add 'blendValueFunction' to the new animationPropertiesOverride:

 

module BABYLON {
    /**
     * Class used to override all child animations of a given target
     */
    export class AnimationPropertiesOverride {
        /**
         * Gets or sets a value indicating if animation blending must be used
         */
        public enableBlending = false;

        /**
         * Gets or sets the blending speed to use when enableBlending is true
         */
        public blendingSpeed = 0.01;

        /**
         * Gets or sets the default loop mode to use
         */
        public loopMode = Animation.ANIMATIONLOOPMODE_CYCLE;

        /**
         * Gets or sets the blend value function to use
         */
        public blendValueFunction:(runtimeAnimation:BABYLON.RuntimeAnimation, repeatCount:number, loopMode:number, currentValue:any)=>any;
    }
}

 

And use right here in the 'animate' function:

 

// Compute value
var repeatCount = (ratio / range) >> 0;
var currentFrame = returnValue ? from + ratio % range : to;
var currentValue = this._interpolate(currentFrame, repeatCount, loopMode, offsetValue, highLimitValue);

// Blend value
if (this._target && this._target._skeleton && this._target._skeleton.animationPropertiesOverride && this._target._skeleton.animationPropertiesOverride.blendValueFunction && typeof this._target._skeleton.animationPropertiesOverride.blendValueFunction === "function") {
                currentValue = this._target._skeleton.animationPropertiesOverride.blendValueFunction(this, repeatCount, loopMode, currentValue);
}            

// Set value
this.setValue(currentValue);

 

I can then use mu custom blendValueFunction to get the other animations involved in the blending and blend them together based on the Blend Tree threshold and whatever propertees you setup on the Unity Animation Controller as the "Blend Factor" ... Like X and Y movement or speed property that would BLEND one or more animations together.

Please let me know, if its Kool I will PR

That works for me if it works for you :)

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.