0

我正在尝试在 XNA 4.0 中创建第一人称视角相机。我让相机正常工作,我的场景渲染得很好。我的 W、A、S、D 移动也很好,但我不知道为什么我的鼠标旋转搞砸了。

当我尝试用相机向上看时,它会倾斜我的整个世界,向左和向右看做同样的事情,并且都朝同一个方向看。最终,我的整个世界都翻转了:S。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Brandon
{
    public class FPC : GameComponent
    {   
        private KeyboardState OldKeyboardState;
        private MouseState OldMouseState;

        private Vector3 Target = Vector3.Zero;
        private Vector3 UpVector = Vector3.Up;
        private Vector3 Position = new Vector3(0.0f, 0.0f, 1.0f);
        private Vector2 Velocity = Vector2.Zero;
        private Matrix View = Matrix.Identity;
        private Matrix Projection = Matrix.Identity;
        private BasicEffect Effects = null;
        private float Speed = 5.0f;
        private float WalkingSpeed = 1.0f;
        private float RotationSpeed = 0.1f;
        private float AngleX = 0.0f;
        private float AngleY = 0.0f;

        public BasicEffect Effect
        {
            get { return this.Effects; }
        }

        public FPC(Game game) : base(game)
        {
            Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
            Game.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
            this.Effects = new BasicEffect(Game.GraphicsDevice);
            this.OldMouseState = Mouse.GetState();
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        public void LookAt(float FOV_Degrees, float NearPlaneDistance, float FarPlaneDistance, Vector3 Position, Vector3 Target, Vector3 UpVector)
        {
            this.Position = Position;
            this.Target = Target;
            this.UpVector = UpVector;
            this.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(FOV_Degrees), Game.GraphicsDevice.Viewport.AspectRatio, NearPlaneDistance, FarPlaneDistance);
            this.View = Matrix.CreateLookAt(Position, Target, UpVector);
        }

        private void UpdateView(Matrix rotationMatrix)
        {
            Vector3 finalTarget = this.Position + Vector3.Transform(this.Target, rotationMatrix);
            Vector3 finalUp = Vector3.Transform(this.UpVector, rotationMatrix);
            this.View = Matrix.CreateLookAt(this.Position, finalTarget, finalUp);
        }

        private void ProcessInput(GameTime gameTime)
        {
            bool isWalking = false;
            KeyboardState CurrentKeyboardState = Keyboard.GetState();

            Vector3 pos = Vector3.Zero;
            if (CurrentKeyboardState.IsKeyDown(Keys.W)) pos.Z -= 1.0f;
            if (CurrentKeyboardState.IsKeyDown(Keys.S)) pos.Z += 1.0f;
            if (CurrentKeyboardState.IsKeyDown(Keys.A)) pos.X -= 1.0f;
            if (CurrentKeyboardState.IsKeyDown(Keys.D)) pos.X += 1.0f;
            if (CurrentKeyboardState.IsKeyDown(Keys.LeftShift)) isWalking = true;
            this.OldKeyboardState = CurrentKeyboardState;

            if (pos != Vector3.Zero)
            {
                pos.Normalize(); //So we don't move faster diagonally
                pos *= (float)gameTime.ElapsedGameTime.TotalSeconds * (isWalking ? this.WalkingSpeed : this.Speed); //Smooth movement
            }

            this.ProcessMouseInput(gameTime);

            Matrix rotationMatrix = Matrix.CreateRotationX(this.AngleX) * Matrix.CreateRotationY(this.AngleY);
            this.Position += (isWalking ? this.WalkingSpeed : this.Speed) * Vector3.Transform(pos, rotationMatrix);
            this.UpdateView(rotationMatrix);
        }


        //Rotate the camera using the mouse.
        private void ProcessMouseInput(GameTime gameTime)
        {
            float amount = (float)gameTime.ElapsedGameTime.TotalSeconds;
            MouseState mouse = Mouse.GetState();
            if (mouse != this.OldMouseState)
            {
                int xDist = mouse.X - (Game.GraphicsDevice.Viewport.Width / 2);
                int yDist = mouse.Y - (Game.GraphicsDevice.Viewport.Height / 2);
                this.AngleX -= RotationSpeed * xDist * amount;
                this.AngleY -= RotationSpeed * yDist * amount;
            }

            Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
            this.OldMouseState = mouse;
        }

        //Return a matrix for use with rendering hands holding weapons.
        public Matrix ModelWorldMatrix(float xOffset, float yOffset, float zOffset, float scale)
        {
            Vector3 ModelPos = this.Position;
            ModelPos += this.Target * zOffset;
            ModelPos += Vector3.UnitY * yOffset;
            ModelPos += Vector3.UnitX * xOffset;

            return Matrix.CreateScale(scale) * Matrix.CreateRotationX(MathHelper.ToRadians(this.AngleX)) * Matrix.CreateRotationY(MathHelper.ToRadians(this.AngleY)) * Matrix.CreateTranslation(ModelPos);
        }

        public override void Update(GameTime gameTime)
        {
            ProcessInput(gameTime);
            this.Effects.View = View;
            this.Effects.Projection = Projection;
            this.Effects.World = Matrix.Identity;
            base.Update(gameTime);
        }
    }
}

我已经尝试了各种示例代码并遵循了我能找到的所有教程,但它们都没有我遇到的相同问题。他们要么不工作,要么落后很多!

任何想法我做错了什么?

4

1 回答 1

2

您初始化this.Target为 0,0,0。这个值永远不会改变。

then later in your UpdateView method, you calculate finalTarget by transforming this.Target by a matrix representing a rotation only.

The result of

Vector3.Transform(this.Target, rotationMatrix) is essentially the same as

Vector3.Transform(Vector3.Zero, rotationMatrix).

Essentialy, that always results in (0,0,0) which should place finalTarget at the same position as this.Position except for floating point error that will give very small values to each component which factor in to cause your issue.

Try starting off by giving this.Target the value of 0,0,-1 (which causes the initial look direction to be the same as what your current code is trying to do, but gives the Vector3.Transform() something to work with) and you should be ok.

于 2013-11-19T13:20:42.090 回答