Tuesday 29 October 2013

WPF Multi Touch - Rotate the World

In this article we are going to see how to create a 3D multi touch example, this example we are going to create a rotatable 3D world with touch as well as in Mouse.For this we have to use StoryBoard for animation, and ViewPort3D for 3D support of image.




<Window x:Class="CSWPF3DMultiTouch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:shapes="clr-namespace:CSWPF3DMultiTouch"
        Title="Touch 3D World">
    <Window.Resources>
        <Storyboard x:Key="sb">
            <DoubleAnimation Storyboard.TargetName="InfoScale" Storyboard.TargetProperty="ScaleX" From="0" To="1">
                <DoubleAnimation.EasingFunction>
                    <BounceEase/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
            <DoubleAnimation Storyboard.TargetName="InfoScale" Storyboard.TargetProperty="ScaleY" From="0" To="1">
                <DoubleAnimation.EasingFunction>
                    <BounceEase/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </Window.Resources>

        <Grid Background="Black"  IsManipulationEnabled="True" ManipulationDelta="OnManipulationDelta" TouchUp="OnTouchUp" MouseLeftButtonDown="Grid_MouseLeftButtonDown" MouseMove="Grid_MouseMove" MouseLeftButtonUp="Grid_MouseLeftButtonUp" MouseWheel="Grid_MouseWheel">
              <Viewport3D x:Name="viewport">
                     <Viewport3D.Camera>
                           <PerspectiveCamera Position="0,0,5"/>
                     </Viewport3D.Camera>

                     <ModelVisual3D x:Name="Light">
                           <ModelVisual3D.Content>
                                  <Model3DGroup>
                                         <AmbientLight x:Name="light" Color="White"/>
                                  </Model3DGroup>
                           </ModelVisual3D.Content>
                     </ModelVisual3D>

                     <shapes:Sphere x:Name="earth">
                           <shapes:Sphere.Material>                              
                                  <DiffuseMaterial>
                                         <DiffuseMaterial.Brush>
                                                <ImageBrush ImageSource="Map.png"/>
                                         </DiffuseMaterial.Brush>
                                  </DiffuseMaterial>
                           </shapes:Sphere.Material>
                           <shapes:Sphere.Transform>
                                  <Transform3DGroup x:Name="transformGroup">
                                         <ScaleTransform3D x:Name="scaleTransform"/>
                                  </Transform3DGroup>
                           </shapes:Sphere.Transform>
                     </shapes:Sphere>                
              </Viewport3D>
       
              <Rectangle Fill="Transparent"/>
        <CheckBox x:Name="MouseSimulationCheckBox" Content="Allow mouse simulation" Foreground="RosyBrown" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"/>
        <TextBlock x:Name="InfoTextBox" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10" FontSize="24" Foreground="RosyBrown" FontWeight="Bold" RenderTransformOrigin="0.5,0.5">
            <TextBlock.RenderTransform>
                <ScaleTransform x:Name="InfoScale"/>
            </TextBlock.RenderTransform>
        </TextBlock>
        <Line x:Name="TouchLine" Stroke="Red" StrokeThickness="2"/>
    </Grid>
</Window>



using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;

namespace CSWPF3DMultiTouch
{
       public partial class MainWindow : Window
       {
              private double _angleBuffer = 0d;
              private static int _imageWidth = 1995;
              private static int _imageHeight = 2051;
              private List<DataCenter> _dataCenters;

              private bool _isMouseDown;
        private Point _startPoint;

              public MainWindow()
              {
                     InitializeComponent();
                     this._dataCenters = new List<DataCenter>(6);
            this._dataCenters.Add(new DataCenter() { Name = "Chicago", Bound = new Rect(328, 790, 20, 20) });
            this._dataCenters.Add(new DataCenter() { Name = "San Antonio", Bound = new Rect(285, 873, 20, 20) });
            this._dataCenters.Add(new DataCenter() { Name = "Amsterdam", Bound = new Rect(856, 711, 20, 20) });
            this._dataCenters.Add(new DataCenter() { Name = "Dublin", Bound = new Rect(796, 703, 20, 20) });
            this._dataCenters.Add(new DataCenter() { Name = "Hong Kong", Bound = new Rect(1454, 923, 20, 20) });
            this._dataCenters.Add(new DataCenter() { Name = "Singapore", Bound = new Rect(1406, 1040, 20, 20) });
            Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
              }
              private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
              {
                     this.scaleTransform.ScaleX *= e.DeltaManipulation.Scale.X;
                     this.scaleTransform.ScaleY *= e.DeltaManipulation.Scale.Y;
                     this.scaleTransform.ScaleZ *= e.DeltaManipulation.Scale.X;

                     this._angleBuffer++;
                     if (_angleBuffer >= 0)
                     {
                           Vector delta = e.DeltaManipulation.Translation;
                this.RotateEarth(delta);
            }
            e.Handled = true;
              }

        private void RotateEarth(Vector delta)
        {
            if (delta.X != 0 || delta.Y != 0)
            {
                Vector3D vOriginal = new Vector3D(-delta.X, delta.Y, 0d);
                Vector3D vZ = new Vector3D(0, 0, 1);
                Vector3D perpendicular = Vector3D.CrossProduct(vOriginal, vZ);
                RotateTransform3D rotate = new RotateTransform3D();
                QuaternionRotation3D quatenion = new QuaternionRotation3D();
                quatenion.Quaternion = new Quaternion(perpendicular, 3);
                rotate.Rotation = quatenion;
                this.transformGroup.Children.Add(rotate);
                this._angleBuffer = 0;
            }
        }




              private void OnTouchUp(object sender, TouchEventArgs e)
              {           
            DoHitTest(e.GetTouchPoint(this.viewport).Position);
              }



        private void DoHitTest(Point point)
        {
            VisualTreeHelper.HitTest(this.viewport, null, new HitTestResultCallback(target =>
            {
                RayMeshGeometry3DHitTestResult result = target as RayMeshGeometry3DHitTestResult;
                if (result != null)
                {
                    Point p1 = result.MeshHit.TextureCoordinates[result.VertexIndex1];
                    Point p2 = result.MeshHit.TextureCoordinates[result.VertexIndex2];
                    Point p3 = result.MeshHit.TextureCoordinates[result.VertexIndex3];
                    double hitX = p1.X * result.VertexWeight1 + p2.X * result.VertexWeight2 + p3.X * result.VertexWeight3;
                    double hitY = p1.Y * result.VertexWeight1 + p2.Y * result.VertexWeight2 + p3.Y * result.VertexWeight3;
                    Point pointHit = new Point(hitX * _imageWidth, hitY * _imageHeight);

                    foreach (DataCenter dc in this._dataCenters)
                    {
                        if (dc.Bound.Contains(pointHit))
                        {
                            this.InfoTextBox.Text = "You've just touched the " + dc.Name + " data center!";
                            Storyboard sb = this.Resources["sb"] as Storyboard;
                            if (sb != null)
                            {
                                sb.Begin();
                            }
                            return HitTestResultBehavior.Stop;
                        }
                    }
                }
                return HitTestResultBehavior.Continue;
            }), new PointHitTestParameters(point));
        }


        void Touch_FrameReported(object sender, TouchFrameEventArgs e)
        {
            var touchPoints = e.GetTouchPoints(this.viewport);
            if (touchPoints.Count >= 2 && touchPoints[0].Action == TouchAction.Up)
            {
                this.TouchLine.X1 = touchPoints[0].Position.X;
                this.TouchLine.X2 = touchPoints[1].Position.X;
                this.TouchLine.Y1 = touchPoints[0].Position.Y;
                this.TouchLine.Y2 = touchPoints[1].Position.Y;
            }
        }

              private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
              {
                     this._isMouseDown = true;
            this._startPoint = e.GetPosition(this.viewport);
              }

              private void Grid_MouseMove(object sender, MouseEventArgs e)
              {
                     if (this._isMouseDown && this.MouseSimulationCheckBox.IsChecked.Value)
                     {
                this._angleBuffer++;
                if (_angleBuffer >= 0)
                {
                    Point currentPoint = e.GetPosition(this.viewport);
                    Vector delta = new Vector(currentPoint.X - this._startPoint.X, currentPoint.Y - this._startPoint.Y);
                    RotateEarth(delta);
                }
                     }
              }

              private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
              {
                     this._isMouseDown = false;
            if (this.MouseSimulationCheckBox.IsChecked.Value)
            {
                this.DoHitTest(e.GetPosition(this.viewport));
            }
              }

        private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (this.MouseSimulationCheckBox.IsChecked.Value)
            {
                double delta = e.Delta > 0 ? 1.2 : 0.8;
                this.scaleTransform.ScaleX *= delta;
                this.scaleTransform.ScaleY *= delta;
                this.scaleTransform.ScaleZ *= delta;
            }
        }
       }
}




 From this article i hope you will learn how to create a 3D view.


No comments:

Post a Comment