矩阵在XNA (3D -游戏)为相机旋转

本文关键字:游戏 相机 旋转 3D XNA | 更新日期: 2023-09-27 18:06:25

我已经为旋转和移动摄像机编写了这段代码。
遗憾的是,我对矩阵和3D编程不是很有经验,因为我几天前才开始:

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是Player (camera)的位置
view是视图矩阵
rotate是保存摄像机旋转的位置(Vector3)
PrMS是前一帧的MouseState。
这段代码不起作用,我认为这是因为乘法的顺序,但我不确定。旋转相机的最佳方式是什么,这样它才能正常工作,我才能朝着相机的方向移动。提前感谢!

矩阵在XNA (3D -游戏)为相机旋转

你的问题不在于矩阵乘法的顺序,而是你的旋转需要围绕相机本地轴,而你正在围绕世界轴执行它们。

我认为你所期望的是应用.CreateRotationX(rotations.X).CreateRotationY(rotationsY)将导致相机改变俯仰和偏航关于它自己的本地轴。但是这些旋转总是引起绕世界轴的旋转。如果你的相机的本地X轴恰好与世界X轴对齐,并且你执行了.CreateRotationX(),那么它将像预期的那样工作。但在你的情况下,你首先围绕Y轴旋转摄像机,这会使摄像机的局部X轴与世界X轴不对齐,所以下一次旋转(X)不会像预期的那样进行。即使你先做X,后做Y, X也会把Y弄乱。虽然矩阵乘法的顺序通常很重要,但在你的特殊情况下,问题是旋转轴。

看起来你正在制作一个位于玩家位置的摄像机,但可以通过鼠标控制向左/向右,向上/向下看。下面是一个类,它提供了一种不同的方法来实现这个标准:

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