3
\$\begingroup\$

I'm trying to achieve a dolly zoom effect.
My first try was the obvious one, the original "zoom in & dolly out" technique, which works nicely.
Except that there are cases which this is not possible due spatial conditions (E.g.: camera close to a wall)

If you pull back the camera too much you may occlude the view with some other objects (the red area).

To solve this I figured that I can't move the camera. Instead, I have to change the frustum, making a larger near plane and a smaller far plane.

This way, it's possible to control de effect without moving the camera.

I know how to build the perspective and orthogonal projection matrices, and I was able to interpolate between them (interpolating each element separately).
This got me really near to solve the puzzle.

The only problem now is to set a distance from the camera to keep my frustum height, effectively locking the focus in an object/position.
But I can't figure this one out.

So, any ideas?


Aditional info

This is the matrices that I'm using:

4x4 matrix for orthogonal projection

   0         1         2          3
  -----------------------------------------------
0 | 2/(r-l) |         |          | -(r+l)/(r-l) |
  -----------------------------------------------
1 |         | 2/(t-b) |          | -(t+b)/(t-b) |
  -----------------------------------------------
2 |         |         | -2/(f-n) | -(f+n)/(f-n) |
  -----------------------------------------------
3 |         |         |          | 1            |
  -----------------------------------------------

4x4 matrix for perspective projection

   0           1         2              3
  -----------------------------------------------------
0 | 2n/(r-l) |          | (r+l)/(r-l)  |              |
  -----------------------------------------------------
1 |          | 2n/(t-b) | (t+b)/(t-b)  |              |
  -----------------------------------------------------
2 |          |          | -(f+n)/(f-n) | -2*f*n/(f-n) |
  -----------------------------------------------------
3 |          |          | -1           |              |
  -----------------------------------------------------

To interpolate them, I use something like this (pseudo-code):

interpolate (from, to, percentage)
{
    matrix = []
    i = 0
    while (i < 16)
    {
        matrix[i] = from[i] + (to[i] - from[i]) * percentage
        i++
    }
    return matrix;
}

projection = interpolate(perspective, orthogonal, 0.75)
\$\endgroup\$
  • 1
    \$\begingroup\$ This is still moving the camera. (Logically, the camera's position is the point where the sides of the frustum would meet, if extended past the near plane) What you need to do here is adjust your near plane distance to crop out the obstacles between this logical position and the front of the object you want to draw. \$\endgroup\$ – DMGregory Oct 14 '19 at 19:31

Your Answer

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

Browse other questions tagged or ask your own question.