This article is obsolete. Some functionalities might not work anymore. Comments are disabled.
Closing my last post on Tweener(Of T) for Silverlight 2.0, I left promising myself to test it in a WPF 3D scenario.
Now that I've done it. I show you the results...
The screenshot above pictures a 3D scene where the five classical polyhedra rotate around the Y-Axis
(in WPF X-Axis goes from left to right along the screen, Y-Axis from bottom up and Z-Axis enters into the screen as our gaze does).
It is nothing more than a simple WPF application (installable from here via ClickOnce)
No instructions are provided, so you better be aware that to trigger scene tweenings you have to use your Left and Right arrow-keys!
The ModelVisual3D containing the polyhedra will be rotated (using Easing.Back easing), focusing a specific Solid.
The solid getting the focus starts to rotate around a generic axis (which passes through
the origin of the coordinate system relative to it) in a Loop (*new) behavior.
This rotation stops as soon as it loses the focus.
The C# implementation was neatly straightforward: I pointed the tweener on different AxisAngleRotation3D DependencyObjects
to modify their AngleProperty DependencyProperty.
Here's the complete C# implementation code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Pacem.Media.Tweening;
using System.Windows.Media.Media3D;
using Pacem.Media.Media3D;
namespace Test_WpfApp
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
solids = new Solid[] { dodeca, tetra, octa, hexa, icosa };
}
private Tween<double> tween;
private Tween<double> tween2;
private int jTick = 0;
private Solid[] solids = null;
private void RootPage_KeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Left:
if (tween != null) Tweener<double>.Stop(tween, true);
tween = Tweener<double>.CreateTween(
rotation,
AxisAngleRotation3D.AngleProperty,
Pacem.Media.Tweening.Easing.Back.EaseOut,
rotation.Angle, 72D * (double)++jTick,
TimeSpan.FromSeconds(1D));
break;
case Key.Right:
if (tween != null) Tweener<double>.Stop(tween, true);
tween = Tweener<double>.CreateTween(
rotation,
AxisAngleRotation3D.AngleProperty,
Pacem.Media.Tweening.Easing.Back.EaseOut,
rotation.Angle, 72 * (double)--jTick,
TimeSpan.FromSeconds(1D));
break;
}
if (tween != null)
{
tween.MotionStarted += new EventHandler(tween_MotionStarted);
tween.MotionFinished += new EventHandler(tween_MotionFinished);
}
}
void tween_MotionFinished(object sender, EventArgs e)
{
int index = (int)(((Tween<double>)sender).Finish / -72D) % 5;
if (index < 0) index = 5 + index;
AxisAngleRotation3D rotation = ((RotateTransform3D)
((Transform3DGroup)solids[index].Transform).Children[1]).Rotation
as AxisAngleRotation3D;
tween2 = Tweener<double>.CreateTween(
rotation,
AxisAngleRotation3D.AngleProperty,
Pacem.Media.Tweening.Easing.Quad.EaseInOut,
rotation.Angle, rotation.Angle+360D,
TimeSpan.FromSeconds(2.5D));
tween2.FinishedBehavior = ClockFinishedBehavior.Loop;
}
void tween_MotionStarted(object sender, EventArgs e)
{
int index = (int)(((Tween<double>)sender).Start / -72D) % 5;
if (index < 0) index = 5 + index;
if (tween2 != null) Tweener<double>.Stop(tween2, true);
}
}
}
And here is the XAML relative to the octahedron solid:
<Window x:Class="Test_WpfApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006"
xmlns:pacemHedra="clr-namespace:Pacem.Media.Media3D.Hedra;assembly=Pacem.Media"
xmlns:primitives="clr-namespace:Pacem.Media.Media3D.Primitives;assembly=Pacem.Media"
xmlns:pacem="clr-namespace:Pacem.Media.Media3D;assembly=Pacem.Media"
x:Name="RootPage" Width="640" Height="250"
Title="Cristian Merighi Polyhedra" KeyUp="RootPage_KeyUp">
<!--
...[OMITTED XAML]...
-->
<ModelVisual3D x:Name="scene">
<ModelVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="rotation" Angle="0" Axis="0,1,0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ModelVisual3D.Transform>
<!--
...[OMITTED XAML]...
-->
<!-- octahedron -->
<pacemHedra:Octahedron x:Name="octa">
<ModelVisual3D.Transform>
<Transform3DGroup>
<TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="-3" />
<RotateTransform3D CenterX="0" CenterY="0" CenterZ="-3">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="-1,.15,.65" Angle="0"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,1,0" Angle="144" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</ModelVisual3D.Transform>
<pacemHedra:Octahedron.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="#c00099ff" />
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<SpecularMaterial>
<SpecularMaterial.Brush>
<SolidColorBrush Color="#ff00ccff" />
</SpecularMaterial.Brush>
</SpecularMaterial>
</MaterialGroup>
</pacemHedra:Octahedron.Material>
</pacemHedra:Octahedron>
<!--
...[OMITTED XAML]...
-->
</ModelVisual3D>
I was enthusiastic when I saw the result!
As it was done with Silverlight, I'll probably add some targeted Tween implementations for Visual3D objects, with encapsulated support
for Point3D and Vector3D.
See you soon then...
Take care. Bye.