Rotation3D, RotateTransform3D, Rotation3DAnimation, Center, Angle, Axis

I've been spending some time with the Rotation transformation and animation classes in Avalon.  These are very nifty and much easier to learn and use than Quaternions.  Thanks to the 3D guys for adding this class.

If you want to rotate something, you definitely need to get your head around both the Center property that hangs of RotationTransform3D class and the Axis property that hangs off the Rotation3D class which is used as the To, By and From values of the Rotation3DAnimation class.  The Center property will determine where the rotation will occur.  By default, it is set to Center="0 0 0" (to use XAML syntax of "X Y Z"), meaning that the rotation will be based from the very center of your mesh.  Let's say you wanted to make a plane swing back, like the hinge on a cat door.  Well, you would change the Center value to be Center="0 1 0", which bumps you up the Y axis.  Then, you would specify that you want to rotate around the X axis by specifying the Axis property of the Rotation3D as Axis ="1 0 0". (It is a little curious that you can't get at the Center property from the Rotation3D class -- need to investigate why this is.)  Any, it would look something like this: 

And here is the XAML. Cut and paste into XAMLPad to see it working.

<Grid Background="Black" xmlns="https://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
<Grid.Resources>
<MeshGeometry3D x:Key="PlaneMesh"
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0 1 2 1 3 2" />
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="x">
<EventTrigger.Actions>
<BeginAction TargetName="myTimeline" />
</EventTrigger.Actions>
</EventTrigger>
</Grid.Triggers>
<Grid.Storyboards>
<SetterTimeline
TargetName="myViewport3D"
Path="(Viewport3D.Models).(Model3DGroup.Children)[2].(Model3D.Transform).(RotateTransform3D.Rotation)"
FillBehavior="HoldEnd"
BeginTime="{x:Null}"
Name="myTimeline"
AutoReverse="True">
<Rotation3DAnimation Duration="00:00:01" >
<Rotation3DAnimation.To>
<Rotation3D Axis="1 0 0" Angle="45">
</Rotation3D>
</Rotation3DAnimation.To>
</Rotation3DAnimation>
</SetterTimeline>
</Grid.Storyboards>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<Viewport3D Focusable="true" Name="myViewport3D" Grid.Row="0" >
<Viewport3D.Camera>
<PerspectiveCamera
Position="0,0,7"
LookAtPoint="0,0,0"
Up="0,1,0"
NearPlaneDistance="0.25"
FarPlaneDistance="20"
FieldOfView="60" />
</Viewport3D.Camera>
<Viewport3D.Models>
<Model3DGroup >
<Model3DGroup.Children>
<AmbientLight Color="#ffcccccc"/>
<!-- 1 Light -->
<DirectionalLight Color="White" Direction="1,1,1" />
<!-- 2 Child -->
<GeometryModel3D Geometry="{StaticResource PlaneMesh}">
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Aqua">
</SolidColorBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<RotateTransform3D Center="0 1 0" />
</GeometryModel3D.Transform>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</Viewport3D.Models>
</Viewport3D>
<DockPanel Grid.Row="1">
<Button Width="100" Height="20" Name="x">Rotate Me</Button>
</DockPanel>
</Grid>

To make the rotation open like a door, change the Center to "-1 0 0" which would place the rotation center on the left hinge and then change the Axis to "0 1 0" which will rotate the mesh along the Y axis, simulating a door.

The sample also shows off EventTriggers, which wires up the animation to the button click. Notice how the BeginTime is {x:Null} which means that the animation will start based on the event trigger.

Also worth noting is how I path to the Mesh in the SetterTimeline -- a little complex, but if you look at the object hierarchy, it makes sense.