将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));
这部分工作,相机现在可以飞到空中。但这是不对的,无论你把相机"向上"倾斜多远,它都会向前移动相同的量。向上不是取代正向,而是加在正向上。
我希望这个解释是有意义的。谢谢
你可以这样做:首先从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);
}