When we talk about 3D rotations in WPF, we immediately think of RotateTransform3D and AxisAngleRotation3D. Animating these rotations is then a matter of changing the Angle property using a DoubleAnimation. When we want to apply a series of rotations on 3D models with smooth transitions to different orientations, specifying the rotations using AxisAngleRotation3D may not give the best possible results. The transitions from one orientation to another may not be smooth or sometimes you may lose a Degree of Freedom (DoF), also called the Gimbal Lock effect.
To circumvent these problems, we can use a different representation for specifying orientations and rotations. That representation is called the Quaternion, first coined by William Hamilton. In short, a quaternion is a 4-dimensional complex number where the first 3 dimensions constitute the postional vector (v) and the last dimension is a scalar (w). Quaternions have their own laws of addition, subraction, multiplication, etc. There is no division operation.
Now getting back to our discussion on smooth rotations; quaternions greatly simplify the task of smooth interpolations between two orientations of a body. These interpolations coupled with a 3D rotation can give us the desired effect when rotating 3D models. One should note that quaternion rotations are only applicable for 3D and NOT for 2D.
Using the QuaternionRotation3D
WPF provides the QuaternionRotation3D class for specifying rotations to a 3D model. The most important dependency property of that class is the Quaternion property, which specifies the orientation. We know from our discussion earlier that a quaternion is a 4D quantity with a positional vector (x, y, z) and a scalar (w). Thus the quaternion is going to be a 4 tuple of the form (x, y, z, w).
But how does one go about specifying this tuple? The answer: we need to do a transformation to the quaternion space with some simple formulas.
If the axis around which we want to rotate is (ax, ay, az) and the angle of rotation is theta, then the quaternion (x, y, z, w) is:
x = ax * sin(theta / 2)
y = ay * sin(theta / 2)
z = az * sin(theta / 2)
w = cos(theta / 2)
Lets try an example.
Say we want to rotate about the X-axis (1, 0, 0) by 60 degrees. Then we have
ax = 1, ay = 0, az = 0; theta = 60
Then our quaternion (x, y, z, w) will be:
x = 1 * sin(30) = 0.5
y = 0, z = 0
w = cos(30) = 0.866
Thus our quaternion = (0.5, 0, 0, 0.866)
In XAML we would write this as:
<RotateTransform3D\>\ <RotateTransform3D.Rotation\>\ <QuaternionRotation3D Quaternion="0.5, 0, 0, 0.866" x:Name="\_rotator"/\>\ </RotateTransform3D.Rotation\>\ </RotateTransform3D\>
and then animate the rotation with:
<Storyboard> <QuaternionAnimation Storyboard.TargetName="_rotator" Storyboard.TargetProperty="Quaternion" From="0,0,1,0" To="0.3, 0.3, 1, 0" Duration="0:0:2" /> </Storyboard>
By adding more QuaternionAnimations to the Storyboard we can realize a smooth set of transitions to different orientions of the model.