将FPS地面相机转换为FPS自由飞行相机

本文关键字:FPS 相机 自由 飞行 转换 面相 | 更新日期: 2023-09-27 18:13:45

我在我的OpenGL(openTk)项目中实现了一个相机

      //Move(0f, 0.1f, 0f); }    Forward
      //Move(-0.1f, 0f, 0f); }   Left
      //Move(0f, -0.1f, 0f); }   Back
      //Move(0.1f, 0f, 0f); }    Right
      //Move(0f, 0f, 0.1f); }    Up
      //Move(0f, 0f, -0.1f); }   Down
    public static void Move(float x, float y, float z)
    {  
        Vector3 offset = new Vector3();
        Vector3 forward = new Vector3((float)Math.Sin((float)Orientation.X), 0, (float)Math.Cos((float)Orientation.X));
        Vector3 right = new Vector3(-forward.Z,0,forward.X);
        offset += x * right;
        offset += y * forward;
        offset.Y += z;
        offset.NormalizeFast();
        offset = Vector3.Multiply(offset, MoveSpeed);
        Position += offset;
    }

其中"Orientation"是摄像机所面对方向的x,y。"Position"是摄像机在世界中的位置,"MoveSpeed"是浮动。

这个相机很好用。但它是基于地面的。我的意思是只有摄像机方向的x值才会影响移动方向。而y值则不是。我想做一个自由飞行的相机,如果你向上看并向前按,相机就会飞到空中。

我尝试将前向声明更改为:

Vector3 forward = new Vector3((float)Math.Sin((float)Orientation.X), (float)Math.Sin((float)Orientation.Y), (float)Math.Cos((float)Orientation.X));

这部分工作,相机现在可以飞到空中。但这是不对的,无论你把相机"向上"倾斜多远,它都会向前移动相同的量。向上不是取代正向,而是加在正向上。

我希望这个解释是有意义的。

谢谢

将FPS地面相机转换为FPS自由飞行相机

你可以这样做:首先从Orientation中获得forward向量(您可以将其用于相机)。

public Vector3 getForward(Vector2 Orientation)
{  
    Vector3 forward = new Vector3(0, 1, 0);
    //X axis rotation
    forward.Z = (float)Math.Sin((float)Orientation.Y);
    forward.Y = (float)Math.Cos((float)Orientation.Y);
    //Z axis rotation
    forward.X = forward.Y*(float)Math.Sin((float)Orientation.X);
    forward.Y = forward.Y*(float)Math.Cos((float)Orientation.X);
    return forward;
}

然后移动你的相机:

public void Move(float horizontal, float strafe)
{  
    Vector3 forward=getForward(Orientation);
    //forward vector projected on XoY plane and rotated 90 degrees
    Vector3 leftXoY = new Vector3(-forward.y ,forward.x,0);
    Vector3 moveDirection = Vector3.Multiply(forward,horizontal)+Vector3.Multiply(leftXoY,strafe);
    moveDirection.Normalize();
    Position += Vector3.Multiply(moveDirection,MoveSpeed);
}

因此,如果您调用move(1,-1);将移动摄像机向前(沿着forward矢量)并向右移动。

经过长时间的摸索,我终于找到了解决方案。我不知道这是不是一种有效的方法,但它确实有效。

 public static void Move(float x, float y, float z)
    {
        Vector3 CameraTargetVector;
        CameraTargetVector.X = (float)(Math.Sin((float)Orientation.X) * Math.Cos((float)Orientation.Y));
        CameraTargetVector.Y = (float)Math.Sin((float)Orientation.Y);
        CameraTargetVector.Z = (float)(Math.Cos((float)Orientation.X) * Math.Cos((float)Orientation.Y));
        Vector3 offset = new Vector3();
        offset += x * new Vector3(-CameraTargetVector.Z, 0, CameraTargetVector.X);
        offset += y * CameraTargetVector;
        offset.Y += z;
        offset.NormalizeFast();
        Position += Vector3.Multiply(offset, MoveSpeed);
    }