MouseRotationController.cs
上传用户:huazai0421
上传日期:2008-05-30
资源大小:405k
文件大小:4k
源码类别:

SilverLight

开发平台:

C#

  1. // Silver.Globe, version 0.11 for Silverlight 1.1 Alpha
  2. // Copyright © Florian Krüsch (xaml-kru.com)
  3. // xaml-kru.com/silverglobe
  4. // This source is subject to the Microsoft Public License (Ms-PL).
  5. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx.
  6. // All other rights reserved.
  7. using System;
  8. using System.Windows;
  9. using SilverGlobe.Math3D;
  10. using System.Windows.Input;
  11. namespace SilverGlobe
  12. {
  13.     /// <summary>
  14.     /// MouseRotationController controls the globe by rotating it towards the current mouse position.
  15.     /// </summary>
  16.     internal sealed class MouseRotationController
  17.     {
  18.         #region Members
  19.         private Boolean _start = false;
  20.         private Vector _position;
  21.         private DateTime _lastTime;
  22.         private Double _speed = 0d;
  23.         private Vector3D _rotationAxis = Vector3D.YAxis * -1;
  24.         private Globe _globe;
  25.         private FrameworkElement _mouseEventSource;
  26.         #endregion
  27.         #region Properties
  28.         public Vector3D Axis
  29.         {
  30.             get { return _rotationAxis; }
  31.         }
  32.         #endregion
  33.         #region Constructor
  34.         public MouseRotationController(Globe globe)
  35.         {
  36.             _globe = globe;
  37.             _mouseEventSource = (FrameworkElement)Application.Current.RootVisual;
  38.         }
  39.         #endregion
  40.         #region Methods
  41.         /// <summary>
  42.         /// Start controlling the globe.
  43.         /// </summary>
  44.         public void Init()
  45.         {
  46.             _lastTime = DateTime.Now;
  47.             _position = Vector.Empty;
  48.             _start = true;
  49.             _speed = 0d;
  50.             _mouseEventSource.MouseMove -= MouseMove_Rotate;
  51.             _mouseEventSource.MouseMove += MouseMove_Rotate;
  52.         }
  53.         /// <summary>
  54.         /// Stop controlling the globe.
  55.         /// </summary>
  56.         public void End()
  57.         {
  58.             _mouseEventSource.MouseMove -= MouseMove_Rotate;
  59.         }
  60.         /// <summary>
  61.         /// Get the current rotation speed.
  62.         /// </summary>
  63.         public Double GetSpeed()
  64.         {
  65.             Double speed = _speed;
  66.             _speed = 0d;
  67.             return speed;
  68.         }
  69.         #endregion
  70.         #region Implementation
  71.         private void MouseMove_Rotate(object sender, MouseEventArgs e)
  72.         {
  73.             // mouse position relativ to Globe's center
  74.             Vector mousePos = new Vector(e.GetPosition(_globe)) - new Vector(_globe.Width / 2, _globe.Height / 2);
  75.             if (_start)
  76.             {
  77.                 _start = false;
  78.                 _position = mousePos;
  79.                 return;
  80.             }
  81.             // position
  82.             Vector oldPos = _position;                        
  83.             // time difference
  84.             DateTime now = DateTime.Now;
  85.             Double dt = (now - _lastTime).TotalSeconds;
  86.             _lastTime = now;
  87.             // smoothed position
  88.             _position = mousePos * 0.7 + _position * 0.3;
  89.             // direction
  90.             Vector dir = _position - oldPos;
  91.             if (dir == Vector.Empty) return;
  92.             // polar coordinates of mouse position
  93.             Double angle = -Math.Atan2(_position.Y, _position.X);
  94.             Double radius = _position.Length;
  95.             Double dx;
  96.             dx = radius / _globe.ScreenRadius;
  97.             dx = dx.Clamp(0, 1) * 0.75;
  98.             dx = dx * dx;
  99.             Vector v = dir.Normalized * (1d - dx);
  100.             _rotationAxis = new Vector3D(v.Y, -v.X, v.Rotate(angle).Y * dx);
  101.             Double k = 0.2 / dt;
  102.             if (k > 1) k = 1;
  103.             _speed = dir.Length * k * 0.3;
  104.             _globe.Orientation *= Quaternion.ForRotation(_rotationAxis, _speed);
  105.             _globe.Orientation.Normalize();
  106.         }
  107.         #endregion
  108.     }
  109. }