Blending limits?

Topics: Developer Forum, Project Management Forum, User Forum
Apr 7, 2007 at 4:22 PM
Is there any limitations on how many blending animations you could have? I am planing to do a face rig, and wonder if there is something I should consider before I start to test things out. I plan to do something similar to Jason Osipia's rig but with bones instead of blendshapes. Is it possible to have an animation for each of these, a smile, a wide mouth, narrow mouth, closed and opened and mix them all together to create loads of expressions? By mixing I mean, to control the amount of blending between the "shapes" from inside a XNA game.

Cheers
Alfons

http://www.jasonosipa.com/JasonOsipa_Main.htm
Coordinator
Apr 7, 2007 at 4:46 PM
This isn't hardcoded into the library since it's a somewhat special case. There are many different ways to mix a lot of animations together. For example, in your case, you want some animations to run only one frame (such as wide mouth) and others to run multiple (such as smiling).

However, I've designed the library so that you can implement such extensions for yourself. I'll post an example of making a controller that blends an arbitrary number of facial expressions in a minute.
Coordinator
Apr 7, 2007 at 4:54 PM
Edited Apr 7, 2007 at 4:58 PM
So this probably isn't the easiest way to do it, but you could implement IAnimationController in your own class to represent an animation controller that blends an arbitrary number of single facial expression animations together. As a disclaimer, I haven't tested this code, and it's just meant to give a hint for one way to approach this problem:

public class FacialExpressionController : GameComponent, IAnimationController
{

#region IAnimationController Members

public event AnimationEventHandler AnimationEnded;
private ModelAnimator faceAnimator;
private long duration;
private List<AnimationController> expressions = new List<AnimationController>();
private List<float> weights = new List<float>();
private long elapsed;
private bool isLooping = false;
private double speedFactor;

public FacialExpressionController(Game game, ModelAnimator faceAnimator)
: base(game)
{
this.faceAnimator = faceAnimator;
}

public void RegisterFacialExpression(AnimationController expression, float weight)
{
expressions.Add(expression);
weights.Add(weight);
duration = Math.Max(duration, expression.Duration);
}

// We will assume that each controller will work for all the bones on the face.
public bool ContainsAnimationTrack(BonePose pose)
{
return faceAnimator.BonePoses.Contains(pose);
}

public long Duration
{
get { return duration; }
}

public long ElapsedTime
{
get
{
return elapsed;
}
set
{
elapsed = value;
}
}

public void GetCurrentBoneTransform(BonePose pose, out Matrix transform)
{
transform = new Matrix();
Matrix current;
for (int i = 0; i < expressions.Count; i++)
{
expressionsi.GetCurrentBoneTransform(pose, out current);
transform += weightsi * current;
}
}

public bool IsLooping
{
get
{
return isLooping;
}
set
{
isLooping = value;
}
}

public double SpeedFactor
{
get
{
return speedFactor;
}
set
{
speedFactor = value;
}
}

public override void Update(GameTime gameTime)
{
elapsed += gameTime.ElapsedGameTime.Ticks;
elapsed %= duration;
base.Update(gameTime);
}

#endregion
}
Coordinator
Apr 7, 2007 at 4:56 PM
Edited Apr 7, 2007 at 5:01 PM
You would then use this just like a normal controller, i.e.

if you have: FacialExpressionController controller


foreach (BonePose p in animator.BonePoses)
p.CurrentController = controller;

Even if you don't find implenting an AnimationController satisfactory for your needs, you can create your own ModelAnimator class, subclass ModelAnimator, or manually set the DefaultTransform on the bone poses each frame. The idea is there are lots of ways to do it with the library.
Apr 9, 2007 at 3:14 PM
Thanks for the help, I will try your solution and work my way from there.

I'm experiencing some problems when trying to split up a fbx file with a XML file. I can't get it to work. Do you know how to split the animation of a FBX file from Maya?

Happy Easter
Alfons

Apr 9, 2007 at 4:25 PM
I fixed it, don't know how but I got it to work with a XML file. I'll keep you posted on the progress.
Apr 9, 2007 at 5:32 PM
I registered 2 expressions. But I get this error on this line "expressionsi.GetCurrentBoneTransform(pose, out current);":

System.Collections.Generic.KeyNotFoundException was unhandled
Message="The given key was not present in the dictionary."
Source="mscorlib"
StackTrace:
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Xclna.Xna.Animation.AnimationChannelCollection.get_Item(String boneName)
at Xclna.Xna.Animation.AnimationController.GetCurrentBoneTransform(BonePose pose, Matrix& transform)
at FacialrigDemo.FacialExpressionController.GetCurrentBoneTransform(BonePose pose, Matrix& transform) in C:\Documents and Settings\Alfons\My Documents\Visual Studio 2005\Projects\FacialrigDemo\FacialrigDemo\FacialExpressionController.cs:line 73
at Xclna.Xna.Animation.BonePose.GetCurrentTransform()
at Xclna.Xna.Animation.BonePoseCollection.CopyAbsoluteTransformsTo(Matrix[] transforms)
at Xclna.Xna.Animation.ModelAnimator.Update(GameTime gameTime)
at Microsoft.Xna.Framework.Game.Update(GameTime gameTime)
at FacialrigDemo.Game1.Update(GameTime gameTime) in C:\Documents and Settings\Alfons\My Documents\Visual Studio 2005\Projects\FacialrigDemo\FacialrigDemo\Game1.cs:line 184
at Microsoft.Xna.Framework.Game.Run()
at FacialrigDemo.Program.Main(String[] args) in C:\Documents and Settings\Alfons\My Documents\Visual Studio 2005\Projects\FacialrigDemo\FacialrigDemo\Program.cs:line 14


Coordinator
Apr 9, 2007 at 9:20 PM
I doubt that code works as is - I just hacked it together without using a compiler as prototype code. I was just trying to get you started.

This example assumes that all your animations affect all bones, so that's why it isn't working. You'll need to add checks to make sure that all the expressions called in GetCurrentBoneTransform(pose, out current) contains the bone.