0

I've read all kinds of various methods to determine the angle between two vectors and I'm really confused so I need some help to understand what I need to do.

Below is my First-person camera code

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

    }
}

The "lookat" method is blank because I'm trying to figure out how to do it. I move the camera so it's position is (500,500,500) and need it to look at (0,0,0) but I can't figure out how to get the yaw and pitch between them so I can set the rotation correctly. I've read about normalizing the vectors and using the cross and dot product, but you can't normalize (0,0,0) as it has no direction so I'm a bit lost as to what to do. Any help would be appreciated.

mikelomaxxx14
  • 133
  • 12

2 Answers2

0

First thing you already have a method which calculates proper matrix Matrix.CreateLookAt(this.Position, target, up). This method creates proper matrix.

Aside from that you want to work with is not a looking position point rather direction from camera to looking point. So in your case it would be [0, 0, 0] - [500, 500, 500]. You'll also need "up" direction to figure out the winding direction of angles.

Here you have related discusscion: Calculating a LookAt matrix

And here you have a bit more explanation about transformation matrices: http://www.math.washington.edu/~king/coursedir/m308a01/Projects/m308a01-pdf/yip.pdf

Community
  • 1
  • 1
blazejmar
  • 1,080
  • 8
  • 10
0

It seems like you want to be able to manipulate your camera in 2 different ways:

1.) Add or subtract a little yaw or pitch and have the camera respond accordingly.
2.) Have the camera look at a known position and then back calculate the pitch and yaw angles so you can do #1 on subsequent frames if desired.

I think what is making it difficult for you is that you want to store the overall pitch and yaw angles for later use. You might hear hear some experienced 3d programmes say that if you think you need to store angles, you're probably doing something wrong (last paragraph in this blog). Anyways, if you can let go of those angles, you camera class will be much simpler. Here is an example. These 2 public methods allow you to maipulate the camera by either 1.) adding pitch, yaw, or translation or 2.) by setting it to look at a specific point in the world. It also allows you to use either method at any time. By not having the concern of the absolute pitch and yaw angles, the code is much simpler.

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);
        }

    }
}

You could also make a public method to set the camera position to a specific location if you wanted.

Steve H
  • 5,479
  • 4
  • 20
  • 26
  • Ok, I see... I have thought of simplifying it as it seemed a bit bloated and unnecessary. I'll implement it and see how it goes. – mikelomaxxx14 Jul 15 '14 at 12:50
  • How do I move the camera forward (i.e. the direction it is facing?). At the moment if I pass in the movement vector it moves the camera but only on the axis, not the the way the camera if facing. I will also need to figure out what angle the camera is facing for other functions but I believe I can do that using the Target somehow. – mikelomaxxx14 Jul 15 '14 at 20:11
  • you can add a method like this to move forward or backward. http://pastebin.com/YPKnM2ye – Steve H Jul 16 '14 at 02:37
  • That does move it forwards and backwards, but not in the direction the camera is facing! I know it's a FPS camera, but it's only by name only! I need the camera to move in the direction the camera is facing. – mikelomaxxx14 Jul 19 '14 at 20:20
  • Ignore my last comment, was using the wrong method. This works ok, but the only real problem I have is that i need to know which direction the camera is facing as either an angle or unit vector (which I can use to determine the angle if need be). I'll explore this as well and post an answer if I get one. – mikelomaxxx14 Jul 19 '14 at 20:42
  • the unit vector that is pointing in the direction that the camera is facing is `Matrix.Invert(View).Forward` – Steve H Jul 20 '14 at 17:03
  • Yeah, I was having a funny day yesterday. Think I left my brain somewhere... Thank you! – mikelomaxxx14 Jul 20 '14 at 20:04