Whenever I change the orientation of the camera, yaw and roll become inverted (or correct); the strafing, movement and pitch do remain correct however.
Can you tell what is causing this and how to fix it ?
private Vector3 _cameraOrientation;
private Vector3 _cameraPosition;
private Matrix _matrixProjection;
private Matrix _matrixView;
protected override void Update(GameTime gameTime)
{
var state = GamePad.GetState(PlayerIndex.One);
if (state.Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (state.Buttons.Start == ButtonState.Pressed) _cameraPosition = _cameraOrientation = Vector3.Zero;
var right = state.ThumbSticks.Right;
var left = state.ThumbSticks.Left;
// get position/orientation deltas from gamepad
var position = new Vector3
{
X = left.X,
Y = state.Buttons.A == ButtonState.Pressed ? -1 : state.Buttons.Y == ButtonState.Pressed ? 1 : 0,
Z = -left.Y,
};
var orientation = new Vector3
{
X = -right.Y,
Y = -right.X,
Z = state.Buttons.X == ButtonState.Pressed ? -1 : state.Buttons.B == ButtonState.Pressed ? 1 : 0
};
// update position according orientation
_cameraOrientation += orientation;
var cameraReference = Vector3.Forward;
var cameraRotation =
Matrix.CreateRotationX(MathHelper.WrapAngle(MathHelper.ToRadians(_cameraOrientation.X))) *
Matrix.CreateRotationY(MathHelper.WrapAngle(MathHelper.ToRadians(_cameraOrientation.Y))) *
Matrix.CreateRotationZ(MathHelper.WrapAngle(MathHelper.ToRadians(_cameraOrientation.Z)));
_cameraPosition += Vector3.Transform(position, cameraRotation);
// update matrices
var cameraPosition = _cameraPosition;
var cameraTransformedReference = Vector3.Transform(cameraReference, cameraRotation);
var cameraTarget = cameraPosition + cameraTransformedReference;
var cameraUpVector = Vector3.Transform(Vector3.Up, cameraRotation); // Vector3.Up;
_matrixView = Matrix.CreateLookAt(cameraPosition, cameraTarget, cameraUpVector);
_matrixProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
_graphics.GraphicsDevice.Viewport.AspectRatio, 0.01f, 100000f);
base.Update(gameTime);
}
position
tovelocity
,positionDelta
, or anything else that is more indicative of their purposes. \$\endgroup\$cameraRotation
; i.e.cameraRotation.Forward
,cameraRotation.Left
. Both of the directions returned are relative to the stored rotation, not "the world". So,If (left.X != 0) _cameraPosition += cameraRotation.Right * left.X;
\$\endgroup\$Matrix.CreateRotationX
creates "pitch". You are applying X, then Y, then Z which is Pitch, then Yaw, then Roll. Each of the matrices you are creating is relative to world-space ("Up" is +Y). When you pitch the camera past 90 degrees (first), camera-space "Up" becomes world-space "Down". \$\endgroup\$Vector3.Forward
, looking toward (0,0); that means that, initially,Camera.Forward
isVector3.Backward
. Positive rotations are clock-wise, relative to the axis being twisted which is why starting atVector3.Forward
is an intuitive solution. The other and, more common, intuitive solution is starting atVector3.Backward
, looking toward (0,0), and inverting your sticks' pitch values. \$\endgroup\$