Jump to content

Will there ever be animation blending or transitions ? Would be great to have that breaking change :D


Recommended Posts

That demo is using a "hacked" version of BabylonJS.

https://dl.dropboxusercontent.com/u/208774/babylon.js

Check out the Scene.beginAnimation function that has a weightAtFrame param:

Scene.prototype.beginAnimation = function (target, from, to, loop, speedRatio, onAnimationEnd, animatable, weightAtFrame) {
            if (speedRatio === undefined) {
                speedRatio = 1.0;
            }
            // this.stopAnimation(target);
            if (!animatable) {
                animatable = new BABYLON.Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd, null, weightAtFrame);
            }
            // Local animations
            if (target.animations) {
                animatable.appendAnimations(target, target.animations);
            }
            // Children animations
            if (target.getAnimatables) {
                var animatables = target.getAnimatables();
                for (var index = 0; index < animatables.length; index++) {
                    this.beginAnimation(animatables[index], from, to, loop, speedRatio, onAnimationEnd, animatable, weightAtFrame);
                }
            }
            return animatable;
        };

 

and Animatable:

 

var Animatable = (function () {
        function Animatable(scene, target, fromFrame, toFrame, loopAnimation, speedRatio, onAnimationEnd, animations, weightAtFrame) {
            if (fromFrame === void 0) { fromFrame = 0; }
            if (toFrame === void 0) { toFrame = 100; }
            if (loopAnimation === void 0) { loopAnimation = false; }
            if (speedRatio === void 0) { speedRatio = 1.0; }
            this.target = target;
            this.fromFrame = fromFrame;
            this.toFrame = toFrame;
            this.loopAnimation = loopAnimation;
            this.speedRatio = speedRatio;
            this.onAnimationEnd = onAnimationEnd;
            this.weightAtFrame = weightAtFrame;
            this._animations = new Array();
            this._paused = false;
            this.animationStarted = false;
            if (animations) {
                this.appendAnimations(target, animations);
            }
            this._scene = scene;
            scene._activeAnimatables.push(this);
        }
        // Methods
        Animatable.prototype.appendAnimations = function (target, animations) {
            for (var index = 0; index < animations.length; index++) {
                var animation = animations[index];
                animation._target = target;
                if (this.weightAtFrame != null) {
                    animation.weightFunction = this.weightAtFrame;
                }
                this._animations.push(animation);
            }
        };
        Animatable.prototype.getAnimationByTargetProperty = function (property) {
            var animations = this._animations;
            for (var index = 0; index < animations.length; index++) {
                if (animations[index].targetProperty === property) {
                    return animations[index];
                }
            }
            return null;
        };
        Animatable.prototype.pause = function () {
            if (this._paused) {
                return;
            }
            this._paused = true;
        };
        Animatable.prototype.restart = function () {
            this._paused = false;
        };
        Animatable.prototype.stop = function () {
            var index = this._scene._activeAnimatables.indexOf(this);
            if (index > -1) {
                this._scene._activeAnimatables.splice(index, 1);
            }
            if (this.onAnimationEnd) {
                this.onAnimationEnd();
            }
        };
        Animatable.prototype._animate = function (delay, cache) {
            if (this._paused) {
                if (!this._pausedDelay) {
                    this._pausedDelay = delay;
                }
                return true;
            }
            if (!this._localDelayOffset) {
                this._localDelayOffset = delay;
            }
            else if (this._pausedDelay) {
                this._localDelayOffset += delay - this._pausedDelay;
                this._pausedDelay = null;
            }
            // Animating
            var running = false;
            var animations = this._animations;
            for (var index = 0; index < animations.length; index++) {
                var animation = animations[index];
                var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio, cache);
                running = running || isRunning;
            }
            if (!running) {
                // Remove from active animatables
                index = this._scene._activeAnimatables.indexOf(this);
                this._scene._activeAnimatables.splice(index, 1);
            }
            if (!running && this.onAnimationEnd) {
                this.onAnimationEnd();
            }
            return running;
        };
        return Animatable;
    })();
    BABYLON.Animatable = Animatable;

 

That looks like a good starting point for blending animations.

 

Link to post
Share on other sites
On 2/21/2016 at 4:58 PM, adam said:

That demo is using a "hacked" version of BabylonJS.

https://dl.dropboxusercontent.com/u/208774/babylon.js

Check out the Scene.beginAnimation function that has a weightAtFrame param:


Scene.prototype.beginAnimation = function (target, from, to, loop, speedRatio, onAnimationEnd, animatable, weightAtFrame) {
            if (speedRatio === undefined) {
                speedRatio = 1.0;
            }
            // this.stopAnimation(target);
            if (!animatable) {
                animatable = new BABYLON.Animatable(this, target, from, to, loop, speedRatio, onAnimationEnd, null, weightAtFrame);
            }
            // Local animations
            if (target.animations) {
                animatable.appendAnimations(target, target.animations);
            }
            // Children animations
            if (target.getAnimatables) {
                var animatables = target.getAnimatables();
                for (var index = 0; index < animatables.length; index++) {
                    this.beginAnimation(animatables[index], from, to, loop, speedRatio, onAnimationEnd, animatable, weightAtFrame);
                }
            }
            return animatable;
        };

 

and Animatable:

 


var Animatable = (function () {
        function Animatable(scene, target, fromFrame, toFrame, loopAnimation, speedRatio, onAnimationEnd, animations, weightAtFrame) {
            if (fromFrame === void 0) { fromFrame = 0; }
            if (toFrame === void 0) { toFrame = 100; }
            if (loopAnimation === void 0) { loopAnimation = false; }
            if (speedRatio === void 0) { speedRatio = 1.0; }
            this.target = target;
            this.fromFrame = fromFrame;
            this.toFrame = toFrame;
            this.loopAnimation = loopAnimation;
            this.speedRatio = speedRatio;
            this.onAnimationEnd = onAnimationEnd;
            this.weightAtFrame = weightAtFrame;
            this._animations = new Array();
            this._paused = false;
            this.animationStarted = false;
            if (animations) {
                this.appendAnimations(target, animations);
            }
            this._scene = scene;
            scene._activeAnimatables.push(this);
        }
        // Methods
        Animatable.prototype.appendAnimations = function (target, animations) {
            for (var index = 0; index < animations.length; index++) {
                var animation = animations[index];
                animation._target = target;
                if (this.weightAtFrame != null) {
                    animation.weightFunction = this.weightAtFrame;
                }
                this._animations.push(animation);
            }
        };
        Animatable.prototype.getAnimationByTargetProperty = function (property) {
            var animations = this._animations;
            for (var index = 0; index < animations.length; index++) {
                if (animations[index].targetProperty === property) {
                    return animations[index];
                }
            }
            return null;
        };
        Animatable.prototype.pause = function () {
            if (this._paused) {
                return;
            }
            this._paused = true;
        };
        Animatable.prototype.restart = function () {
            this._paused = false;
        };
        Animatable.prototype.stop = function () {
            var index = this._scene._activeAnimatables.indexOf(this);
            if (index > -1) {
                this._scene._activeAnimatables.splice(index, 1);
            }
            if (this.onAnimationEnd) {
                this.onAnimationEnd();
            }
        };
        Animatable.prototype._animate = function (delay, cache) {
            if (this._paused) {
                if (!this._pausedDelay) {
                    this._pausedDelay = delay;
                }
                return true;
            }
            if (!this._localDelayOffset) {
                this._localDelayOffset = delay;
            }
            else if (this._pausedDelay) {
                this._localDelayOffset += delay - this._pausedDelay;
                this._pausedDelay = null;
            }
            // Animating
            var running = false;
            var animations = this._animations;
            for (var index = 0; index < animations.length; index++) {
                var animation = animations[index];
                var isRunning = animation.animate(delay - this._localDelayOffset, this.fromFrame, this.toFrame, this.loopAnimation, this.speedRatio, cache);
                running = running || isRunning;
            }
            if (!running) {
                // Remove from active animatables
                index = this._scene._activeAnimatables.indexOf(this);
                this._scene._activeAnimatables.splice(index, 1);
            }
            if (!running && this.onAnimationEnd) {
                this.onAnimationEnd();
            }
            return running;
        };
        return Animatable;
    })();
    BABYLON.Animatable = Animatable;

 

That looks like a good starting point for blending animations.

 

Thaks for all  stuff & wisdom  you've sent me,,,, I've been trying your experimentation earlier but didnt know that there was modified babylon.js file.... I am gonna loook into it much deeper........... loooks like you really did skeletal animation blending,, ,,

Link to post
Share on other sites
23 hours ago, adam said:

That wasn't my code.  I found that in a demo in some other thread.

Ok,,, so ,,,, i used that hacked version its version 2.1beta which is hacked..........

I looked into it and did easingIN  function,,,,,,,,it works great, !,, i think its very great solution for blending  skeletal animations,,,,,,,,,, so what I am trying to do,, ,is ......... that I have implemented this into the latest version of babylon 2.4alpha...

 

conclusion for now --- > everythings works great,, but,,...."?"......  one thing i am missing is   that somehow i cant figure out why _activeAnimations for my specific target won't have more that 1 animatabale,,, I've also disabled animation stop on beginning of animation.........          I will let U know if I will finish this for 2.4a........... or I will do some extension code for latest version..

..................... working on .....  please stand by......

 

 

this is solved for now.... blending works !! but will need to dynamically change speed of animation

Link to post
Share on other sites
  • 2 weeks later...

As I'm so keen to use this feature I copied RalphEL's code onto my own fork (a week is a long time :P) The blending works really well :) 

I was going to try doing a pull request to get it into babylon as RalphEL doesn't seem to have had time to fix the issue you mentioned above, but noticed my pull request would look exactly like his commit (with a tiny bit of formatting). So, being new to github, what is needed to resolve the 159 file issue? :) 

Link to post
Share on other sites

@RalphEl - I really like the scene you built for both the animation as well as the behaviors. I would recommend posting as a babylon.js demo, and If you have a chance to improve the aesthetics a bit, then it would be something to showcase.

I hope newbies to game develoment look at such scenes and understand the code driving them - but also understand all of the preparation required to sucessfully blend character animation for a character driven game - such as move trees. If there are users on this forum who don't understand move trees, then it might be worth a seperate post and discussion. I would like to know what users are currently using to solve this piece of development, which is what software they use to build their move trees and are there blending tools in these applications.

Cheers,

DB

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.

×
×
  • Create New...