3DTools TrackballDecorator实现3D漫游
1.基本原理
WPF提供的TrackballDecorator類用來實現三維漫游功能。TrackballDecorator可以看做是在Viewport3D后面的一個虛擬球面,當鼠標點擊TraclcballDecorator投影在Viewport3D的這個平面內時,可以在球面上找到與鼠標在平面上面一一對應的一個點。當鼠標運動的時候,照相機根據鼠標的運動來旋轉,以此來保證鼠標在這個虛擬球面上的位置是不變的。這樣就完成了把把鼠標的二維運動轉換為三維運動。下面以一個立方體為模型,簡單說明一下上述過程。
圖1.1 Viewport3D與TtackballDecorator位置關系
圖1.2 鼠標垂直拖動
圖1-2表示當鼠標進行垂直移動的時候,球面繞X軸進行旋轉,來保證鼠標在球面上的位置是不變的,同時球面內的模型會跟隨球面運動,就能得到預期的效果。
2.實現過程
對于每次鼠標移動,都需要計算一個旋轉來保證鼠標在球面上的位置是不變的。因此需要做以下兩個工作:首先,確定鼠標在球面上的位置;其次,計算鼠標從一個點移動到另一個點所進行的旋轉。為了找到鼠標在球體上對應的點,將UIElement坐標系中的二維點投影到的Viewport3D內部的球面上。
(1)首先如何將二維點映射到Viewport3D內部球面呢?下面顯示了兩個坐標系。
2.1 二維坐標系
2.2 三維坐標系
如圖2-1所示,鼠標顯示了其在UIElement坐標系中的位置,原點(0,0)位于坐標系的左上角。在圖2-2中把鼠標映射到Viewport3D內部的球面上,鼠標的坐標也變換為了三維坐標系中的坐標。
由于最終的目的是得到相機的旋轉,因此可以選擇最簡單的TrackballDecorator球面坐標系,因此可以假定這個球面半徑為1,其圓心為坐標系的原點(0,0,0)。只需要構建一個[0,0]—[2,2]的Viewport3D,然后將原點從左上角移動至中心,這樣 ViewportsD 就變成了從[-1,1]一[1,-1]。如圖 2-3,圖 2-4 所示。
2.3 建一個寬、高為2的Viewport3D
2.4 將原點平移至中心
假設鼠標在UIElement坐標系的坐標為(Px, Py),在TrackballDecorator坐標系中的坐標為(x,y, z)那么可得出x,y點坐標如式2-1,2-2所示。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
根據球面半徑,就能得到Z坐標如式2-3所示。
獲取三維坐標信息代碼:
private Vector3D ProjectToTrackball(double width, double height. Point point) { double X = point.X / (width / 2); double y = point. Y / (height / 2); X = X - 1; y = 1 - y; double z2=l-x*x-y*y; double z = z2 > 0 ? Math.Sqrt(z2): 0; return new Vector3D(x, y, z); }這樣就得到了鼠標在球面上的坐標(x,y,z)對于鼠標的每次拖動,都需要構建一個旋轉,使得鼠標在球面上的位置保持不變。因此需要記錄鼠標拖動之前的坐標,和鼠標拖動到當前位置的旋轉。為了得到這個旋轉需要計算旋轉軸和旋轉角度。
2.3用向量來描述鼠標的拖動
如圖2.3所示向量VI和向量V2分別為原點到鼠標拖動前所在位置和拖動后所在位置的向量。可以簡單計算得到旋轉軸Axis和旋轉角度0,如式2-4、2-5所示。
//根據右手定則,兩向量叉乘,確定垂直兩向量的軸,即旋轉軸
Θ為球面的旋轉角度,取Θ的相反數就得到了照相機的旋轉角度,當有了旋轉軸和旋轉角度就可以控制的照相機去進行旋轉。
//響應漫游
private void Track(Point currentPosition) { Vector3D currentPosition3D =ProjectToTrackball( EventSource.Actual Width,EventSource.ActualHeight, currentPosition);Vector3D axis =Vector3D.CrossProduct(_previousPosition3D, currentPosition3D); double angle =Vector3D.AngleBetween(_previousPosition3D, currentPosition3D); Quaternion delta = new Quaternion(axis, -angle); AxisAngleRotation3D r = _rotation; Quaternion q = new Quatemion(_rotation.Axis, _rotation.Angle); q*= delta; _rotation.Axis = q.Axis; _rotation.Angle = q.Angle; _previousPosition3 D = currentPosition3D; } 3.源代碼點擊打開鏈接
總結
以上是生活随笔為你收集整理的3DTools TrackballDecorator实现3D漫游的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zeppelin--使用D-Tale,针
- 下一篇: 几经沉浮,人工智能(AI)前路何方?