我的相机出了什么问题?

时间:2011-07-25 20:36:09

标签: c# visual-studio-2010 3d xna camera

我正在将VS2010与C#和XNA 4.0一起使用。我正在关注Aaron Reed的“学习XNA 4.0”一书。我将相机游戏组件添加到我的项目中,但这个相机表现得非常奇怪。移动鼠标使其“跳跃”然后崩溃。我不知道造成这种情况的原因。它看起来代码与书中的代码几乎完全相同。它工作得更早,但现在不是,虽然我不记得我是否改变了它(我想不是)。请注意,我只在游戏中注册此组件,仅此而已。它应该工作,但事实并非如此。任何帮助都会很棒。这是代码:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace MyGame
{
    public class Camera : Microsoft.Xna.Framework.GameComponent
    {

        public Matrix View { get; protected set; }
        public Matrix Projection { get; protected set; }
        public Vector3 CameraPosition { get; protected set; }
        public Vector3 CameraDirection { get; protected set; }
        public Vector3 CameraUp { get; protected set; }
        private MouseState prevMouseState;

        public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up)
            : base(game)
        {
            // Some initialization of camera.
            CameraPosition = pos;
            CameraDirection = target - pos;
            CameraDirection.Normalize();
            CameraUp = up;
            CreateLookAt();

            Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.PiOver4,                
                (float)Game.Window.ClientBounds.Width /
                (float)Game.Window.ClientBounds.Height,
                1f, 3000f);
        }

        public override void Initialize()
        {
            // Set mouse position and do initial get state.
            Mouse.SetPosition(Game.Window.ClientBounds.Width / 2,
                Game.Window.ClientBounds.Height / 2);
            prevMouseState = Mouse.GetState();

            base.Initialize();
        }


        public override void Update(GameTime gameTime)
        {
            // Standard WSAD keyboard movement.
            if (Keyboard.GetState().IsKeyDown(Keys.W))
                CameraPosition += CameraDirection;
            if (Keyboard.GetState().IsKeyDown(Keys.S))
                CameraPosition -= CameraDirection;
            if (Keyboard.GetState( ).IsKeyDown(Keys.A))
                CameraPosition += Vector3.Cross(CameraUp, CameraDirection);
            if (Keyboard.GetState().IsKeyDown(Keys.D))
                CameraPosition -= Vector3.Cross(CameraUp, CameraDirection);

            // Yaw rotation (via mouse).
            CameraDirection = Vector3.Transform(CameraDirection,
                Matrix.CreateFromAxisAngle(CameraUp, (-MathHelper.PiOver4 / 150) *
                (Mouse.GetState().X - prevMouseState.X) 
                ));

            // Pitch rotation (via mouse).
            CameraDirection = Vector3.Transform(CameraDirection,
                Matrix.CreateFromAxisAngle(Vector3.Cross(CameraUp, CameraDirection),
                (MathHelper.PiOver4 / 100) *
                (Mouse.GetState().Y - prevMouseState.Y) 
                ));

            CameraUp = Vector3.Transform(CameraUp,
                Matrix.CreateFromAxisAngle(Vector3.Cross(CameraUp, CameraDirection),
                (MathHelper.PiOver4 / 100) *
                (Mouse.GetState().Y - prevMouseState.Y)
                ));

            prevMouseState = Mouse.GetState();

            CreateLookAt();
            base.Update(gameTime);
        }

        private void CreateLookAt()
        {
            View = Matrix.CreateLookAt(CameraPosition,
                CameraPosition + CameraDirection, CameraUp);
        }
    }
}

有人可以检查此代码是否适用于他?任何想法都会很棒!

//编辑1: 在游戏的初始化中,我使用代码:

Camera cam = new Camera(this, new Vector3(0, 0, 100), Vector3.Zero, Vector3.Up);
Components.Add(cam);

然后我画模型。我在模型的BasicEffect中使用了cam的视图和投影矩阵。

//编辑2: 有些事情是严重错误的。我做了一些调试,似乎在某些时候,这些Vector3对象的X,Y,Z属性设置为NaN。我无法知道如何以及何时。在运行一段时间之后(也许这没什么)游戏时间显示经过的游戏时间只有16毫秒(就像它跳过帧?)并且游戏运行缓慢。无论我何时调试,这16毫秒总是一样的。

我是否有可能搞砸了XNA / C#设置?如果是这样,有人可以给我任何暗示现在该做什么吗?

1 个答案:

答案 0 :(得分:2)

    // Pitch rotation (via mouse).
    CameraDirection = Vector3.Transform(CameraDirection,
        Matrix.CreateFromAxisAngle(Vector3.Cross(CameraUp, CameraDirection),
        (MathHelper.PiOver4 / 100) *
        (Mouse.GetState().Y - prevMouseState.Y) 
        ));

    CameraUp = Vector3.Transform(CameraUp,
        Matrix.CreateFromAxisAngle(Vector3.Cross(CameraUp, CameraDirection),
        (MathHelper.PiOver4 / 100) *
        (Mouse.GetState().Y - prevMouseState.Y)
        ));

每当使用CreateFromAxisAngle时,第一个参数(轴)必须是单位长度向量。如果它不是单位长度矢量,它将导致失真(倾斜)矩阵和一个超过(或低于)旋转的矩阵。

每当你越过两个向量时,结果很少是单位长度向量。产生横向单位长度的结果。试试这个:

Vector3.Transform(CameraDirection, Matrix.CreateFromAxisAngle(Vector3.Normalize(Vector3.Cross(CameraUp, CameraDirection)), ...

通过添加'Normalize',它使得交叉的结果成为单位长度向量。不要忘记对偏航线做同样的事情。