• Create Account

### #ActualSector0

Posted 10 July 2013 - 03:33 PM

Hi Tispe,

Obviously the quaternion multiplication is not commutative this means q1 * q2 is not equal to q2 * q1. beside this you might know that quaternion slerp always interpolates between two rotations on the shortest arc from all possible arcs between them so using slerp is a great idea to achieve animation blending.

For blending, first you have to order your animations in the way you need. For example you can enable walk animation firstly and next run animation could be enabled. I recommend you to always save the order of  enabled animations in a queue. Users have to enable them in order they want.

Each bone for each animation owns a weight. In animation systems there are two ways to apply weights for blending. First one is mixing and the second is additive weighting.

Mixing: For mixing you should calculate the average weight of each animation with respect to the other animation weights. For example if you want to blend three animations together, they should be blended like this (assume that anim1, anim2 and anim3 have been enabled in order):

if (anim1.weight > anim2 weight)

{

q = slerp( anim1, anim2, 1- anim1.weight/(anim1.weight + anim2.weight));

}

else

{

q = slerp( anim1, anim2, anim2.weight/(anim1.weight + anim2.weight));

}

if ( anim1.weight + anim2.weight > anim3.weight >)

{

q = slerp( q, anim3, 1- (anim1.weight + anim2.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

else

{

q = slerp( q, anim3, (anim3.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

After this, you can multiply q to the T-pose of the current bone: qfinal = q * T-pose
It is better to make a loop for this procedure because there maybe many animations blending with each other.

Some graphics engines like OGRE do not blend different animations with slerp interpolation like i mentioned above. They sequentially multiply quaternions in order. For

example three animations are calculated like this (assume that anim1, anim2 and anim3 have been enabled in order):

anim1.weight = anim1.weight/(anim1.weight + anim2.weight + anim3.weight)

anim2.weight = anim2.weight/(anim1.weight + anim2.weight + anim3.weight)
anim3.weight = anim3.weight/(anim1.weight + anim2.weight + anim3.weight)

q = (anim3.weight * q3) * (anim2.weight* q2) * (anim1.weight * q3) ;

This method does not provide accurate blending resultd because it does not interpolates on the shortest arc between 2 rotations but its result is acceptable and it has a better performance in comparison to using slerp for blending.

You might want to implement two techniques and use them for different usages. For example if you want to have animations with lower LOD you can apply the second technique to them.

For each animation you have to save its blending type to know whether it is average or additive to apply its weights with the proper technique.

I have two short posts on my blog about unit quaternions. you might want to check them out:

Hope this would help.

### #2Sector0

Posted 10 July 2013 - 02:56 PM

Hi Tispe,

Obviously the quaternion multiplication is not commutative this means q1 * q2 is not equal to q2 * q1. beside this you might know that quaternion slerp always interpolates between two rotations on the shortest arc from all possible arcs between them so using slerp is a great idea to achieve animation blending.

For blending, first you have to order your animations in the way you need. For example you can enable walk animation firstly and next run animation could be enabled. I recommend you to always save the order of  enabled animations in a queue. Users have to enable them in order they want.

Each bone for each animation owns a weight. In animation systems there are two ways to apply weights for blending. First one is mixing and the second is additive weighting.

Mixing: For mixing you should calculate the average weight of each animation with respect to the other animation weights. For example if you want to blend three animations together, they should be blended like this (assume that anim1, anim2 and anim3 have been enabled in order):

if (anim1.weight > anim2 weight)

{

q = slerp( anim1, anim2, 1- anim1.weight/(anim1.weight + anim2.weight));

}

else

{

q = slerp( anim1, anim2, anim2.weight/(anim1.weight + anim2.weight));

}

if ( anim1.weight + anim2.weight > anim3.weight >)

{

q = slerp( q, anim3, 1- (anim1.weight + anim2.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

else

{

q = slerp( q, anim3, (anim3.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

After this, you can multiply q to the T-pose of the current bone: qfinal = q * T-pose
It is better to make a loop for this procedure because there maybe many animations blending with each other.

Some graphics engines like OGRE do not blend different animations with slerp interpolation like i mentioned above. They sequentially multiply quaternions in order. For

example three animations are calculated like this (assume that anim1, anim2 and anim3 have been enabled in order):

anim1.weight = anim1.weight/(anim1.weight + anim2.weight + anim3.weight)

anim2.weight = anim2.weight/(anim1.weight + anim2.weight + anim3.weight)
anim3.weight = anim3.weight/(anim1.weight + anim2.weight + anim3.weight)

q = (anim3.weight * q3) * (anim2.weight* q2) * (anim1.weight * q3) ;

This method does not provide actual blending result because it does not interpolates on the shortest arc between 2 rotations but its result is acceptable and it has a better performance in comparison to using slerp for blending.

You might want to implement two techniques and use them for different usages. For example if you want to have animations with lower LOD you can apply the second technique to them.

For each animation you have to save its blending type to know whether it is average or additive to apply its weights with the proper technique.

I have two short posts on my blog about unit quaternions. you might want to check them out:

Hope this would help.

### #1Sector0

Posted 10 July 2013 - 02:27 PM

Hi Tispe,

Obviously the quaternion multiplication is not commutative this means q1 * q2 is not equal to q2 * q1. beside this you might know that quaternion slerp always interpolates between two rotations on the shortest arc from all possible arcs between them so using slerp is a great idea to achieve animation blending.

For blending, first you have to order your animations in the way you need. For example you can enable walk animation firstly and next run animation could be enabled. I recommend you to always save the order of  enabled animations in a queue. Users have to enable them in order they want.

Each bone for each animation owns a weight. In animation systems there are two ways to apply weights for blending. First one is mixing and the second is additive weighting.

Mixing: For mixing you should calculate the average weight of each animation with respect to the other animation weights. For example if you want to blend three animations together, they should be blended like this (assume that anim1, anim2 and anim3 have been enabled in order):

if (anim1.weight > anim2 weight)

{

q = slerp( anim1, anim2, 1- anim1.weight/(anim1.weight + anim2.weight));

}

else

{

q = slerp( anim1, anim2, anim2.weight/(anim1.weight + anim2.weight));

}

if ( anim1.weight + anim2.weight > anim3.weight >)

{

q = slerp( q, anim3, 1- (anim1.weight + anim2.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

else

{

q = slerp( q, anim3, (anim3.weight)/(anim1.weight + anim2.weight + anim3.weight));

}

After this, you can multiply q to the T-pose of the current bone: qfinal = q * T-pose
It is better to make a loop for this procedure because there maybe many animations blending with each other.

Some graphics engines like OGRE do not blend different animations with slerp interpolation like i mentioned above. They sequentially multiply quaternions in order. For

example three animations are calculated like this (assume that anim1, anim2 and anim3 have been enabled in order):

anim1.weight = anim1.weight/(anim1.weight + anim2.weight + anim3.weight)

anim2.weight = anim2.weight/(anim1.weight + anim2.weight + anim3.weight)
anim3.weight = anim3.weight/(anim1.weight + anim2.weight + anim3.weight)

q = (anim3.weight * q3) * (anim2.weight* q2) * (anim1.weight * q3) ;

This method does not provide actual blending result because it does not interpolates on the shortest arc between 2 rotations but its result is acceptable and it has a better performance in comparison to using slerp for blending.

You might want to implement two techniques and use them for different usages. For example if you want to have animations with lower LOD you can apply the second technique to them.