Showing posts with label Technical Animation. Show all posts
Showing posts with label Technical Animation. Show all posts

Monday, September 21, 2015

Creating Non-Repetitive Randomized Idle Using Animation Blending

You might have seen that the standing idle animations in video games are some kind of a magical movement. They never get repetitive. The character is looking at different directions with a non-repetitive pattern. He/she shows different facial animations or shifts his/her weight randomly and does many other usual acts in a standing idle animation.

These kind of animations can be implemented using an animation blend tree and a component which can manipulate animation weights. This post is going to show how a non-repetitive idle animation can be created.

Defining Animation Blend Tree for Idle Animation

In this section, I'm going to define an animation blend tree which can bring a range of possible animations for idle. Before creating a blend tree,  the animations which are used within are described here:

1- A simple breathing idle animation which is just 70 frames (2.33 second).

2- A left weight shift animation similar to the original idle animation while having the pelvis shifted to left and with a more curvy torso. "Similar" here, means that the animations have same timings and almost same poses but just with a difference in main poses. This difference shows the weight shift left pose. I created the weight shift animation just by adding an additive keyframe to different bones on top of the original idle animation in the DCC tool.

3- A right weight shift animation similar to the original idle animation while having the pelvis shifted to right and with a more curvy torso.

4- Four different look animations. Look left, right, up and down. These 4 are all one frame additive animations. Their transforms are subtracted from the first frame of the original idle animation.

5- Two different facial and simple body movement animations. These two animations are additive as well. They are adding some facial animations to the original idle animation and some movement over torso and hands.

So the required animations are described. Now let's define a scenario for blend tree in three steps before creating it:

1- We want the character to stand using an idle animation while often shifting his/her weight. So first we have to create a blend node which can blend between, left weight shift, basic idle and right weight shift.

2- The character wants to look around often and we have four different additive look animations for this. So first we create a blend node which can blend between 4 additive look animations. It works with two parameters. One parameter is mapped to blend between look left and right and one parameter is mapped to blend between look up and down. This blend node is going to be added to the blend node defined in step 1.

3- After adding head look animations, the two additive facial animations are going to be added to the result. These two animations are switching randomly when they are reaching at their final frame.

So a blend tree which is capable of supporting this scenario is shown here:



Idle Animation Controller to Manipulate Blend Weights

So far an animation blend tree is created which can create continuous motions with some simple additive and idle animations. Now we have to manipulate the blend weights to create a non-repetitive idle animation. This would be an easy task. I'm going to define it in four steps to obtain a non-repetitive weight shift animation. These steps can be used for facial and look animations as well:

1- First, we randomly select a target weight for the weight shift. It should be in the range of defined weight shift parameter used in blend tree.

2- I define a random blend speed which makes the character to shift weight through time until it reaches the selected target weight in step 1. The blend speed is randomly selected from a reasonable numeric range.

3- When we reach the target blend weight for weight shift, the character should remain in that blend weight for a while. That's completely like what humans do in reality. When a human stands, he/she shifts his/her weight to left or right and stay in that pose for a while. Shifting weight, helps human body to relax the spine muscles. So we select a random time from a reasonable range to set the weight shift remaining time.

4- After the selected weight shifting time ends, we get back to step 1 and this loop repeats while the character is in idle state.

The same 4 steps goes for the directional look and facial animations as well.

This random time, speed and target weight selection, creates a non-repetitive idle animation. The character always look at different directions with different times while shifting his weight to left or right and do different facial and body movement animations. All are done with different and random time, speed and poses.


You can check the result here in this video:




Here is the source code I wrote for the idle animation controller. The system is implemented in Unreal Engine 4. This component calculates the blend weights and pass them to the animation blend tree:


The header file:

 
   
 #pragma once  
   
 #include "Components/ActorComponent.h"  
 #include "ComponenetIdleRandomizer.generated.h"  
   
   
 UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )  
 class RANDOMIZEDIDLE_API UComponenetIdleRandomizer : public UActorComponent  
 {  
      GENERATED_BODY()  
   
 public:       
      UComponenetIdleRandomizer();  
   
      // Called every frame  
      virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;  
   
   
 public:  
      /*Value to be used for weight shift blend*/  
      UPROPERTY(BluePrintReadOnly)  
      float mCurrentWeightShift;  
   
      /*Value to be used for idle look blend*/  
      UPROPERTY(BluePrintReadOnly)  
      FVector2D mCurrentHeadDir;  
   
      /*Value to be used for idle facial blend*/  
      UPROPERTY(BluePrintReadOnly)  
      float mCurrentFacial;  
   
      FVector2D mTargetHeadDir;  
   
      float mTargetWeightShift;  
   
      float mTargetFacial;  
   
 protected:  
   
      float mWSTransitionTime;  
   
      float mWSTime;  
   
      float mWSCurrentTime;  
   
      float mLookTransitionTime;  
   
      float mLookTime;  
   
      float mLookCurrentTime;  
   
      float mFacialTransitionTime;  
   
      float mFacialTime;  
   
      float mFacialCurrentTime;  
   
 private:  
      float mLookTransitionSpeed;  
   
      float mWSTransitionSpeed;  
   
      float mFacialTransitionSpeed;  
   
        
 };  
   


And The CPP Here:


 #include "RandomizedIdle.h"  
 #include "ComponenetIdleRandomizer.h"  
   
   
 /******************************************************/  
 UComponenetIdleRandomizer::UComponenetIdleRandomizer()  
 {  
      // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features  
      // off to improve performance if you don't need them.  
      bWantsBeginPlay = true;  
      PrimaryComponentTick.bCanEverTick = true;  
   
      // ...  
      //weight shift initialization  
      mTargetWeightShift = FMath::RandRange(-100, 100) * 0.01f;  
      mCurrentWeightShift = 0;  
      mWSTransitionTime = FMath::RandRange(10, 20) * 0.1f;  
      mWSTime = FMath::RandRange(20, 50) * 0.1f;  
      mWSCurrentTime = 0;  
      mWSTransitionSpeed = mTargetWeightShift / mWSTransitionTime;  
   
      //look initialization  
      mTargetHeadDir.X = FMath::RandRange(-80, 80) * 0.01f;  
      mTargetHeadDir.Y = FMath::RandRange(-15, 15) * 0.01f;  
      mCurrentHeadDir = FVector2D::ZeroVector;  
      mLookTransitionTime = FMath::RandRange(10, 20) * 0.1f;  
      mLookTime = FMath::RandRange(20, 40) * 0.1f;  
      mLookCurrentTime = 0.f;  
      mLookTransitionSpeed = mTargetHeadDir.Size() / mLookTransitionTime;  
   
      //facial initialization  
      mTargetFacial = FMath::RandRange(0, 100.f) * 0.01f;  
      mCurrentFacial = 0.f;  
      mFacialTransitionTime = FMath::RandRange(20, 50) * 0.1f;  
      mFacialTime = FMath::RandRange(20.f, 40.f) * 0.1f;  
      mFacialCurrentTime = 0.f;  
      mFacialTransitionSpeed = mTargetFacial / mFacialTransitionTime;  
 }  
   
   
 /**********************************************************************************************************************************/  
 void UComponenetIdleRandomizer::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )  
 {  
      Super::TickComponent( DeltaTime, TickType, ThisTickFunction );  
   
      /*look weight calculations*/  
      if (mLookCurrentTime > mLookTransitionTime + mLookTime)  
      {  
           mLookTime = FMath::RandRange(20, 40) * 0.1f;  
           mLookTransitionTime = FMath::RandRange(20, 40) * 0.1f;  
           mLookCurrentTime = 0;  
           mTargetHeadDir.X = FMath::RandRange(-80, 80) * 0.01f;  
           mTargetHeadDir.Y = FMath::RandRange(-15, 15) * 0.01f;  
           mLookTransitionSpeed = (mTargetHeadDir - mCurrentHeadDir).Size() / mLookTransitionTime;  
      }  
   
      mCurrentHeadDir += mLookTransitionSpeed * (mTargetHeadDir - mCurrentHeadDir).GetSafeNormal() * DeltaTime;  
if (mLookCurrentTime > mLookTransitionTime) { /*Damping*/ float lTransitionSpeedSign = FMath::Sign(mLookTransitionSpeed); mLookTransitionSpeed = mLookTransitionSpeed - lTransitionSpeedSign * 2.0f * DeltaTime;
if (lTransitionSpeedSign * FMath::Sign(mLookTransitionSpeed) == -1) { mLookTransitionSpeed = 0.f; } if (FMath::Abs(mCurrentHeadDir.X) > 0.9f) { mCurrentHeadDir.X = FMath::Sign(mCurrentHeadDir.X) * 0.9f; } if (FMath::Abs(mCurrentHeadDir.Y) > 0.2f) { mCurrentHeadDir.Y = FMath::Sign(mCurrentHeadDir.Y) * 0.2f; } } mLookCurrentTime += DeltaTime; /*weight shift calculations*/ if (mWSCurrentTime > mWSTransitionTime + mWSTime) { mWSTime = FMath::RandRange(20.f, 50.f) * 0.1f; mWSTransitionTime = FMath::RandRange(30.f, 50.f) * 0.1f; mWSCurrentTime = 0; mTargetWeightShift = FMath::RandRange(-80.f, 80.f) * 0.01f; mWSTransitionSpeed = (mTargetWeightShift - mCurrentWeightShift) / mWSTransitionTime; } mCurrentWeightShift += mWSTransitionSpeed * DeltaTime; if (mWSCurrentTime > mWSTransitionTime) { /*Damping*/ float lTransitionSpeedSign = FMath::Sign(mWSTransitionSpeed); mWSTransitionSpeed = mWSTransitionSpeed - lTransitionSpeedSign * 2.0f * DeltaTime;
if (lTransitionSpeedSign * FMath::Sign(mWSTransitionSpeed) == -1.0f) { mWSTransitionSpeed = 0.f; } if (FMath::Abs(mCurrentWeightShift) > 1.0f) { mCurrentWeightShift = FMath::Sign(mCurrentWeightShift); } } mWSCurrentTime += GetWorld()->DeltaTimeSeconds; /*facial calculations*/ if (mFacialCurrentTime > mFacialTransitionTime + mFacialTime) { mFacialTime = FMath::RandRange(20, 50) * 0.1f; mFacialTransitionTime = FMath::RandRange(20, 50) * 0.1f; mFacialCurrentTime = 0; mTargetFacial = FMath::RandRange(0, 100) * 0.01f; mFacialTransitionSpeed = (mTargetFacial - mCurrentFacial) / mFacialTransitionTime; } mCurrentFacial += mFacialTransitionSpeed * DeltaTime;
if (mFacialCurrentTime > mWSTransitionTime) { mCurrentFacial = mTargetFacial; } mFacialCurrentTime += DeltaTime; }

Saturday, February 14, 2015

Skeletal Animation Optimization Tips and Tricks



Introduction


Skeletal animation plays an important role in video games. Recent games are using many characters within. Processing huge amount of animations can be computationally intensive and requires much memory as well so to have multiple characters in a real time scene, optimization is highly needed. There exists many techniques which can be used to optimize skeletal animations. This article tends to address some of these techniques. Some of the techniques addressed here, have plenty of details, so I just try to define them in a general way and introduce references for those who are eager to know the details.

This article is divided into two main sections. The first section is addressing some optimization techniques which can be used within animation systems. The second section is from the perspective of the animation system users and describes some techniques which can be used by users to use the animation system more efficiently. So if you are an animator/technical animator you can read the second section and if you are a programmer and you want to implement an animation system you may read the first section.

This article is not going to talk about mesh skinning optimization and it's just going to talk about skeletal animation optimization techniques. There exists plenty of useful articles about mesh skinning around the web.


1. Skeletal Animation Optimization Techniques


I assumed that most of the audiences of this article know the basics of skeletal animation so I'm not going to talk about the basics here. To start, let's have a definition for a skeleton in character animation. A skeleton is an abstract model of a human or animal body in computer graphics. It is a tree data structure. A tree which its nodes are called bones or joints. Bones are just some containers for transformations. For each skeletal animation, there exists animation tracks. Each track has the transformation info of a specific bone. A track is a sequence of keyframes. A keyframe is transformation of a bone at a specific time. The keyframe time is specified from the beginning of the animation. Usually the keyframes are stored relative to a pose of the bone named binding pose. These animation tracks and skeletal representation can be optimized in different ways. In the following sections, I will introduce some of these techniques. As stated before, the techniques are described generally and this article is not going to describe the details here. Each of which can be described in a separated article.

Optimizing Animation Tracks


An animation consists of animation tracks. Each animation track stores the animation related to one bone. An animation track is a sequence of keyframes where each keyframe contains one of the translation, rotation or scale info. Animation tracks are one thing that can be optimized easily from different aspects. First we have to note that most of the bones in character animations do not have translation. For example we don't need to move fingers or hands. They just need to be rotated. Usually the only bones that need to have translation are the root bone and the props (weapons, shields and so on). The other body organs do not move and they are just being rotated. Also the realistic characters usually do not use scale. Scale is usually applied to cartoony characters. One other thing about the scale is that animators mostly use uniform scale and less non-uniform scale.

So based on these information, we can remove scale and translation keyframes for those animation tracks that do not own these two. The animation tracks can become light weighted and allocate less memory and calculation by removing unnecessary translation and scale keyframes. Also if we use uniform scale, the scale keyframes can just contain one float instead of a Vector3.

Another technique which is very useful for optimization of animation tracks, is animation compression schemes. The most famous one is curve simplification. You may know it as keyframe reduction as well. It reduces the keyframes of an animation track based on a user defined error. With this, the consecutive keyframes which have a little difference can be omitted. The curve simplification should be applied for translation, rotation and scale separately because each of which has their own keyframes and different values. Also their value difference is calculated differently. You may read this paper about curve simplification to find out more about it.

One other thing that can be considered here, is how you store rotation values in the rotation keyframes. Usually the rotations are stored in unit quaternion format because quaternions have some good advantages over Euler Angles. So if you are storing quaternions in your keyframes, you need to store four elements. But in unit quaternions the scalar part can be obtained easily from the vector part. So the quaternions can be stored with just 3 floats instead of four.  See this post from my blog to find out how you can obtain the scalar part from the vector part.


Representation of a Skeleton in Memory


As mentioned in previous sections, a skeleton is a tree data structure. As animation is a dynamic process, the bones may be accessed frequently while the animation is being processed. So a good way is to keep the bones sequentially in the memory. They should not be separated because of the  locality of the references. The sequential allocation of bones in memory can be more cache friendly for CPU.


Using SSE Instructions


To update a character animation, the system has to do lots of calculations. Most of them are based on linear algebra. This means that the most of calculations are with vectors. For example the bones are always being interpolated between two consecutive keyframes. So the system has to LERP between two translations and two scales and SLERP between two quaternion rotations as well. Also there might be animation blending which leads the system to interpolate between two or more different animations based on their weights. LERP and SLERP are calculated with these equations respectively:

LERP(V1, V2, a) = (1-a) * V1 + a * V2
SLERP(Q1, Q2, a) =  sin((1-a)*t)/sin(t) * Q1 + sin(a*t)/sin(t) * Q2

Where 't' is the angle between Q1 and Q2 and 'a' is interpolation factor and it is a normalized value. These two equations are frequently used in keyframe interpolation and animation blending. Using SSE instructions can help you to achieve faster and more efficient results. I highly recommend to see the hkVector4f class from Havok physics/animation SDK as reference. The hkVector4f class is using SSE instructions very well and it's a very well designed class. You can define translation, scale and quaternion similar to hkVector4f class.

You have to note that if you are using SSE instructions, then your objects which is using it, have to be memory aligned otherwise you will run into traps and exceptions. Also you should consider your target platform and see that how it supports these kind of instructions.


Multithreading the Animation Pipeline


Imagine you have a crowded scene full of NPCs in which each NPC has bunch of skeletal animations. Maybe a herd of bulls. The animation can take much time to be processed. This can be reduced significantly if the computation of crowds become multithreaded. Each entity’s animations can be computed in a different thread.

Intel introduced a good solution to achieve this goal in this article. It defines a thread pool with worker threads which their count should not be more than CPU cores otherwise the application performance decreases. Each entity has its own animation and skinning calculations and it is considered as a job and is placed in a job queue. Each job is picked by a worker thread and the main thread calls render functions when the jobs are done. If you want to see this computation technique more in action, I suggest you to have a look at Havok animation/physics documentation and study the multithreading in the animation season. To have the docs you have to download the whole SDK here. Also you can find that Havok is handling synchronous and asynchronous jobs there by defining different job types.

Updating Animations


One important thing in animation systems is how you manage the update rate of a skeleton and its skinning data. Do we always need to update animations each frame? If true do we need to update each bone every frame? So here we should have a LOD manager for skeletal animations. The LOD manager should decide whether to update hierarchy or not. It can consider different states of a character to decide about its update rate. Some possible cases to be considered are listed here:

1- The priority of the animated character: Some characters like NPCs and crowds do not have very high degree of priority so you may not update them in every frame. At most of the times, they are not going to be seen clearly so they can be ignored to be updated every frame.

2- Distance to Camera: If the character is far from the camera, many of its movements cannot be seen. So why should we just compute something that cannot be seen? Here we can define a skeleton map for our current skeleton and select more important bones to be updated and ignore the others. For example when you are far from the camera you don't need to update finger bones or neck bone. You can just update spines, head, arms and legs. These are the bones which can be seen from far. So with this you have a light weighted skeleton and you are ignoring many bones to update. Don't forget that human hands have 28 bones for fingers and 28 bones for a small portion of a mesh, is not very efficient.

3- Using Dirty Flags For Bones: In many situations, the bone transformation is not changed in two consecutive frames. For example the animator himself didn't animate that bone in several frames or the curve simplification algorithm reduced consecutive keyframes which are more similar. In these kind of situations, you don't need to update the bone in its local space again. As you might know the bones are firstly calculated in their local space based on animation info and then they will be multiplied by their binding pose and parent transformation to be specified in world or modeling space. Defining dirty flags for each bone can help you to not calculate bones in their local space if they are not changed between two consecutive frames. They can be updated in their local space if they are dirty.

4- Update Just When They Are going To Be Rendered: Imagine a scene in which some agents are following you. You try to run away from them. The agents are not in the camera frustum but their AI controller is monitoring and following you. So do you think we should update the skeleton while the player can't see them? Not at most cases. So you can ignore the update of skeletons which are not in camera frustum. Both Unity3D and Unreal Engine4 have this feature. They allow you to select whether the skeleton and its skinned mesh should be updated or not if they are not in camera frustum.

You might need to update skeletons even if they are not in the camera frustum. For example you might need to shoot an object to a character's head which is not in the camera. Or you may need to read the root motion data and use it for locomotion extraction. So you need calculated bone positions. In this kind of situations you can force the skeleton to be updated manually or not using this technique.

2. Optimized Usage of Animation Systems


So far, some techniques have been discussed to implement an optimized animation systems. As a user of an animation system, you should trust the system and assume that it is well optimized. You assume that the system has many of the techniques described above or even more. So you can produce animations which can be friendlier with an optimized animation system. I'm going to address some of them here. This section is more convenient for animators/technical animators.


Do not Move All Bones Always


As mentioned earlier the animation tracks can be optimized and their keyframes can be reduced easily. So by knowing this, you can create animations which is more suitable for this kind of optimization. So do not scale or move the bones if it is not necessary. Do not transform bones that cannot be seen. For example while you are making a fast sword attack, not all of the facial bones can be seen. So you don't need to move them all.

In the cutscenes where you have a predefined camera, you know which bones are in the camera frustum. So if you have zoomed the camera on the face of your character, you don't need to move the fingers or hands. With this you will save your own time and will let the system to save much memory by preventing to export or simplifying the animation tracks for bones.

One other important thing is duplicating two consecutive keyframes. This occurs frequently in blocking phase of animation. For example, you move fingers in frame 1 and again move them in frame 15 and you copy the keyframe 15 to frame 30. Keyframe 15 and 30 are the same. But the default keyframe interpolation techniques are set to make the animation curves smooth. This means that you might get an extra motion between frame 15 and 30. Figure1 shows a curve which is smoothed with keyframe interpolation techniques.


Figure1: A smoothed animation curve

As you can see in Figure1, the keyframe number 2 and 3 are the same. But there is an extra motion between them. You might need this smoothness for many bones so leave it be if you need it. But if you don't need it make sure to make the two similar consecutive keyframes more linearly as shown in figure 2. With this, the keyframe reduction algorithm can reduce the keyframe samples.


Figure2: Two linear consecutive keyframes

You should consider this case for finger bones more carefully. Because fingers can be up to 28 bones for a human skeleton and they are showing a small portion of the body but they take much memory and calculation. In the previous example if you make the two similar consecutive keyframes linear, there would be no visual artifact for finger bones and you can drop 28 * (30 - 15 + 1) keyframe samples. Where 28 is the number of finger bones and 30 and 15 are the frames in which keyframes are created by the animator. The sampling rate is one sample per frame in this example. So by setting two consecutive keyframes to linear for finger bones, you will save much memory. This amount of memory can't be very huge for one animation but it can become huge when your game have many skeletal animations.

Using additive and partial animations instead of full body animation


Animation blending has different techniques. Two of them which are very good at both functionality and performance are additive and partial animation blending. These two blending schemes are usually used for asynchronous animation events. For example when you are running and decide to shoot. So lower body continue to run and the upper body blends to shoot animation.

Using additive and partial animations can help you to have less animations. Let me describe this with an example. Imagine you have a locomotion animation controller. It blends between 3 animations (walk, run and sprint) based on input speed. You want to add a spine lean animation to this locomotion. So when your character is accelerating the character leans forward for a period of time. First you can make 3 full body walk_lean_fwd, run_lean_fwd and sprint_lean_fwd animations which are blending synchronously with walk, run and sprint respectively. You can change the blend weight to achieve a lean forward animation. Now you have three full body animations with several frames. This means more keyframes, more memory usage and more calculation. Also your blend tree gets more complicated and high dimensional. Imagine that you are adding 6 more animations to your current locomotion system. Two directional walks, two directional runs and two directional sprints. Each of them have to be blended with walk, run and sprint respectively. So with this, if we want to have leaning forward,  we have to add two directional walk_lean_fwd, two directional run_fwd and two directional sprint_fwd and blend them respectively with walk, run and sprint blend trees. The blend tree is going to be high dimensional and needs too much full body animations and too much memory and calculation. Even it becomes hard for the user to manipulate.

You can handle this situation more easily by using a light weighted additive animation. An additive animation is an animation that is going to be added to current animations. Usually it's a difference between two poses. So first your current animations are calculated then the additive is going to be multiplied to the current transforms. Usually the additive animation is just a single frame animation which is not really needs to affect all of the body parts. In our example the additive animation can be a single frame animation in which spine bones are rotated forward, the head bone is rotated down and the arms are spread a little. You can add this animation to the current locomotion animations by manipulating its weight. You can achieve the same results with just one single frame and half body additive animation and there is no need to produce different lean forward full body animations. So using additive and partial animation blending can reduce your workload and help you to achieve better performance very easily.

Using Motion Retargetting


A motion retargetting system promises to apply a same animation on different skeletons without visual artifacts. By using it you can share your animations between different characters. For example you make a walk for a specific character and you can use this animation for other characters as well. By using motion retargetting you can save your memory by preventing animation duplication. But just note that a motion retargetting system has its own computations. So it's not just the basic skeletal animation and it needs many other techniques like how to scale the positions and root bone translation how to limit the joints, ability to mirror animations and many other things. So you may save animation memory and animating time, but the system needs more computation. The computation may not become a bottleneck in your game.

Unity3D, Unreal Engine4 and Havok animation all three support motion retargetting. If you don't need to share animations between different skeletons, you don't need to use motion retargetting.


Conclusion


Optimization is always a serious part in video games. Video games are among the soft real time software so they should respond in a proper time. Animation is always an important part of a video game. It is important from different aspects like visuals, controls, storytelling, gameplay and more. Having lots of character animations in a game can improve it significantly, but the system should be capable of handling too much character animations. This article tried to address some of the techniques which are important in the optimization of skeletal animations. Some of the techniques are highly detailed and they were discussed generally here. The discussed techniques were reviewed from two perspectives. First, from the developers who want to create skeletal animation systems and second, from the users of animation systems.

Monday, September 2, 2013

What Is a Binding Pose in Character Animation?

3D Character modelers always model 3D models in a pose known as T-pose where the character model stands in a certain pose and the hands and body shows a figure like T (Figure1)


     Figure1: A 3D model in T-pose and bones placed in it


Modelers model the characters in T-Pose so the riggers can rig the character easily. This helps them to place the bones to adjust vertex weights and envelopes easier. When all the bones are placed in the 3D model and the skinning process starts, the current pose of the skeleton is saved. This pose is called Binding Pose. The name speaks for itself. Binding pose is the pose where you start binding a mesh to its corresponding skeleton.

The idea of binding pose comes from Bio-mechanics where a human body motion is studied with respect to a pose called Standard Anatomical Position. Standard anatomical position is actually shows the rotation origin for each limb. Within this pose, the human body muscles has the highest level of rest hence it's the best pose to consider for the origin of the rotation of the limbs. That's the reason the 3D modelers model the characters in similar pose because the muscles are the least contracted and it's the most neutral pose for the body. Then the character riggers place the bones to the mesh to define the biding pose as the origin of the transformation of the bones.

Now why a binding pose should be saved?  You might know that all of the vertices' positions initially should be calculated in modeling space. A skinned mesh's vertices are transformed by its corresponding skeleton. When the skeleton bones transform, the vertices' positions change based on the weights they have for each bone (bones transformations are calculated in mesh's modeling space (object space)). Now if the vertices' positions change based on the orientation of the bones the whole mesh will be distorted because of an extra orientation or maybe position that the riggers applied to bones to adjust them into meshes. The rigger transforms each bone to fit them in the mesh's body. These transformations (call it Binding Pose Transformation) should not be calculated for the final vertices positions. You can consider an example in which you have a skinned mesh, so by changing bone transformations the vertices positions should be changed as well. Lets consider just one bone rotation. The orientation of the bone in mesh's modeling space is equal to:

Bone Orientation =  Binding Pose Rotation * KeyFrame Rotation

If vertices get affected by the "Bone Orientation" variable, first they will be rotated by Binding Pose Rotation and next with the key frame rotation and that binding pose rotation will distort all of the vertices because the initial model that the modeler created is affected by some extra unnecessary rotations produced by the rigger. So for bones belonging to a skeleton of a skinned mesh, a reference pose have to be saved and this reference pose is called Binding Pose. It will be saved when you apply a skin modifier to your mesh or in other words when you start the skinning process. For each bone in character animation, all of the key frames are stored relative to its binding pose. For a skinned mesh, deformations occur based on the relative transformations of each bone to its binding pose. This will prevent the mesh to be distorted.

For animation blending each bone has a weight. The weight is ranged between 0 and 1 which 1 means the full calculation of the key frame transformation and 0 means the binding pose. Now any other number between 0 and 1 for a weight shows a blended transformation between bones binding poses and key frames transformations.

As a side note, saving the keyframes relative to binding pose facilitates the process of  animation retargetting and also provides easier ways to compress the keyframes.

Monday, October 15, 2012

Weird hierarchy of character studio biped

This post is in the class of technical animation.

Early video games have many animations, producing such amount of animations need a flexible animation pipeline and a flexible pipeline needs a flexible working package. Here is when 3dsmax Character Studio comes in. Character studio is such a flexible animation package, it can help animators to create animations as fast as they can, it's like a plug and play device, but it has some limitations such as zero degree of extendability, this means it has low level of customization but it's still a good package. The most annoying problem it has, is that it's a huge black box. It doesn't work in the way 3dsmax works. It was a standalone plugin on older versions of max but now it becomes an inseparable part of 3dsmax.

On this post i'm gonna talk about the weird hierarchy of character studio and the problems it can make on relatime animations in another environment such as your game engine.

For all who worked with character studio they know that if they rotate the "Bip001 Spine", "Bip001 Spine1" and it's children are going to rotate. it's natural because you find that they are it's children they have to move you can see it's structure in the picture below.







 But there are some other unyielding children which they never obey their parent. So let's take a look at actual hierarchy of a biped using 3dsmax schematic view.




 You can see that "Bip001 L Thigh" and "Bip001 R Thigh" are the children of the "Bip001 Spine", but when you rotate the "Bip001 Spine" you see no effects to legs!! That's weird! Character studio internally handles the transformation of the bones not in the way max handles the standard nodes in it's scene graph and more important it's transformation computing is different from an external environments like game engines. Before i talk about the problem and it's solution let me to compare the desired hierarchy and the default one.

From top to down:

1- You expect "Bip001 Prop" to be 'Bip001  Hand' 's child but it's the "Bip001" 's child
2- You expect "Bip001 L Thigh" and "Bip001 L Thigh" to be "Bip001" or "Bip001 Pelvis" 's children but they are the "Bip001 Spine" 's children
3- You expect "Bip001 L Clavicle" and "Bip001 R Clavicle" be "Bip001 Spine3"  children but they are the "Bip001 Neck"'s children

You might never find any problem in this kind of hierarchy, because you can see what you expect in max, also there is no problem if you export the animation with normal keyframe sample rate (maybe 30 samples per second or higher) and play it on your game engine because the exporter stores all the transformations at each time step. The main problem occurs when you want to blend between two or more animations with some techniques like partial and additive animations or some procedural animation like inverse kinematics or ragdoll simulations.

Assume a situation in which you have 2 animations, a run and a shoot, if you play each one separately you will see a normal animation, an expected result, but assume that you want a make a shoot while running using partial blending. So you have to make a blend mask for upper body of shoot animation and a blend mask for lower body of run and then playing both animations. When you do that you will see an unexpected result. The legs rotate when you shoot this is because when the upper body animation plays it affects the lower body since originally Bip001 spine is the parent of Bip001 L and R Thighs so when it start rotating it affects the legs. You can find the same problem on the Bip001 Prop bones in the same situation or if you add another animation to the spine or it's children, the prop bone is "Bip001" 's child so it moves whenever Bip001 moves, in this case the additive animation applies to some bones rather than Bip001 so the prop bone inherit no orientation and it leaves the body.

There is a simple solution for this problem. Just do this simple changes on your rig once and for all when you want to start rigging your character it has no side effects and it solves all of the runtime problems:

$'Bip001 prop1'.parent = $'Bip001 R Hand'
$'Bip001 Spine'.parent = $'Bip001'
$'Bip001 L Thigh'.parent = $'Bip001'
$'Bip001 R Thigh'.parent = $'Bip001'
$'Bip001 L Clavicle'.parent = $'Bip001 Spine3'
$'Bip001 R Clavicle'.parent = $'Bip001 Spine3'

After doing this you can have any type of blending or procedural animations without sacrifice.
Beside of the blending problem, the default hierarchy forces the exporter to export some extra transformation data for translations. So doing this simple changes can help the exporter to optimize the keyframes better and with that you find more memory for your other works.

There is another problem about twist bones hierarchy. Assume that you added some upper arm twists to your rig. By default upper arm twists are children of the clavicle. This leads you to a problem when you want to add some procedural animations at run time on arms like inverse kinematics. If you make upper arm as their parent all the problems at run time will be solved. But there is last remaining problem, and that is max never save your changes to the twist bones hierarchy! so you have to make your custom changes to the twists every time you want to export the animation. I have written a simple callback script for this issue. It is triggered on the open file event. It checks if there are any biped in the scene and and make our desired changes to the twists.


Conclusion

Character studio have a weird  hierarchy. This hierarchy leads the animation to some problems while applying procedural animations and blending at runtime. Doing simple changes to it's hierarchy will help you to solve the problems during blending and procedural animations and also helps the exporter to perform a better keyframe optimization.