简体   繁体   中英

Matrices in XNA (3D - Game) for Camera rotation

I have written this code for rotating and moving the camera.
Sadly, I am not very experianced with matrices and 3D programming, since I started only a few days ago:

plLookAt = new Vector3(plPos.X, plPos.Y, plPos.Z - 20);    
if (kb.IsKeyDown(Keys.W))
        {
            plPos.Z++;
        }
        if (kb.IsKeyDown(Keys.A))
        {
            plPos.X++;
        }
        if (kb.IsKeyDown(Keys.S))
        {
            plPos.Z--;
        }
        if (kb.IsKeyDown(Keys.D))
        {
            plPos.X--;
        }
        view = Matrix.CreateLookAt(new Vector3(0, 0, 0), plLookAt, Vector3.UnitY);
        view = view * Matrix.CreateRotationY(MathHelper.ToRadians(rotations.Y)) * Matrix.CreateRotationX(MathHelper.ToRadians(rotations.X));
        view = view *Matrix.CreateTranslation(plPos);

        if (PrMS.X < ms.X)
        {
            rotations.Y++;
        }
        else if (PrMS.X > ms.X)
        {
            rotations.Y--;
        }
        if (PrMS.Y < ms.Y)
        {
            rotations.X++;
        }
        else if (PrMS.Y > ms.Y)
        {
            rotations.X--;
        }    

plPos is the Player (camera) position
view is the view Matrix
rotations is where the rotation of the camera is saved (Vector3)
PrMS is the MouseState of the previous frame.
This code doesn't work and I think it is because of the order, which the multiplications are in, but I'm not sure. What is the best way of rotating the camera, so that it actually works and I can go in the direction the camera is facing. Thank You in advance!

Your problem is not in the order of the matrix multiplication, it is that your rotations need to be around camera local axes and your are performing them around world axes.

I think that what you are expecting is that applying .CreateRotationX(rotations.X) and .CreateRotationY(rotationsY) will cause the camera to change pitch and yaw about it's own local axis. But these rotations always cause a rotation about the world axis. If your camera's local X axis just happens to be aligned with the world X axis and you performed a .CreateRotationX() , then it would work as expected. But in your case, you are rotating the camera about the Y axis first and this is throwing the camera's local X axis out of alignment with the world X axis so the next rotation (the X) is not going to go as expected. Even if you did the X first and the Y second, the X would throw the Y out of whack. Although the order of matrix multiplication does matter in general, in your particular case, it is the axis of rotation that is the problem.

It appears you are making a camera that is located at your player's position but can look left/right, up/down by mouse control. Here is a class that offers a different way to approach that criteria:

class Camera
{
    public Matrix View { get; set; }
    public Matrix Projection { get; set; }

    Vector2 centerOfScreen;// the current camera's lookAt in screen space (since the mouse coords are also in screen space)
    Vector3 lookAt;

    float cameraRotationSpeed;



    public Camera()
    {
        //initialize Projection matrix here
        //initialize view matrix here 
        //initialize centerOfScreen here like this:  new Vector2(screenWidth/2, screenHeihgt/2); 
        cameraRotationSpeed = 0.01f;//set to taste
    }



    public void Update(Vector3 playerPosition, MouseState currentMouse)
    {
        Matrix cameraWorld = Matrix.Invert(View);

        Vector2 changeThisFrame = new Vector2(currentMouse.X, currentMouse.Y) - centerOfScreen;

        Vector3 axis = (cameraWorld.Right * changeThisFrame.X) + (cameraWorld.Up * changeThisFrame.Y);//builds a rotation axis based on camera's local axis, not world axis

        float angle = axis.Length() * cameraRotationSpeed;
        axis.Normalize();

        //rotate the lookAt around the camera's position
        lookAt = Vector3.Transform(lookAt - playerPosition, Matrix.CreateFromAxisAngle(axis, angle)) + playerPosition;//this line does the typical "translate to origin, rotate, then translate back" routine

        View = Matrix.CreateLookAt(playerPosition, lookAt, Vector3.Up);// your new view matrix that is rotated per the mouse input

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM