2017-04-12 19 views
1

我目前在一個wpf應用程序,其中有一個Viewport3D相機。 我正在創建一個3D漫遊模塊。 我希望我的PerspectiveCamera根據它在朝向改變後面對的方向移動。 我用我的鍵盤來控制運動,例如:
NUMPAD8:前進
NUMPAD2:向後移動
NUMPAD4:向左旋轉
NUMPAD6:向右旋轉移動PerspectiveCamera在它面臨的方向C#

下面這種方法是檢測鍵盤事件:

private void button20_KeyDown(Object sender, KeyEventArgs e) 
    { 
     if (e.Key == Key.NumPad6) 
     { 
      Rotate(1); 
     } 
     else if (e.Key == Key.NumPad4) 
     { 
      Rotate(-1); 
     } 
     else if (e.Key == Key.NumPad8) 
     { 
      Move(-10); 
     } 
     else if (e.Key == Key.NumPad2) 
     { 
      Move(10); 
     } 
    } 

這是計算旋轉:

public void Rotate(double d) 
    { 
     double u = 0.05; 
     double angleD = u * d; 
     PerspectiveCamera camera = (PerspectiveCamera)Viewport3D.Camera; 
     Vector3D lookDirection = camera.LookDirection; 
     double L = lookDirection.Length; 
     double D = 2 * L * Math.Sin(angleD/2); 
     double m = Math.Sqrt(lookDirection.X * lookDirection.X + lookDirection.Y * lookDirection.Y); 
     double angleA = 2 * Math.Asin(D/(2 * m)); 
     double x = lookDirection.X; 
     double y = lookDirection.Y; 
     double angleB = Math.Atan2(y, x); 
     double angleG = angleB - angleA; 
     double newx = m * Math.Cos(angleG); 
     double newy = m * Math.Sin(angleG); 
     Vector3D NewlookDirection = new Vector3D(newx, newy, lookDirection.Z); 
     camera.LookDirection = NewlookDirection; 

    } 

這是計算攝像機的運動:

public void Move(double d) 
    { 
     double u = 0.05; 
     PerspectiveCamera camera = (PerspectiveCamera)Viewport3D.Camera; 
     Vector3D lookDirection = camera.LookDirection; 
     Point3D position = camera.Position; 
     //Point3D NewPosition = new Point3D(); 
     position.Y += d; 
     //NewPosition.X = position.X + u * lookDirection.X * d; 
     //NewPosition.Y = position.Y + u * lookDirection.Y * d; 
     //NewPosition.Z = position.Z + u * lookDirection.Z * d; 
     //camera.Position = NewPosition; 
     camera.Position = position; 
    } 

旋轉運算完美的作品,但運動似乎沒有工作好,因爲它基於攝像頭的位置,而不是旋轉後面對的方向移動相機。

回答

1

註釋掉的代碼看起來或多或少是正確的......你沒有說出它有什麼問題。你有沒有試圖規範化lookDirection向量?歸一化矢量使其具有1

public void Move(double d) 
{ 
    double u = 0.05; 
    PerspectiveCamera camera = (PerspectiveCamera)Viewport3D.Camera; 
    Vector3D lookDirection = camera.LookDirection; 
    Point3D position = camera.Position; 

    lookDirection.Normalize(); 
    position = position + u * lookDirection * d; 

    camera.Position = position; 
} 

UPDATE的幅度(長度):

private void Window_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.NumPad6) 
    { 
     Rotate(10); 
    } 
    else if (e.Key == Key.NumPad4) 
    { 
     Rotate(-10); 
    } 
    else if (e.Key == Key.NumPad8) 
    { 
     Move(-10); 
    } 
    else if (e.Key == Key.NumPad2) 
    { 
     Move(10); 
    } 
    else if (e.Key == Key.PageUp) 
    { 
     RotateVertical(10); 
    } 
    else if (e.Key == Key.PageDown) 
    { 
     RotateVertical(-10); 
    } 
} 
public void Rotate(double d) 
{ 
    double u = 0.05; 
    double angleD = u * d; 
    PerspectiveCamera camera = (PerspectiveCamera)Viewport3D.Camera; 
    Vector3D lookDirection = camera.LookDirection; 

    var m = new Matrix3D(); 
    m.Rotate(new Quaternion(camera.UpDirection, -angleD)); // Rotate about the camera's up direction to look left/right 
    camera.LookDirection = m.Transform(camera.LookDirection); 
} 

public void RotateVertical(double d) 
{ 
    double u = 0.05; 
    double angleD = u * d; 
    PerspectiveCamera camera = (PerspectiveCamera)Viewport3D.Camera; 
    Vector3D lookDirection = camera.LookDirection; 

    // Cross Product gets a vector that is perpendicular to the passed in vectors (order does matter, reverse the order and the vector will point in the reverse direction) 
    var cp = Vector3D.CrossProduct(camera.UpDirection, lookDirection); 
    cp.Normalize(); 

    var m = new Matrix3D(); 
    m.Rotate(new Quaternion(cp, -angleD)); // Rotate about the vector from the cross product 
    camera.LookDirection = m.Transform(camera.LookDirection); 
} 
+0

感謝很多的解決方案,但你的解決方案與註釋掉的代碼類似的東西。 註釋掉的部分就像放大和縮小面向的方向。例如,如果我繼續放大,它最終會逐步穿過地板。 我想要的就像一個沉浸式演練。就像3D環境中用戶視圖的第一個視角一樣。更簡單的話,用戶就像走在3D環境中。 –

+0

Wpf只做渲染。你需要建立一個碰撞引擎或者使用現有的像Bullet Physics。它有一個c#包裝,BulletSharp - https://andrestraks.github.io/BulletSharp/ –

+0

謝謝。你能解釋旋轉部分的代碼嗎?因爲我從互聯網上獲得了這些代碼,我不完全明白它究竟做了什麼。只需簡單解釋一下。非常感謝。 –