1
\$\begingroup\$

I´ve implemented zooming of orthographic camera (just scaling it with its speed value):

viewMatrix = glm::scale(viewMatrix, glm::vec3(_cameraScale, _cameraScale, 1.0f));

And then applied these transformations (also translation by camera position) to the destination point (actually a cursor position vector) so I got its world positions:

void Camera::applyTransformationsToPoint(glm::vec3& pos) {

    pos += _cameraPosition;

    pos /= _cameraScale;
}

It worked fine, i was getting the right world position with diferent scales. However, this was done with normal scaling - to the origin of the matrix so basically when i scaled the matrix the whole camera moved to its origin and it looked a little bit weird. SO i have decided to imlement zoom to the middle of the screen feature. So basically what I do is (in pseudocode):

translate(screenWidth/2,screenHeight/2);
scaleTranslatedMatrix();
translate(-screenWidth/2,-screenHeight/2);

It works fine but the code above for transformation of screen coordinations to the world is now not working properly(im not getting the right world positions), any suggestions how to correct it? Thanks.

Edit1: This is how I apply the scaling (if anyone wondered):

void Camera::zoomOut(float dt) {


    _cameraScale -= _scaleSpeed * dt;

    if (_cameraScale < 0.4f) {

        _cameraScale = 0.4f;
    }
}

According to the first answer edit: As I have 4x4 matrix and using a vec3 for my point representation, i have to use temporary vec4 to perform the multiplication, however, it is not working correctly (even without scaling and just translating the view matrix) - for inverse matrix im using GLM library.

glm::vec3 Camera::applyTransformationsToPoint(glm::vec3 pos) {

    glm::vec4 tmpVec(pos.x, pos.y, pos.z, 1.0f);
    tmpVec = tmpVec * glm::inverse(viewMatrix);

    return glm::vec3(tmpVec.x,tmpVec.y,tmpVec.z);
}
\$\endgroup\$
1
\$\begingroup\$

For any matrix transformation, the inverse matrix is what you can consider to be the transformation in "reverse".

Currently, the logic in your :applyTransformationsToPoint is basically calculating the inverse transformation directly for a standard matrix that has only ever been scaled and translated about the origin.

Instead, and as a more general solution, the INVERSE of the matrix you compute for the screen transform should be used to apply transformations to point instead.

So where you would have

m = new Matrix()
m.translate(screenWidth/2,screenHeight/2);
m.scale(scaleX, scaleY)
m.translate(-screenWidth/2,-screenHeight/2);

You would then also create

inv = m.invert()

And then your point transformation method would become

applyTransformationsToPoint(pt){
   return inv*pt   // where * is a matrix multiply
}

Hope that helps!

\$\endgroup\$
  • \$\begingroup\$ I have tried but it is not working - even without scaling and just translating the view matrix. I have updated the question according to your answer to see if I´m doing it right. \$\endgroup\$ – Pins Jun 19 '17 at 19:09
1
\$\begingroup\$

[EDIT 2]

You can change the scale of an orthographic projection matrix by modifying the left right bottom top values.

Here is the OpenGL call: glOrtho( -width/2*zoom, width/2*zoom, -height/2*zoom, height/2*zoom, -1, 1 );

Alternatively:

left = -width / 2 * zoom
right = width / 2 * zoom
bottom = -height / 2 * zoom
top = height / 2 * zoom
\$\endgroup\$
  • \$\begingroup\$ Yes this works for perspective projection but I´m using orthographic projection and as "zoom effect" I´ve decided to implement scaling of the view matrix. \$\endgroup\$ – Pins Jun 19 '17 at 19:32
  • \$\begingroup\$ Ah I see sorry I didn't read your question very carefully. \$\endgroup\$ – oscar toomey Jun 19 '17 at 19:33
  • \$\begingroup\$ I have updated my answer \$\endgroup\$ – oscar toomey Jun 19 '17 at 19:40
  • \$\begingroup\$ And what about the calculation of the screen point coordinates to the world coordinates? I mean, the way how I implemented the zooming is working great however I´m not able to transform screen coordinates into world coordinates correctly. \$\endgroup\$ – Pins Jun 19 '17 at 19:49
  • \$\begingroup\$ The shader is doing the following: projection_matrix * camera_matrix * model_matrix. To do the reverse, (ie screen to world) you simply have to reverse the equation: (camera_matrix * model_matrix) / projection_matrix. \$\endgroup\$ – oscar toomey Jun 19 '17 at 19:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.