移动PerspectiveCamera在它面临的方向C#

问题描述:

我目前在一个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; 
    } 

旋转运算完美的作品,但运动似乎没有工作好,因为它基于摄像头的位置,而不是旋转后面对的方向移动相机。

注释掉的代码看起来或多或少是正确的......你没有说出它有什么问题。你有没有试图规范化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

谢谢。你能解释旋转部分的代码吗?因为我从互联网上获得了这些代码,我不完全明白它究竟做了什么。只需简单解释一下。非常感谢。 –