# Transforming 2D viewport coordinates after scaling the viewport (zoom in/out)

I've been getting started with personal experimentation and have been working on a project for a few days now using SDL2. It is a 2D game, and at this stage I have it rendering game objects in a fixed-size viewport that can navigate around the 'game world'.

I'm not terribly well-versed in linear algebra yet, so it's possible that the answer to this question is somewhere in that curriculum that I have yet to tackle.

The game space has its own coordinates, organized in the same way that they are on an SDL_Window. The "viewport" then has its own coordinates (indicated by it's top left corner) in the game space. Game objects are then given transformed coordinates in the viewport's own coordinate space, which corresponds to the SDL_Window's coordinate space i.e. they start at (0, 0) at the upper left, which is essentially an offset given the viewport's coordinates, e.g.:

Entity x's gamespace coordinates are (100, 200) and the viewport's gamespace coordinates are (20, 20), the entity's "viewport" coordinates would be (100 - 20, 200 - 20) or (80, 180).

I've started to think about implementing 'zoom' functionality. At the moment, all that means is that the viewport is scaled up or down (to certain size limits), and the game entity's dimensions are scaled up or down correspondingly. What isn't transformed are the coordinates.

Visually, this is the basic problem:

At maximum size, where the viewport's dimensions are the same as the game space's dimensions (they have the same aspect ratio), the positions of all objects in the viewport space would be the same as they are in the game space, but they would have to be positioned using completely different coordinates in the viewport space.

What are the mathematical techniques/principles I should be studying to figure this one out? Thank you!

This is all covered by Translation, Rotation (not mentioned by you) and Scaling. You can write separate functions for each transformation but usually it is done using homogeneous coordinates and Matrices. By this you can define arbitrary sequence of operations and perform them on any point.

Here are the three Matrices:

Translation (Translate a point by (X,Y)):

[ 1  0  X  ]
[ 0  1  Y  ]
[ 0  0  1  ]


Rotation (rotate a point by a):

[ cos(a) -sin(a)  0  ]
[ sin(a)  cos(a)  0  ]
[    0      0     1  ]


Scaling (scale a point Sx,Sy):

[ Sx   0    0  ]
[  0   Sy   0  ]
[  0   0    1  ]


To transform a point by any matrix you need to add a 3rd coordinate to your points which is basically just "1":

[x y 1]


Now you can multiply any of the above mentioned matrices with your vector and transform it:

Example Scaling:

  [x]   [ Sx   0    0  ]     [ x * Sx  ]
[y] . [  0   Sy   0  ]  =  [ y * Sy  ]
[1]   [  0   0    1  ] =   [    1    ]


If you want to combine operations you can multiply your matrices and then multiply each point with the result. So you can calculate a transformation matrix based on your viewport once and transform all points before drawing them.

See this question for more detailed information about homogeneous coordinates