【问题标题】:What's wrong with my camera?我的相机怎么了?
【发布时间】:2011-10-12 21:59:57
【问题描述】:

我将 VS2010 与 C# 和 XNA 4.0 一起使用。我正在关注 Aaron Reed 的《Learning 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。我不知道如何以及何时。此外(也许这没什么)在运行一段时间后,gameTime 显示经过的游戏时间只有 16 毫秒(就像它跳过帧一样?)并且游戏运行缓慢。无论我何时调试,这 16 毫秒始终相同。

有没有可能我弄乱了 XNA/C# 设置?如果是这样,有人可以给我任何提示现在该怎么做吗?

【问题讨论】:

  • 有什么例外吗?错误?更详细?
  • 无异常,无错误。它运作良好,但是当我移动鼠标时,屏幕变得疯狂。然后我只看到蓝屏,根本没有模型。也许“崩溃”是一个坏词,但这就是我的意思。 :)
  • 试试把 (MathHelper.PiOver4 / 100) 改成 (MathHelper.PiOver4 / 100.0) 看看是不是整数转换
  • 不,不是那样(一分钟前试过)。也正如我所说 - 它早些时候运作良好。所有的转换都是从书中复制的。
  • 附注:即使对于像这样的小型项目,源代码控制也非常方便!调查类似 unfuddle.com 的网站。它是免费的,而且绝对有帮助。这样,您可以签入有效的代码,而不必处理诸如此类的问题!

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


【解决方案1】:
    // 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',它使交叉的结果成为一个单位长度的向量。不要忘记对偏航线也做同样的事情。

【讨论】:

  • 成功了!好吧,不完全像你写的那样,因为规范化方法是无效的(至少在 XNA 4.0 中)。 :) 非常感谢。虽然我真的很惊讶,因为代码是从书中获取的,并且在早期它没有任何问题。我想知道为什么会这样?无论如何,谢谢!
  • 如果你交叉两个本身是单位长度的向量并且它们在方向上恰好相隔 90 度,那么结果将是单位长度。我想知道这是否是它之前正常工作的原因。
  • 是的,我知道这个理论。叉积的长度等于长度乘以向量之间夹角的余弦的乘积。但我认为 CreateFromAxisAngle 方法中的长度无关紧要。猜我错了。 :) 谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-09-05
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多