我正在尝试在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);
}
}
}
我尝试了各种示例代码并遵循了我能找到的所有教程,但没有一个我遇到同样的问题。它们要么不起作用,要么落后一吨!
任何想法我做错了什么?
答案 0 :(得分:2)
您将this.Target
初始化为0,0,0。这个值永远不会改变。
然后在UpdateView
方法中,您可以通过将finalTarget
转换为仅代表轮换的矩阵来计算this.Target
。
的结果
Vector3.Transform(this.Target, rotationMatrix)
与
Vector3.Transform(Vector3.Zero, rotationMatrix)
。
实际上,始终会导致(0,0,0)将finalTarget
置于与this.Position
相同的位置,除了浮点错误,每个组件的小值会导致您的问题。
首先尝试给this.Target
值0,0,-1(这会导致初始查找方向与您当前代码尝试的方向相同,但会给出{{1}和某些东西一起工作)你应该没问题。