WPF 3D 平移模型+動畫


關於WPF 3D,網上有很多旋轉的例子,但是關於平移的例子並不是太多。本文並非WPF 3D掃盲篇,因此需要對WPF 3D有一定了解,至少知道Viewport, PerspectiveCamera, ModelVisual3D等數據結構。需要了解WPF 3D的基礎知識,可以參考MSDN: http://msdn.microsoft.com/zh-cn/library/ms747437.aspx

 

1. 攝像機平移OR物體平移:

WPF場景主要是由這兩部分構成的:攝像機,物體。可以想象一下,自己拿着台攝像機正對着某個物體進行拍攝。

那么當發生平移的時候有兩種方法,第一種是將攝像機平移;第二種是將物體平移。相對來說,攝像機平移實現較復雜,效率較高;物體平移效率較低,實現簡單。

本文實現的是物體平移,如果希望做攝像機平移的朋友可以不往下讀了。

 

2. 在本項目中平移的操作流程: 

1. 程序啟動時可以看到整個3D場景,類似一個沙盤,此時旋轉等操作會圍繞沙盤中心;

2. 雙擊沙盤某個地方,將沙盤中心移動到雙擊的地方,此時旋轉等操作會圍繞新的沙盤中心。

 

3. 平移的算法:

1.獲取雙擊屏幕后鼠標在3D中相對應的點,主要利用了射線和3D碰撞的一個原理。代碼上主要應用的就是VisualTreeHelper.HitTest函數,它會將結果傳入一個回調函數中,我們這里是HTResultCenter.

void BridgeVisual_MouseDoubleClick(object sender, MouseButtonEventArgs args)
 

     Point mouseposition = args.GetPosition(ViewPort);

   MoveCenter(mouseposition);

}

 

 public void MoveCenter(Point mouseposition)
 {
      PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);
      VisualTreeHelper.HitTest(ViewPort, null, HTResultCenter, pointparams);

 } 

 

 private HitTestResultBehavior HTResultCenter(HitTestResult result)
 {
      RayHitTestResult rayResult = result as RayHitTestResult;
      if (rayResult != null)
      {
           //這就是鼠標點擊后在3D中的坐標
           var hitPoint = rayResult.PointHit;
           ...

      }

 } 

 

2.根據相機位置 + 相機的投射方向 = 獲取相機在3D上投影的點,camera.Postion就是攝像機在3D世界中的位置了,camera.LookDirection就是攝像機看的方向。那么兩者加起來就可以獲取這個攝像機投射過后的位置了。 

 

   /// /相機位置
   var cameraPostion = Camera.Position;
               
   /// /相機看的方向
   var lookDirection = Camera.LookDirection;

   ///  獲取相機在3D投影的點 
   var x = cameraPostion.X + lookDirection.X;
   var y = cameraPostion.Y + lookDirection.Y;
   var z = cameraPostion.Z + lookDirection.Z;

 

 

3. 那么利用攝像機投射的位置 - 鼠標雙擊的位置就可以獲取物體應該偏移的量了,WPF中本來就有Transform3D 這個東西進行平移,
此處應用了動畫DoubleAnimation,所以代碼有點多。

DoubleAnimation doubleAnimationX =  new DoubleAnimation();
doubleAnimationX.BeginTime =  new TimeSpan( 000);
doubleAnimationX.Duration = TimeSpan.FromMilliseconds( 500);
doubleAnimationX.From = Transform3D.OffsetX;
doubleAnimationX.To = x - hitPoint.X;

DoubleAnimation doubleAnimationY =  new DoubleAnimation();
doubleAnimationY.BeginTime =  new TimeSpan( 000);
doubleAnimationY.Duration = TimeSpan.FromMilliseconds( 500);
doubleAnimationY.From = _Transform3D.OffsetY;
doubleAnimationY.To = y - hitPoint.Y;

DoubleAnimation doubleAnimationZ =  new DoubleAnimation();
doubleAnimationZ.BeginTime =  new TimeSpan( 000);
doubleAnimationZ.Duration = TimeSpan.FromMilliseconds( 500);
doubleAnimationZ.From = Transform3D.OffsetZ;
doubleAnimationZ.To = z - hitPoint.Z;

Transform3D.BeginAnimation(TranslateTransform3D.OffsetXProperty, doubleAnimationX);
Transform3D.BeginAnimation(TranslateTransform3D.OffsetYProperty, doubleAnimationY);  

Transform3D.BeginAnimation(TranslateTransform3D.OffsetZProperty, doubleAnimationZ);  

 

 

4. 最終的效果:

1.平移前:

 

 2.平移后:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM