Jump to content
  • Advertisement
Sign in to follow this  
Galantida

Matrix for FPS Camera

This topic is 2559 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello All,

I don't normally post questions on any forums so I am new not just to this forum but forums in general. I have been pretty proud of myself learning C# and XNA. I have a stationary camera sitting at 0,0,0 that follows a space ship which I steer using the mouse to free look and the keys to go forward, back and strafe left and right. I thought it would be simple to now convert my camera to first person by simply applying the same matrix that I do to the ship model to my camera but I just cant get it to work. I have read many camera tutorials and picked this up and put it down more than a few times over the past few months but just can't get past this. Below is my draw function and the matrix functions.

I am really stuck if anyone can help.


ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)Window.ClientBounds.Width / (float)Window.ClientBounds.Height, 1, 3000);


protected override void Draw(GameTime gameTime)
{
// Clear Display
GraphicsDevice.Clear(Color.Black);

// Camera Matrix
Matrix CameraMatrix;
if (World.FirstPerson == true) CameraMatrix = this.CameraFirstPerson(World.CameraObject);
else CameraMatrix = this.CameraFollow(World.CameraObject, World.LookAtObject);

// Terrain
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.VertexColorEnabled = true;
basicEffect.World = Matrix.CreateTranslation(GraphicsDevice.Viewport.Width / 2f - 150, GraphicsDevice.Viewport.Height / 2f - 50, 0);
basicEffect.View = CameraMatrix;
basicEffect.Projection = ProjectionMatrix;

foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
pass.Apply();
DrawTriangleStrip();
}

// Render World Objects (Models and Sounds)
foreach (KeyValuePair<int, clsObject> kvp in World.Objects)
{
// set object value to current object
clsObject Object = kvp.Value;


// ***************************
// Draw Model for each object
// ***************************
Model Model = ModelBank[Object.ModelName];
Matrix[] transforms = new Matrix[Model.Bones.Count];
Model.CopyAbsoluteBoneTransformsTo(transforms);


// Object Matrix (Rotation /scale etc...)
Matrix ObjMatrix = ObjectMatrix(Object);

foreach (ModelMesh mesh in Model.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.Projection = ProjectionMatrix; // using the view settings defined earlier (Near & Far planes, Camera Lens, etc...)
be.View = CameraMatrix; // Camera is from the view matrix from the object we are currently viewing from
be.World = ObjMatrix * mesh.ParentBone.Transform; // Apply the view matrix from the object we are currently drawing.
}
mesh.Draw();
}

}


// Display HUD
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.Opaque);

spriteBatch.DrawString(Arial, "Camera Object" + World.CameraObject.Name + " (Use Alt # to Change)", new Vector2(10, 10), Color.Red);
spriteBatch.DrawString(Arial, "Location: " + World.CameraObject.X + "," + World.CameraObject.Y + "," + World.CameraObject.Z, new Vector2(10, 30), Color.White);
spriteBatch.DrawString(Arial, "Rotation: " + World.CameraObject.Yaw + ", " + World.CameraObject.Pitch + ", " + World.CameraObject.Roll, new Vector2(10, 50), Color.White);

spriteBatch.DrawString(Arial, "Input Object" + World.InputObject.Name + " (Use Ctrl # to Change)", new Vector2(10, 90), Color.Red);
spriteBatch.DrawString(Arial, "Location: " + World.InputObject.X + "," + World.InputObject.Y + "," + World.InputObject.Z, new Vector2(10, 110), Color.White);
spriteBatch.DrawString(Arial, "Rotation: " + World.InputObject.Yaw + ", " + World.InputObject.Pitch + ", " + World.InputObject.Roll, new Vector2(10, 130), Color.White);

spriteBatch.DrawString(Arial, "Look At Object" + World.LookAtObject.Name + " (Use Shift # to Change)", new Vector2(10, 170), Color.Red);
spriteBatch.DrawString(Arial, "Location: " + World.LookAtObject.X + "," + World.LookAtObject.Y + "," + World.LookAtObject.Z, new Vector2(10, 190), Color.White);
spriteBatch.DrawString(Arial, "Rotation: " + World.LookAtObject.Yaw + ", " + World.LookAtObject.Pitch + ", " + World.LookAtObject.Roll, new Vector2(10, 210), Color.White);

string CameraMode;
if (World.FirstPerson == true) CameraMode = "First Person";
else CameraMode= "Follow Look At Object";
spriteBatch.DrawString(Arial, "Camera Mode: " + CameraMode + " (Use function keys to change)", new Vector2(10, 250), Color.Red);

spriteBatch.End();


// Draw all Game Components
base.Draw(gameTime);
}



private Matrix ObjectMatrix(clsObject WorldObject)
{
// Objects Location, Scale and Roatation
Matrix ScaleMatrix = Matrix.CreateScale(WorldObject.ScaleX, WorldObject.ScaleY, WorldObject.ScaleZ);
Matrix LocationMatrix = Matrix.CreateTranslation(WorldObject.Location);
Matrix RotationMatrix = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(WorldObject.Yaw), MathHelper.ToRadians(WorldObject.Pitch), MathHelper.ToRadians(WorldObject.Roll));

// Combine Matrix
Matrix ResultMatrix;
ResultMatrix = Matrix.Multiply(LocationMatrix, ScaleMatrix);
ResultMatrix = Matrix.Multiply(RotationMatrix, ResultMatrix);
return ResultMatrix;
}

private Matrix CameraFirstPerson(clsObject FromPerspectiveOf)
{
// Objects Position and Rotation
Matrix LocationMatrix = Matrix.CreateTranslation(FromPerspectiveOf.Location);
Matrix RotationMatrix = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(FromPerspectiveOf.Yaw),MathHelper.ToRadians(FromPerspectiveOf.Pitch),MathHelper.ToRadians(FromPerspectiveOf.Roll));

// Camera Matrix (For when we are looking from this Objects perspective
return Matrix.Multiply(RotationMatrix, LocationMatrix);
}

private Matrix CameraFollow(clsObject FromPerspectiveOf, clsObject LookingAt)
{
// Build camera view matrix
Vector3 cameraDirection = LookingAt.Location - FromPerspectiveOf.Location;
cameraDirection.Normalize();
return Matrix.CreateLookAt(FromPerspectiveOf.Location, FromPerspectiveOf.Location + cameraDirection, Vector3.Up);
}

Share this post


Link to post
Share on other sites
Advertisement
Welcome to the forums. :)

Anyway, this is actually pretty simple. A world matrix transforms a coordinate from object local space (AKA object space) to world space. A view matrix transforms from world space to the camera's local space (AKA view space). For any transformation matrix you can flip the direction of the transformation by inverting it. So for instance if you have a world matrix that transforms from object space to world space, the inverse will transform world space to object space. This means that if you invert your ship's world matrix, you'll have a matrix that transforms from world space to the ship's local space...which means you can use it as a view matrix:

private Matrix CameraFirstPerson(clsObject FromPerspectiveOf)
{
return Matrix.Invert(ObjectMatrix(FromPerspectiveOf));
}


You can also use this property of matrices to go the other way around: if you invert a view matrix you get a world matrix for your camera. This can be handy for rendering things that you always want to be in front of a camera...for instance a gun in a first person shooter.

Also on a side note...when you want to post code here you can use the "code" or "source" tags like I did in my post. See this: http://www.gamedev.n...s-and-journals/

Share this post


Link to post
Share on other sites
MJP You are the best, it worked like a charm!!! I have been trying to work through that for so long. biggrin.gif

The only problem is I am not sure if I understand why the inverted matrix of my object works. I have been thinking of the camera as a physical object in space with a location and rotation. I guess I should think of it more as a space or coordinate system in it's self? Even if that is the case why doesn't the same matrix work for the camera as for the object since they are both in the same world?

If it's too difficult to explain the forum I will understand. Just knowing the answer now may help me make a break though in understanding it now.

Thanks again!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!