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)