我的相机出了什么问题?

发布于 2024-11-26 18:45:00 字数 3867 浏览 2 评论 0原文

我将 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 中使用凸轮的视图和投影矩阵。

//编辑2: 出了严重的问题。我做了一些调试,似乎在某些时候这些 Vector3 对象的 X、Y、Z 属性设置为 NaN。我不知道如何以及何时。另外(也许这没什么)运行一段时间后,gameTime 显示游戏运行时间仅为 16 毫秒(就像它跳帧一样?)并且游戏运行缓慢。无论我何时调试,这 16 毫秒始终是相同的。

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

I'm using VS2010 together with C# and XNA 4.0. I'm following the book "Learning XNA 4.0" by Aaron Reed. I added the camera game component to my project but this camera behaves really weird. Moving mouse makes it "jump" and then crash. I don't know what is causing this. It looks that the code is almost identical to that in book. It worked earlier, but now it isn't, although I can't remember whether I change anything in it (I think not). Note that I am only registering this component in game, nothing more. It should work, but it does not. Any help would be great. Here's the code:

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

Can someone please check whether this code works for him? Any idea would be great!

//EDIT 1:
In game's initialization I use code:

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

and then I draw model. I use cam's view and projection matrices in model's BasicEffect.

//EDIT 2:
Something's seriously wrong. I did some debuging and it seems that at some point those Vector3 objects have their X,Y,Z properties set to NaN. I couldn't find out how and when. Also (perhaps this is nothing) after running for some time gameTime shows that the elapsed game time is ONLY 16 miliseconds (like it skips frames?) and that the game is running slowly. This 16 miliseconds is always the same, no matter when I debug.

Is it possible that I somehow messed up XNA/C# settings? If so, can someone give me any hint what to do now?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

池予 2024-12-03 18:45:00
    // 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)), ...

通过添加“归一化”,它使交叉的结果成为单位长度向量。不要忘记对偏航线也做同样的事情。

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

Whenever you use CreateFromAxisAngle, the first param (the axis) needs to be a unit length vector. If it isn't a unit length vector, it will result in a distorted (skewed) Matrix and one that is over (or under) rotated.

Whenever you cross two vectors the result in rarely a unit length vector. To make a result of a cross unit length. try this:

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

by adding the 'Normalize', it makes the result of the cross a unit length vector. Don't forget to do the same to the yaw line as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文