【问题标题】:Determining Yaw and Pitch between two Vector3 point确定两个 Vector3 点之间的 Yaw 和 Pitch
【发布时间】:2014-07-12 02:23:03
【问题描述】:

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

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

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

    }
}

“lookat”方法是空白的,因为我正试图弄清楚如何去做。我移动相机,使其位置为 (500,500,500) 并需要它查看 (0,0,0) 但我不知道如何获得它们之间的偏航和俯仰,因此我可以正确设置旋转。我已经阅读了有关规范化向量和使用交叉点积的信息,但是您无法规范化 (0,0,0),因为它没有方向,所以我不知道该怎么做。任何帮助将不胜感激。

【问题讨论】:

    标签: c# xna


    【解决方案1】:

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

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

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

    如果需要,您还可以创建一个公共方法来将相机位置设置到特定位置。

    【讨论】:

    • 好的,我明白了...我考虑过简化它,因为它看起来有点臃肿且不必要。我会实现它,看看效果如何。
    • 如何向前移动相机(即它面对的方向?)。目前,如果我传入运动矢量,它会移动相机,但只能在轴上移动,而不是相机面对的方式。我还需要弄清楚相机面对的其他功能的角度,但我相信我可以使用 Target 以某种方式做到这一点。
    • 您可以添加这样的方法来向前或向后移动。 pastebin.com/YPKnM2ye
    • 确实会前后移动,但不会朝相机所面对的方向移动!我知道这是一个 FPS 相机,但它只是名字而已!我需要相机朝相机所面对的方向移动。
    • 忽略我最后的评论,使用了错误的方法。这工作正常,但我唯一真正的问题是我需要知道相机面对的方向是角度还是单位向量(如果需要,我可以用它来确定角度)。如果我得到答案,我也会对此进行探索并发布答案。
    【解决方案2】:

    首先你已经有了一个计算正确矩阵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

    【讨论】:

      猜你喜欢
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      • 2019-06-19
      • 2013-06-02
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      相关资源
      最近更新 更多