Animating a Wpf3D 0.1 ModelAnimating a Wpf3D 0.1 Model
Position and size of a Wpf3D model
Wpf3D objects are created by default at (0, 0, 0) or around. Their dimensions are of one unit, or close to one unit. To modify the size or position of these models, it is necessary to apply to them 3D WPF transformations.
But why Wpf3D models don't have properties making it possible to manage their size and position ? The 2 reasons are modularity and performance :
- Modularity, because the model design is independent of model use (scaling, moving, rotation).
- Performance because the 3D transformations are managed by the graphics processor (GPU), which frees the main processor (CPU).
Animating a basic Wpf3D model
To animate a Wpf3D model, we just have to animate the transformations which are applied to it.
I will describe here how to make turn on itself a panel (of Square3D type) while moving it.

Rotation is defined by means of a RotateTransform3D object, and moving is defined by means of a TranslateTransform3D. The 2 transformations are gathered in a Transform3DGroup object, itself assigned to the Transform property of the Square3D. The transformations which are the object of the animation must be indicated by a name through the x:Name attribute. It is useless to give a value to the animated properties (that will be done in the animation definition).
<Wpf3D:Square3D Material="{StaticResource GlossySteelBlue}" BackMaterial="{StaticResource GlossySteelBlue}">
<Wpf3D:Square3D.Transform>
<Transform3DGroup>
<RotateTransform3D CenterX="0.5">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="ModelRotation" Axis="0,1,0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
<TranslateTransform3D x:Name="SquareTranslation"/>
</Transform3DGroup>
</Wpf3D:Square3D.Transform>
</Wpf3D:Square3D>Animations are gathered in a Storyboard. Each one refers to a given property (TargetProperty) of a given transformation (TargetName). The Storyboard is started on the Loaded event of the window by means of a Viewport3D Trigger.
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0" To="10" Duration="0:0:4"
Storyboard.TargetName="SquareTranslation"
Storyboard.TargetProperty="OffsetX" RepeatBehavior="Forever"/>
<DoubleAnimation From="0" To="5" Duration="0:0:4"
Storyboard.TargetName="SquareTranslation"
Storyboard.TargetProperty="OffsetY" RepeatBehavior="Forever"/>
<DoubleAnimation From="0" To="15" Duration="0:0:4"
Storyboard.TargetName="SquareTranslation"
Storyboard.TargetProperty="OffsetZ" RepeatBehavior="Forever"/>
<DoubleAnimation From="0" To="360" Duration="0:0:2"
Storyboard.TargetName="ModelRotation"
Storyboard.TargetProperty="Angle" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Viewport3D.Triggers>Animating a composite Wpf3D model
A ModelVisual3D object can gather several elementary Wpf3D objects. A transformation applied to this ModelVisual3D applies broadly to the various objects which compose it.
A ModelVisual3D can also contain other ModelVisual3D objects, which each one can use transformations.
Thus it is easy to animate independently the various parts of a composite model.

In the case of the above gyroscope, the first animation is thus established for the rotor and applied to RotorRotation. The rotor is composite. An animated composite model is composed by 2 external rings (animation applied to RingModelRotation). Within this pair of rings, the outside ring uses itself an animation (applied to FrameRingRotation).
<ModelVisual3D>
<!-- Rotor and spin axis -->
<ModelVisual3D>
<ModelVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="RotorRotation" Axis="0,1,0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ModelVisual3D.Transform>
<!-- Spin Axis -->
<Wpf3D:Bar3D SideCount="20" Material="{StaticResource GlossySteelBlue}" >
<Wpf3D:Bar3D.Transform>
<Transform3DGroup>
<RotateTransform3D Rotation="{StaticResource X90Rotation}"/>
<TranslateTransform3D OffsetX="0" OffsetY="0.5" OffsetZ="0"/>
<ScaleTransform3D ScaleX="0.2" ScaleY="26" ScaleZ="0.2" CenterX="0" CenterY="0" CenterZ="0" />
</Transform3DGroup>
</Wpf3D:Bar3D.Transform>
</Wpf3D:Bar3D>
<!-- Rotor -->
<Wpf3D:Bar3D SideCount="120" Material="{StaticResource GlossyGold}" >
<Wpf3D:Bar3D.Transform>
<Transform3DGroup>
<RotateTransform3D Rotation="{StaticResource X90Rotation}"/>
<TranslateTransform3D OffsetX="0" OffsetY="0.5" OffsetZ="0"/>
<ScaleTransform3D ScaleX="10" ScaleY="4" ScaleZ="10" CenterX="0" CenterY="0" CenterZ="0" />
</Transform3DGroup>
</Wpf3D:Bar3D.Transform>
</Wpf3D:Bar3D>
</ModelVisual3D>
<Wpf3D:Ring3D SegmentCount="800" Radius="13" SideCount="4" InitialAngle="45.0" RoundingRate="0.15"
Material="{StaticResource GlossySteelBlue}">
<Wpf3D:Ring3D.Transform>
<Transform3DGroup>
<RotateTransform3D Rotation="{StaticResource X90Rotation}"/>
<ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="2" CenterX="0" CenterY="0" CenterZ="0" />
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,1,0" Angle="90" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</Wpf3D:Ring3D.Transform>
</Wpf3D:Ring3D>
<!-- 2 external rings model -->
<ModelVisual3D>
<ModelVisual3D.Transform>
<!-- 2 rings model rotation -->
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="RingModelRotation" Axis="0,0,1" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ModelVisual3D.Transform>
<!-- Frame ring -->
<Wpf3D:Ring3D SegmentCount="800" Radius="16" SideCount="4" InitialAngle="45.0"
RoundingRate="0.15" Material="{StaticResource GlossySteelBlue}">
<Wpf3D:Ring3D.Transform>
<Transform3DGroup>
<RotateTransform3D Rotation="{StaticResource X90Rotation}"/>
<ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="2" CenterX="0" CenterY="0" CenterZ="0" />
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="FrameRingRotation" Axis="1,0,0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</Wpf3D:Ring3D.Transform>
</Wpf3D:Ring3D>
<!-- Second ring -->
<Wpf3D:Ring3D SegmentCount="800" Radius="14.5" SideCount="4" InitialAngle="45.0" RoundingRate="0.15"
Material="{StaticResource GlossySteelBlue}">
<Wpf3D:Ring3D.Transform>
<ScaleTransform3D ScaleX="1" ScaleY="2" ScaleZ="1" CenterX="0" CenterY="0" CenterZ="0" />
</Wpf3D:Ring3D.Transform>
</Wpf3D:Ring3D>
</ModelVisual3D>
</ModelVisual3D>
<Wpf3D.Tools:Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0" To="360" Duration="0:0:30"
Storyboard.TargetName="FrameRingRotation"
Storyboard.TargetProperty="Angle" RepeatBehavior="Forever"/>
<DoubleAnimation From="0" To="360" Duration="0:0:15"
Storyboard.TargetName="RingModelRotation"
Storyboard.TargetProperty="Angle" RepeatBehavior="Forever"/>
<DoubleAnimation From="360" To="0" Duration="0:0:3"
Storyboard.TargetName="RotorRotation"
Storyboard.TargetProperty="Angle" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Wpf3D.Tools:Viewport3D.Triggers>