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.Target0,0,0 に初期化します。この値は決して変わりません。

その後、メソッドの後半で、回転のみを表す行列で変換しUpdateViewて計算します。finalTargetthis.Target

結果として

Vector3.Transform(this.Target, rotationMatrix)本質的に同じです

Vector3.Transform(Vector3.Zero, rotationMatrix).

基本的に、これは常に(0,0,0)になり、問題の原因となる各コンポーネントに非常に小さな値を与える浮動小数点エラーを除いてfinalTarget、同じ位置に配置する必要があります。this.Position

0,0,-1 の値を指定することから始めてみてくださいthis.Target(これにより、最初の視線方向が現在のコードが実行しようとしているものと同じになりますが、Vector3.Transform()動作する何かが得られます)。問題はありません。

于 2013-11-19T13:20:42.090 に答える