Hi, all
During the development of the last game (http://www.stargamm.com/?
p=34), I used animated models for my characters. I needed to use more
than one animation to the model at the same time.
I want to discuss a solution that I found.
I am sure that my decision is not optimal and I present it as an
occasion to discuss this issue.

Here I try to explain the principle, skipping standard code for
creation scene, etc.

For convenience, I need the class <strong>CharacterAnimation</strong>,
in which we will post the entire functionality for working with the
animation model.
<pre>
public class CharacterAnimation
{
        // current frame of the animation
        private var animationTime:Number;
        // our model
        private var animationSrc:ObjectContainer3D;
        // actual animation
        private var animation:BonesAnimator;
        // array of bones, movement of which we need to mix
        private var blendBoneList:Array=[];
        // array for storing bones transform.matrix3D
        private var blendCurrentState:Array=[];
        private var blendFinState:Array=[];

        private var isBlend:Boolean=false;
        private var blendPercent:Number=0.5;
        private var fps:Number=25.2;
        private var startFrame:int;
        private var stopFrame:int;
        private var loop:Boolean;

        public function CharacterAnimation(animationSrc:ObjectContainer3D,
startFrame:int, stopFrame:int, loop:Boolean=true,
isBlend:Boolean=false )
        {
                this.animationSrc=animationSrc;
                this.startFrame=startFrame;
                this.stopFrame=stopFrame;
                this.loop=loop;
                this.isBlend = isBlend;

                // use default animation
                this.animation =
this.animationSrc.animationLibrary.getAnimation("default").animation
as BonesAnimator;
                animation.loop=this.loop;
                animationTime.time = startFrame;
        }

        // This function must be called before scene render
        public function sync():void
        {
                // increment animation frame
                animationTime +=1;

                if (animationTime &gt;= stopFrame)
                {
                        if(this.loop)
                                animationTime = startFrame;
                        else
                        {
                                // stop();
                                return;
                        }
                }

                // calc the time for the current frame
                var ts:Number=animationTime /fps;

                // The usual animation, do not blend movement
                if(!isBlend)
                        animation.update(ts,false);
                else
                {
                        // trying to blend a movement of the bones

                        // reset variables
                        blendBoneList=[];
                        blendCurrentState=[];
                        blendFinState=[];

                        // in an array blendCurrentState put current 
transformation matrix
of bones
                        
getBlendBonesState(animationSrc,blendBoneList,blendCurrentState);
                        // play the current frame of animation, after the 
method call
transformation matrix changed)
                        animation.update(ts,false);
                        // in an array blendFinState put current transformation 
matrix of
bones
                        getBlendBonesState(animationSrc,null,blendFinState);
                        // blend movement
                        blendPercent=0.5;
                        setBlendState();
                }

        }

        // method sets the transformation matrix of bone as the interpolation
of two matrices
        private function setBlendState():void
        {
                // loop through bones
                for(var i:int=0;i&lt; blendBoneList.length;i++)
                {
                        var b:Bone=animationSrc.getBoneByName(blendBoneList[i]);
                        if(b==null) continue;
                        // set the transformation matrix of bone
                        b.transform.matrix3D=Matrix3D.interpolate(
                                        Matrix3D(blendCurrentState[i]),
                                        Matrix3D(blendFinState[i]),
                                        blendPercent);
                }

                // here should be update of skinControllers and  skinVertices 
of the
model,
                // ie part of the  BonesAnimator.update ().
                // In my case I had override this method,
                // here I will cite only the  part of the BonesAnimator.update 
()
method

                                //update skincontrollers
                                for each (_skinController in _skinControllers)
                                _skinController.update();

                                //update skinvertices
                                for each (_skinVertex in _skinVertices)
                                _skinVertex.update();

        }

        // method fills an array of bone transformation matrix model.
        private function
getBlendBonesState(src:ObjectContainer3D,boneList:Array,stateList:Array):void
        {
                for each(var ch:Object3D in src.children)
                {
                        if(ch is Bone)
                        {
                                var b:Bone=ch as Bone;
                                if(boneList!=null)
                                        boneList.push(b.name);
                                stateList.push(b.transform.matrix3D);
                        }
                        if(ch is ObjectContainer3D || ch is Bone)
                                getBlendBonesState((ch as 
ObjectContainer3D),boneList,stateList);
                }

        }
}
</pre>
My model and its animation are stored in the file “model.dae”. I load
it from an embedded resource and put on the scene.
<pre>
[Embed(source="//..//assets//models//test//
model.dae",mimeType="application/octet-stream")]
public static  var actorModelSrc:Class;
public var model:ObjectContainer3D;

var loader:Collada=new Collada();
model=loader.parseGeometry(new actorModelSrc()) as ObjectContainer3D;

// create two instances of CharacterAnimation
// move forward animation
walkForward=new CharacterAnimation(this.parent, model, 1, 30, true,
false);
// some movement of hand animation
handMotion =new CharacterAnimation(this.parent, model, 34, 50, true,
true);</pre>
We need to update walkForward and handMotion before render scene and
in strict  sequence.
<pre>
//  enter frame
private function enterFrame(e:Event):void
{
        …

        walkForward.sync();
        handMotion.sync();
        …
        scene.render();
}</pre>

As a result I have "hand movement" mixed with "walk forward" movement.

Reply via email to