I am trying to learn about the Camera in a 3D space and wanted to 3rd person type of camera. Right now, I directly control my camera and it doesn't follow anything. It works like a first-person camera. I load my Model in my Game1.cs and draw it like this:
Model player;
protected override void LoadContent()
{
// This is the default cube from Blender (when you first open up the program)
player = this.Content.Load<Model>("Cube");
}
protected override void Draw(GameTime gameTime)
{
foreach (ModelMesh mesh in player.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.View = camera.View;
effect.World = Matrix.CreateTranslation(5f, 1, 10f);
effect.Projection = camera.Projection;
mesh.Draw();
}
}
base.Draw(gameTime);
}
I want my camera to behind the cube or player and follow it. I think I have to change PreviewMove method in my Camera class but I don't know what needs to be changed. My guess is that I have to make a world matrix for the camera and set it behind the cube and update it whenever I move the cube. From there I would move the movement (W,S,A,D) code to the player movement.
But like I said, I don't know how I would implement this. If someone can provide any help or link me to a tutorial, it would be greatly appreciated. Thanks for your time!
Camera Class:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Model3D
{
class Camera
{
// Attributes
private Vector3 camLookAt;
private Vector3 camPosition;
private Vector3 camRotation;
private float cameraSpeed;
private float mouseSensitivity;
private Vector3 mouseRotationBuffer;
private MouseState currentMouseState;
private MouseState previousMouseState;
private GraphicsDevice device;
// Properties
public Matrix Projection
{
get;
protected set;
}
public Matrix View
{
get { return Matrix.CreateLookAt(camPosition, camLookAt, Vector3.Up); }
}
public Vector3 Position
{
get { return camPosition; }
set
{
camPosition = value;
UpdateLookAt();
}
}
public Vector3 Rotation
{
get { return camRotation; }
set
{
camRotation = value;
UpdateLookAt();
}
}
// Constructor
public Camera(GraphicsDevice device, Vector3 position, Vector3 rotation, float fieldOfView = 45f, float speed = 10f, float sensitivity = 10f)
{
// Set the GraphicsDevice
this.device = device;
// Set camera speed & mouse sensitivity
cameraSpeed = speed;
mouseSensitivity = sensitivity;
// Setup projection matrix
Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(fieldOfView), device.DisplayMode.AspectRatio, 0.5f, 1000f);
// Set camera position and rotation
MoveTo(position, rotation);
}
// Set camera's position & rotation
private void MoveTo(Vector3 pos, Vector3 rot)
{
Position = pos;
Rotation = rot;
}
// Update LookAt Vector
private void UpdateLookAt()
{
// Build a rotation matrix
Matrix rotationMatrix = Matrix.CreateRotationX(camRotation.X) * Matrix.CreateRotationY(camRotation.Y);
// Build LookAt offset
Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
// Update camera's LookAt vector
camLookAt = camPosition + lookAtOffset;
}
// Simulate movement
private Vector3 PreviewMove(Vector3 amount)
{
// Create a rotate matrix
Matrix rotate = Matrix.CreateRotationY(camRotation.Y);
// Create movement vector
Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
movement = Vector3.Transform(movement, rotate);
// Return value of camera position + movement vector
return camPosition + movement;
}
// Method that actually moves the camera
private void MoveCamera(Vector3 scale)
{
MoveTo(PreviewMove(scale), Rotation);
}
// Keyboard and Mouse movement
public void Update(GameTime gameTime)
{
// For smoothing (might not be beneficial for FPS)
float deltaTime = (float) gameTime.ElapsedGameTime.TotalSeconds;
// Mouse attributes
float deltaX;
float deltaY;
// Mouse State & Keyboard State
currentMouseState = Mouse.GetState();
KeyboardState state = Keyboard.GetState();
// Handle basic movement
Vector3 moveVector = Vector3.Zero;
if (state.IsKeyDown(Keys.W))
moveVector.Z = 1;
if (state.IsKeyDown(Keys.S))
moveVector.Z = -1;
if (state.IsKeyDown(Keys.A))
moveVector.X = 1;
if (state.IsKeyDown(Keys.D))
moveVector.X = -1;
if (state.IsKeyDown(Keys.Space))
moveVector.Y = 1;
if (state.IsKeyUp(Keys.Space) && Position.Y > 1.07)
moveVector.Y = -1;
if (moveVector != Vector3.Zero)
{
// Normalize vector so that we don't move faster diagonally
// Turns it into a unit vector
moveVector.Normalize();
// Now we add in smooth factor and speed
moveVector *= deltaTime * cameraSpeed;
// Move camera
MoveCamera(moveVector);
}
// Handle mouse movement
if(currentMouseState != previousMouseState)
{
// Cache mouse location
deltaX = currentMouseState.X - (device.Viewport.Width / 2);
deltaY = currentMouseState.Y - (device.Viewport.Height / 2);
// Create the rotation
mouseRotationBuffer.X -= 0.01f * deltaX * mouseSensitivity;
mouseRotationBuffer.Y -= 0.01f * deltaY * mouseSensitivity;
// Clamp the rotation so it can't do a barrel roll
if(mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));
if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));
Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)),
MathHelper.WrapAngle(mouseRotationBuffer.X), 0);
}
// Center the mouse
Mouse.SetPosition(device.Viewport.Width / 2, device.Viewport.Height / 2);
// Save previous mouse state
previousMouseState = currentMouseState;
}
}
}