确定两个Vector3点之间的偏航和俯仰
本文关键字:之间 Vector3 两个 | 更新日期: 2023-09-27 18:11:58
我读过各种各样的方法来确定两个向量之间的角度,我真的很困惑,所以我需要一些帮助来理解我需要做什么。
下面是我的第一人称相机代码
public class FPSCamera : Engine3DObject
{
public Matrix View { get; private set; }
public Matrix Projeciton { get; private set; }
private Quaternion rotation;
private float yaw;
private float pitch;
private bool isViewDirty;
private bool isRotationDirty;
public BoundingFrustum Frustum { get; private set; }
public bool Changed { get; private set; }
public Vector3 ForwardVector
{
get
{
return this.View.Forward;
}
}
public FPSCamera()
: base()
{
this.Position = Vector3.Zero;
this.rotation = Quaternion.Identity;
this.yaw = this.pitch = 0;
this.isViewDirty = true;
this.isRotationDirty = false;
}
public void SetPosition(Vector3 position)
{
this.Position = position;
this.isViewDirty = true;
this.Update(null);
}
public void Initialize(float aspectRatio)
{
this.Projeciton = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 1f, 1000f);
}
public void Update(GameTime gameTime)
{
this.Changed = false;
if (isRotationDirty)
{
if (yaw > MathHelper.TwoPi)
{
yaw = yaw - MathHelper.TwoPi;
}
if (yaw < -MathHelper.TwoPi)
{
yaw = yaw + MathHelper.TwoPi;
}
if (pitch > MathHelper.TwoPi)
{
pitch = pitch - MathHelper.TwoPi;
}
if (pitch < -MathHelper.TwoPi)
{
pitch = pitch + MathHelper.TwoPi;
}
this.rotation = Quaternion.CreateFromYawPitchRoll(yaw, pitch, 0);
this.isRotationDirty = false;
this.isViewDirty = true;
this.Changed = true;
}
if (isViewDirty)
{
Vector3 up = Vector3.Transform(Vector3.Up, rotation);
Vector3 target = Vector3.Transform(Vector3.Forward, rotation) + Position;
this.View = Matrix.CreateLookAt(this.Position, target, up);
this.isViewDirty = false;
if (this.Frustum == null)
{
this.Frustum = new BoundingFrustum(this.View * this.Projeciton);
}
else
{
this.Frustum.Matrix = (this.View * this.Projeciton);
}
this.Changed = true;
}
}
public void Move(Vector3 distance)
{
this.Position += Vector3.Transform(distance, rotation);
this.isViewDirty = true;
}
public void Rotate(float yaw, float pitch)
{
this.yaw += yaw;
this.pitch += pitch;
this.isRotationDirty = true;
}
public void LookAt(Vector3 lookAt)
{
}
}
"look"方法是空白的,因为我正在试图弄清楚如何做到这一点。我移动相机,所以它的位置是(500,500,500),需要它看(0,0,0),但我不知道如何获得它们之间的偏航和俯仰,所以我可以设置正确的旋转。我读过关于向量的归一化以及使用叉乘和点积,但是你不能归一化(0,0,0)因为它没有方向所以我有点不知所措。
似乎你希望能够以两种不同的方式操作你的相机:
1)。增加或减少一点偏航或俯仰,并让相机做出相应的反应。2)。让相机看一个已知的位置,然后计算俯仰角和偏航角,这样你就可以在随后的帧中做#1,如果需要的话。
我认为是什么使它对你来说很困难的是,你想要存储整体的俯仰角和偏航角供以后使用。你可能会听到一些经验丰富的3d程序说,如果你认为你需要存储角度,你可能做错了什么(这篇博客的最后一段)。无论如何,如果你可以放弃这些角度,你的相机类会简单得多。这里有一个例子。这两种公共方法允许你通过1.)添加俯仰、偏航或平移来操纵相机,或者2.)将其设置为观察世界中的特定点。它还允许您在任何时候使用任何一种方法。由于不考虑绝对俯仰角和偏航角,所以代码要简单得多。
namespace WindowsGame1
{
class FPSCamera
{
public Matrix View;
public Matrix Proj;
public Vector3 Position, Target;
public FPSCamera(float aspect)
{
Proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect, 1f, 1000f);
Target = Vector3.Forward;
SetViewMatrix();
}
public void UpdateCameraByPitchYawTranslation(float amountToPitchThisFrame, float amountToYawThisFrame, Vector3 amountToTranslateThisFrame)
{
Position += amountToTranslateThisFrame;
Target += amountToTranslateThisFrame;
Matrix camera = Matrix.Invert(View);
Target = Vector3.Transform(Target - Position, Matrix.CreateFromAxisAngle(camera.Right, amountToPitchThisFrame)) + Position;
Target = Vector3.Transform(Target - Position, Matrix.CreateFromAxisAngle(Vector3.Up, amountToYawThisFrame)) + Position;
SetViewMatrix();
}
public void SetCameraToLookAtSpecificSpot(Vector3 spotToLookAt)
{
Target = spotToLookAt;
SetViewMatrix();
}
private void SetViewMatrix()
{
View = Matrix.CreateLookAt(Position, Target, Vector3.Up);
}
}
}
如果你想的话,你也可以创建一个公共方法来设置摄像头的位置。
首先你已经有了一个计算适当矩阵Matrix.CreateLookAt(this.Position, target, up)
的方法。此方法创建合适的矩阵。
除此之外,你想要的工作不是一个观察位置点,而是从相机到观察点的方向。在你的例子中,它是[0,0,0]-[500,500,500]。你还需要"上"方向来计算角度的缠绕方向。
这里有相关的讨论:计算LookAt矩阵
这里你有更多关于变换矩阵的解释:http://www.math.washington.edu/王/coursedir m308a01/项目/m308a01-pdf/yip.pdf