Search code examples
c++mathmatrixglm-math

What is the proper way to zoom in and out using orthographic projection?


I have a view matrix:

    float left = -(float)viewPortWidth / 240, right = (float)viewPortWidth / 240, down = -(float)viewPortHeight / 240, up = (float)viewPortHeight / 240;
    viewMatrix = glm::ortho(left, right, down, up, -1.0f, 1.0f);

I am dividing by 240 to be able to show 16:9 units when it is full screen. Here is how it looks like: enter image description here

I have a class Camera2D and I want to give it a size capability like Unity or at least achieve something similar. Before, I was using the transformation matrix of the game object attached to the camera and multiplying it by viewMatrix, but that leads to many unwanted effects if I make game object a child of the camera. I tried adding the number of extra vertical and horizontal unites I want to left, right, down, up but it leads to stretching effects.

I want to be able to have a zoom feature where 1 would add one vertical or horizontal unit. How can I do this?

Update 1: I tried this:

    float left = -(float)(viewPortWidth + 240) / 240, right = (float)(viewPortWidth + 240) / 240, down = -(float)(viewPortHeight + 240) / 240, up = (float)(viewPortHeight + 240) / 240;
    viewMatrix = glm::ortho(left, right, down, up, -1.0f, 1.0f);

But it still leads to stretching effects.


Solution

  • Try dividing all the parameters.

    float zoom = 16.0f / 14.0f; // 114% zoom in  
    
    float left = -(float)viewPortWidth / 240, right = (float)viewPortWidth / 240, down = -(float)viewPortHeight / 240, up = (float)viewPortHeight / 240;
    
    viewMatrix = glm::ortho(left / zoom, right / zoom, down / zoom, up / zoom, -1.0f, 1.0f);
    

    Another approach

    Or otherwise, if you'd like to control zoom level by specifying the number of units to be shown directly, try:

    float n = 14.0f * unit_size; // Align 14 units horizontally in the screen.
    
    const float aspectRatio = (float)viewPortWidth / viewPortHeight;
    float left = -n * 0.5f, right = n * 0.5f, down = -n * 0.5f / aspectRatio, up = n * 0.5f / aspectRatio;
    
    viewMatrix = glm::ortho(left, right, down, up, -1.0f, 1.0f);