确定两个Vector3点之间的偏航和俯仰

时间:2014-07-08 20:46:13

标签: c# xna

我已经阅读了各种各种方法来确定两个向量之间的角度,我真的很困惑所以我需要一些帮助才能理解我需要做什么。

以下是我的第一人称相机代码

 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)
    {

    }
}

&#34; lookat&#34;方法是空白的,因为我试图找出如何做到这一点。我移动相机所以它的位置是(500,500,500)并且需要它来看(0,0,0)但是我无法弄清楚如何在它们之间获得偏航和俯仰以便我可以设置旋转正确。我已经阅读了有关矢量标准化和使用十字和点积的信息,但是你无法规范化(0,0,0),因为它没有方向所以我有点迷失了什么到做。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

首先,您已经有了一个计算正确矩阵Matrix.CreateLookAt(this.Position, target, up)的方法。这种方法可以创建合适的矩阵。

除此之外,你想要合作的不是一个看起来的位置,而是从相机到看点的方向。所以在你的情况下,它将是[0,0,0] - [500,500,500]。您还需要“向上”方向来确定角度的缠绕方向。

在这里你有相关的讨论: Calculating a LookAt matrix

在这里你对转换矩阵有了更多的解释: http://www.math.washington.edu/~king/coursedir/m308a01/Projects/m308a01-pdf/yip.pdf

答案 1 :(得分:0)

您似乎希望能够以两种不同的方式操作相机:

1。)增加或减少一点偏航或俯仰,让相机做出相应的反应 2.)让相机查看已知位置,然后返回计算俯仰和偏航角度,以便在需要时可以在后续帧上执行#1。

我认为让你感到困难的是你想要存储整体俯仰角和偏航角以供以后使用。您可能会听到一些有经验的3D程序说如果您认为需要存储角度,那么您可能做错了(last paragraph in this blog)。无论如何,如果你可以放开那些角度,你的相机类将会简单得多。这是一个例子。这两种公共方法允许您通过以下方式对摄像机进行操作: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);
        }

    }
}

如果需要,您还可以使用公共方法将相机位置设置为特定位置。