• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
mwkenna

2D Camera Transformation

16 posts in this topic

Hi!

I'm having some trouble getting my head around the behavior of a popular 2D camera class with the following method:

[CODE]
public Matrix GetTransformation()
{
Matrix viewMatrix =
Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
Matrix.CreateTranslation(new Vector3(_viewportWidth * 0.5f, _viewportHeight * 0.5f, 0));
return viewMatrix;
}
[/CODE]

The issue I am facing is that after a camera rotation, all applied camera movement (using _pos variable) is performed on the rotated axis, not the true world axis (up,down,left,right).

To help visually check this I draw an "axis" sprite that just shows a standard x,y "graph paper" axis. When there is no camera rotation and I move the camera up/down/left/right it follows the screen axis perfectly. After I apply a rotation to the camera and try to move up/down/left/right the camera follows the rotated axis rather than the world axis.

Please can somebody help me to understand why this is happening, and perhaps show me how to still move the camera according to the world's X,Y axis?

I can post screen capture's if needed as I'm sure I'm not explaining this properly.

Thanks,
Mark.
0

Share this post


Link to post
Share on other sites
Hi Aimee

Thanks for the info. The reason I have not used createlookat is because I want to learn more about the methodologies including the matrix multiplication.

So if one wanted to rotate the view around the center of the current camera view, how would one accomplished that as an example?

Thanks,
Mark.
0

Share this post


Link to post
Share on other sites
I think the fact they are called matrices is what trips most people up, they make themselves out to be a magical thing that can do all sorts, but really they are just a grid of numbers that provide a way of manipulating coordinates (why can't people just describe em like that). In mathematics you could describe a matrix having certain components preform things like carrying out a cosine calculation for example, but as it's more difficult to express that in programming, classes like the Matrix class provide special methods like CreateRotateZ and CreateLookAt that basically do those individual operations on certain components.

Take the example I showed in my last post, CreateRotateZ manually creates a standard identity matrix, performs Cos and Sin operations on two of the components, flips the sign of the input M12 component for the M22 output component, and passes the original value for M11 to the output M22. This in effect means a Matrix is actually not a magical piece of awesomeness, rather just a holder of a grid of information that needs manipulating.

Same again goes for multiplication, this is literally just an operator that has been created for the Matrix class that multiplies each component and returns the result, here have a look at how monoxna did it:

[source lang="csharp"]public static Matrix operator *(Matrix matrix1, Matrix matrix2)
{
Matrix result;

result.M11 = matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31 + matrix1.M14 * matrix2.M41;
result.M12 = matrix1.M11 * matrix2.M12 + matrix1.M12 * matrix2.M22 + matrix1.M13 * matrix2.M32 + matrix1.M14 * matrix2.M42;
result.M13 = matrix1.M11 * matrix2.M13 + matrix1.M12 * matrix2.M23 + matrix1.M13 * matrix2.M33 + matrix1.M14 * matrix2.M43;
result.M14 = matrix1.M11 * matrix2.M14 + matrix1.M12 * matrix2.M24 + matrix1.M13 * matrix2.M34 + matrix1.M14 * matrix2.M44;

result.M21 = matrix1.M21 * matrix2.M11 + matrix1.M22 * matrix2.M21 + matrix1.M23 * matrix2.M31 + matrix1.M24 * matrix2.M41;
result.M22 = matrix1.M21 * matrix2.M12 + matrix1.M22 * matrix2.M22 + matrix1.M23 * matrix2.M32 + matrix1.M24 * matrix2.M42;
result.M23 = matrix1.M21 * matrix2.M13 + matrix1.M22 * matrix2.M23 + matrix1.M23 * matrix2.M33 + matrix1.M24 * matrix2.M43;
result.M24 = matrix1.M21 * matrix2.M14 + matrix1.M22 * matrix2.M24 + matrix1.M23 * matrix2.M34 + matrix1.M24 * matrix2.M44;

result.M31 = matrix1.M31 * matrix2.M11 + matrix1.M32 * matrix2.M21 + matrix1.M33 * matrix2.M31 + matrix1.M34 * matrix2.M41;
result.M32 = matrix1.M31 * matrix2.M12 + matrix1.M32 * matrix2.M22 + matrix1.M33 * matrix2.M32 + matrix1.M34 * matrix2.M42;
result.M33 = matrix1.M31 * matrix2.M13 + matrix1.M32 * matrix2.M23 + matrix1.M33 * matrix2.M33 + matrix1.M34 * matrix2.M43;
result.M34 = matrix1.M31 * matrix2.M14 + matrix1.M32 * matrix2.M24 + matrix1.M33 * matrix2.M34 + matrix1.M34 * matrix2.M44;

result.M41 = matrix1.M41 * matrix2.M11 + matrix1.M42 * matrix2.M21 + matrix1.M43 * matrix2.M31 + matrix1.M44 * matrix2.M41;
result.M42 = matrix1.M41 * matrix2.M12 + matrix1.M42 * matrix2.M22 + matrix1.M43 * matrix2.M32 + matrix1.M44 * matrix2.M42;
result.M43 = matrix1.M41 * matrix2.M13 + matrix1.M42 * matrix2.M23 + matrix1.M43 * matrix2.M33 + matrix1.M44 * matrix2.M43;
result.M44 = matrix1.M41 * matrix2.M14 + matrix1.M42 * matrix2.M24 + matrix1.M43 * matrix2.M34 + matrix1.M44 * matrix2.M44;

return result;
}[/source]
Ok there is a fair bit going on there, but again it's just a function that sets each component of the Matrix by using standard mathematics. Now the reason why I mentioned using the CreateLookAt method is because that specific method has been designed to make life easier for creating view matrices, also I doubt anyone want's to rewrite that method above every time they go to make a computer game lol.

Personally I am someone who needs to delve into the inner workings of something sometimes in order for me to understand why it works and how to use it, and if you are like me, I'd reccommend studying it, because just looking at the source code for monoxna is a eye opening way to learn this stuff. On the other hand there is lots more information out there about how to best use them, for further reading I'd suggest taking a read of the excellent extra reading tutorials provided by Riemer here: [url="http://www.riemers.net/eng/ExtraReading/matrices_geometrical.php"]http://www.riemers.net/eng/ExtraReading/matrices_geometrical.php[/url]

Aimee
0

Share this post


Link to post
Share on other sites

Hi Aimee

 

I have taken what you said on board and looked into the correct ordering for matrix transformations, I fully understand the concept of Matrices and their application to coordinates but I think I am having trouble grasping how they should be correctly used for transformations.

 

I have modified the method to become:

 

public Matrix GetTransformation()
{
  Matrix viewMatrix = Matrix.CreateTranslation(-_viewportWidth / 2, -_viewportHeight / 2, 0) * //translate to origin
  Matrix.CreateRotationZ(Rotation) * //apply the rotation
  Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) * //apply the scale
  Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) * //apply the positional movement
  Matrix.CreateTranslation(_viewportWidth / 2, _viewportHeight / 2, 0); //translate back to the position
  return viewMatrix;
} 

 

My next step is to make the rotation happen around the center of the viewport as opposed to the center of the world (0, 0)

 

Thanks, Mark.

0

Share this post


Link to post
Share on other sites

I think you are mixing up the view and projection matrix leading to a misunderstanding of why we use world/view/projection in the first place. World is the theoretical transform of the vertices in world space, view can be seen as the camera, it converts world coordinates into ones relative to a camera, now here's the important part; the view matrix doesn't have any knowledge of the size of the view port, that is the job of the projection matrix.

 

The projection matrix is responsible for converting the view position of a vertex onto screen coordinates, In xna the process only works if you follow this order of transformation.

1

Share this post


Link to post
Share on other sites

I have been reading up on the correct ordering for matrix transformations and the creation of the view matrix. I would just like to understand how to model a camera that rotates around a specific point (centre of the viewport perhaps) that you can still adjust the position in non-rotated x,y coordinates that correspond to screen coordinates.

 

If someone has some sample code that would be great - I have looked over many many posts and examples all of which suffer from the same problem that I am facing.

 

Thanks,

Mark.

0

Share this post


Link to post
Share on other sites
if (Position != position || Scale != scale || Origin != origin || Rotation != rotation)
{
scale = Scale;
origin = Origin;
rotation = Rotation;
position = Position;
transform = Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(new Vector3(Scale, 1)) *
Matrix.CreateTranslation(new Vector3(-Origin, 0));
}

 

 

This is exactly what I use, it works fine. Rotates around the center, zooms, translates, everything you wish for smile.png

EDIT: Origin is just your screen center. so in a 800 * 600 window, it is 400,300 vector.

1

Share this post


Link to post
Share on other sites

Hi Morphex

 

That's pretty much the exact code that I use. Don't you find that when you try to re-position the camera left/right/up/down that it always moves along the already-rotated axis? If there is no rotation the camera will move exactly as I want, if you apply any rotation the camera will move on a non-screen aligned axis.

 

Thanks,

Mark.

0

Share this post


Link to post
Share on other sites
Thats what it is supposed to do, if you don't want it like that you will need to change the order of transforms. So you want to rotate the screen but the movement to be Horizontal no matter the rotation?

If thats what you want, I can try and throw some code later to you. Edited by Morphex
0

Share this post


Link to post
Share on other sites
Exactly, I have tried applying the rotation before the transform but it will always rotate around (0,0). I want to always rotate around the current screen center (camera.position.x + viewport.width * 0.5, camera.position.y + viewport.height * 0.5) if that makes any sense?

So the camera movement will go according to screen axis, the rotation will always happen at the current camera focus (center of the screen).

Thanks,
Mark. Edited by mwkenna
0

Share this post


Link to post
Share on other sites

I still think you are getting a bit confused with view and projection matrices, so I've put a bit of an example together for you that demonstrates how I would normally perform camera rotation in a 2D game:

 

> http://aimee.xpod.be/CameraRotationExample2D.rar

 

Note that in this example I disregard the SpriteBatch class to demonstrate another way of drawing sprites (by using the centre of the sprite instead of the top left as origin) which I believe will help you understand things a bit more. Also I create an orthographic projection matrix which means you don't need to figure out where the centre of the screen is because it is placed always at (0,0,0).

 

Again hope this helps, and if you still get stuck, let me know.

 

Aimee

1

Share this post


Link to post
Share on other sites

Well, the quicker way I can think of is to move the camera.X and Y in a trignometric fashion, so that it moves left and right even when rotated.

0

Share this post


Link to post
Share on other sites

Thanks Aimee - the solution seems to do what, I will be taking apart the code in detail and learning what each part does.

 

Morphex - Do you think you could also post that sample code with the trigonometric positioning - I'm guessing that's still using the spritebatch right?

 

Thanks,

Mark.

0

Share this post


Link to post
Share on other sites

Hi Aimee

 

I've been looking over your code (which is really well put together) but it's made me try to jump too far forward in my learning process.

 

Is it possible to alter the code so that it still uses the SpriteBatch which, as I understand it, does not require the use of a projection matrix at all?

 

Thanks,

Mark.

0

Share this post


Link to post
Share on other sites

Hi Mark, No matter what mechanism you use in XNA, you will always require a projection matrix to draw things. If no projection matrix is used then you can't properly place things onto the screen because like I have mentioned before that is the job of the projection matrix.

 

The SpriteBatch sets up a lot of things for you behind the scenes (including a projection matrix), however the question you started this thread with requires a more comprehensive understanding of how matrices work. In my example I did not use a SpriteBatch because using one actually makes things more complicated, the projection matrix by default sets the origin into the top left corner, which makes rotating the camera needlessly more difficult than it needs to be.

 

I promise you that if you take a bit more time to try and understand what I've said over the last few replies that you'll see why I've gone into so much depth, It's not just as simple as dropping a SpriteBatch in there, messing about with a matrix and expecting everything to be perfect.

 

Slow down, learn the mathematics, be patient and don't try to force things. A lot of people never get anywhere because they "want to know how to do stuff RIGHT NOW and sod everything that looks to difficult". It's likely there is a smart programmer here who'd just throw you a quick answer that'd see you off again using the SpriteBatch, but you would never learn anything, and you'd be right back here in a few weeks asking us to fix a problem with the sprite batch that you don't know how to fix because something went wrong and you never learnt the fundamentals in the first place.

 

Aimee

0

Share this post


Link to post
Share on other sites

Hi Aimee

 

Thanks for the advice, I am actually trying to slow it down a notch. I'm working through a book which only deals with the SpriteBatch (for 2D) - I am on transformations and how to model a simple camera, but the rotation/translation in the camera seemed wrong to me (non-axis aligned) so I thought I would post to see if there was a way to "fix" it.

 

Thanks for all your replies.

 

Mark.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0