Created
April 21, 2017 12:27
-
-
Save Wolfolo/6584256640d6a1deffc73ba134cfdd25 to your computer and use it in GitHub Desktop.
3d Camera
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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