Graphics Reference
In-Depth Information
To produce a smoother animation without artefacts introduced from the linear interpolation of
rotation matrices, we have decomposed our transformation matrices for the two key-frames
into its translation, rotation, and scale components. The translation is stored within Vector3 ,
the uniform scale within a float variable, and finally the rotation component is now stored
within a quaternion.
prevFrame.Transform.DecomposeUniformScale(out s1, out q1, out t1);
frame.Transform.DecomposeUniformScale(out s2, out q2, out t2);
A quaternion is an alternative mathematical entity used to represent rotations. The use of
quaternion has advantages over rotation matrices in numerous situations because they
require less storage, fewer arithmetic operations for concatenation, and quaternions are more
easily interpolated (which is most important for this recipe). Spherical linear interpolation is
used here as the method for interpolating the quaternions because regular linear interpolation
does not trace out the arc between q1 and q2 at a constant rate ( Lengyel , 2012 , pp. 80-87 ).
Using linear interpolation between two matrices with the SharpDX.Matrix.Lerp method
would not necessarily result in a correct rotation matrix. It may work fine if the key-frames
are close together and there are no large movements; however, it would be necessary to use
either normalized linear interpolation or spherical linear interpolation to get correct results.
Both of these operations are more efficient when using quaternions.
We linearly interpolate (lerp) between the two scale floats ( s1 and s2 ) and the two
translation vectors ( t1 and t2 ). Then we perform spherical linear interpolation (Slerp)
between the two quaternions ( q1 and q2 ). The matrix is then reconstructed from the
interpolated scale, rotation, and translation.
// Perform interpolation and reconstruct matrix
skinMatrices.Bones[frame.BoneIndex] =
Matrix.Scaling(MathUtil.Lerp(s1, s2, amount)) *
Matrix.RotationQuaternion(
Quaternion.Slerp(q1, q2, amount) ) *
Matrix.Translation(Vector3.Lerp(t1, t2, amount));
To ensure that we end up with the correct result, multiply the matrices in the following order:
first apply scale, then rotate, and finally translate.
To exaggerate the effect of the frame smoothing, try slowing down the
animation. For example, to get 1sec of the animation equal to 10secs ,
use the following code:
// Calculate elapsed seconds as 1sec = 10sec
var time = clock.ElapsedMilliseconds / 10000.0f;
 
Search WWH ::




Custom Search