Skip to content

Instantly share code, notes, and snippets.

@Wolfolo
Created April 21, 2017 12:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Wolfolo/6584256640d6a1deffc73ba134cfdd25 to your computer and use it in GitHub Desktop.
Save Wolfolo/6584256640d6a1deffc73ba134cfdd25 to your computer and use it in GitHub Desktop.
3d Camera
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test3D.Objects
{
public class Camera
{
// We need this to calculate the aspectRatio in the ProjectionMatrix property.
GraphicsDevice graphicsDevice;
Vector3 position = new Vector3();
Vector3 rotation = new Vector3();
Vector3 up;
Vector3 right;
Vector3 look;
public enum CameraRotations
{
YawLeft,
YawRight,
PitchUp,
PitchDown,
RollClockwise,
RollAntiClockwise,
}
public enum CameraMovements
{
StrafeLeft,
StrafeRight,
ThrustForward,
ThrustBackward,
}
public Matrix ViewMatrix
{
get
{
/* To apply Roll (Z rotation) we rotate up and right around the look vector: */
Matrix rollMatrix = Matrix.CreateFromAxisAngle(look, rotation.Z);
up = Vector3.Transform(up, rollMatrix);
right = Vector3.Transform(right, rollMatrix);
/* To apply Yaw (Y rotation) we rotate the look and right vectors around the up vector: */
Matrix yawMatrix = Matrix.CreateFromAxisAngle(up, rotation.Y);
look = Vector3.Transform(look, yawMatrix);
right = Vector3.Transform(right, yawMatrix);
/* To apply Pitch (X rotation) we rotate look and up around the right vector: */
Matrix pitchMatrix = Matrix.CreateFromAxisAngle(right, rotation.X);
look = Vector3.Transform(look, pitchMatrix);
up = Vector3.Transform(up, pitchMatrix);
/* The CreateLookAt function requires a camera position, a target and an up direction.
* We know the camera position and the up vector but we do not know the target.
* However the look vector points in the direction the camera is facing so we can use that to create a target by adding it to the position.
*/
Vector3 target = position + look;
return Matrix.CreateLookAt(position, target, up);
}
}
public Matrix ProjectionMatrix
{
get
{
float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
float nearClipPlane = 1;
float farClipPlane = 200;
float aspectRatio = graphicsDevice.Viewport.Width / (float)graphicsDevice.Viewport.Height;
return Matrix.CreatePerspectiveFieldOfView(fieldOfView, aspectRatio, nearClipPlane, farClipPlane);
}
}
public Camera(GraphicsDevice graphicsDevice)
{
this.graphicsDevice = graphicsDevice;
}
public void SetPosition(Vector3 pos)
{
position = pos;
}
public void SetRotation(Vector3 rot)
{
rotation = rot;
}
public void Rotate(CameraRotations rot, float angle)
{
switch (rot)
{
case CameraRotations.YawLeft:
RotateAroundY(angle);
break;
case CameraRotations.YawRight:
RotateAroundY(-angle);
break;
case CameraRotations.PitchUp:
RotateAroundX(angle);
break;
case CameraRotations.PitchDown:
RotateAroundX(-angle);
break;
case CameraRotations.RollClockwise:
RotateAroundZ(angle);
break;
case CameraRotations.RollAntiClockwise:
RotateAroundZ(-angle);
break;
default:
break;
}
}
public void Move(CameraMovements mov, float speed)
{
const float unitsPerSecond = 10;
switch (mov)
{
case CameraMovements.StrafeLeft:
position += right * unitsPerSecond * speed;
break;
case CameraMovements.StrafeRight:
position -= right * unitsPerSecond * speed;
break;
case CameraMovements.ThrustForward:
position += look * unitsPerSecond * speed;
break;
case CameraMovements.ThrustBackward:
position -= look * unitsPerSecond * speed;
break;
default:
break;
}
}
private void RotateAroundY(float angle)
{
rotation.Y += angle;
// keep the value in the range 0-360 (0 - 2 PI radians)
if (rotation.Y > Math.PI * 2)
rotation.Y -= MathHelper.Pi * 2;
else if (rotation.Y < 0)
rotation.Y += MathHelper.Pi * 2;
}
private void RotateAroundX(float angle)
{
rotation.X += angle;
// keep the value in the range 0-360 (0 - 2 PI radians)
if (rotation.X > Math.PI * 2)
rotation.X -= MathHelper.Pi * 2;
else if (rotation.X < 0)
rotation.X += MathHelper.Pi * 2;
}
private void RotateAroundZ(float angle)
{
rotation.Z += angle;
// keep the value in the range 0-360 (0 - 2 PI radians)
if (rotation.Z > Math.PI * 2)
rotation.Z -= MathHelper.Pi * 2;
else if (rotation.Z < 0)
rotation.Z += MathHelper.Pi * 2;
}
public void Update(GameTime gameTime)
{
float unit = (float)gameTime.ElapsedGameTime.TotalSeconds;
// Rotation
if (Keyboard.GetState().IsKeyDown(Keys.NumPad4))
{
Rotate(CameraRotations.YawRight, unit);
}
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad6))
{
Rotate(CameraRotations.YawLeft, unit);
}
if (Keyboard.GetState().IsKeyDown(Keys.PageDown))
{
Rotate(CameraRotations.PitchDown, unit);
}
else if (Keyboard.GetState().IsKeyDown(Keys.PageUp))
{
Rotate(CameraRotations.PitchUp, unit);
}
if (Keyboard.GetState().IsKeyDown(Keys.NumPad1))
{
Rotate(CameraRotations.RollAntiClockwise, unit);
}
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad3))
{
Rotate(CameraRotations.RollClockwise, unit);
}
// Movement
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
Move(CameraMovements.StrafeLeft, unit);
}
else if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
Move(CameraMovements.StrafeRight, unit);
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
Move(CameraMovements.ThrustForward, unit);
}
else if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
Move(CameraMovements.ThrustBackward, unit);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment