Perspective matrix, frustum and CameraPersp [Solved]

Hi all,

I have a question regarding CameraPersp’s implementation. I’ve searched around and apparently there is no way of directly setting (or modifying frustum) for camera by directly applying mat4 value. Is there a mechanism already implemented that I could use to achieve this? By trial and error I’ve also found out that applying vertical and/or horizontal shift does what I need at this moment.

Thank you!

Hi,

the camera matrices by themselves are not very intuitive to use, so the Camera classes are there for you to create and update them. To do this, it tracks viewing angles, positions, targets etc.

If it would be allowed to set the view and projection matrices of a Camera directly, those values would have to be derived from those matrices, which is not always possible.

Therefor, if you already have a view and/or projection matrix, you can use them instead of a Camera using the gl::setViewMatrix and gl::setProjectionMatrix (or their equivalents and scoped versions).

For those wanting to learn more about camera’s (and what lens shift does), see the CameraPersp sample.

-Paul

Hi,

I already have both matrices manually calculated (and applied). What I want to achieve is to apply the projection matrix to correctly visualize camera in viewport (correct its shifts so the frustum is correctly drawn).

I can render my custom frustum, but since cinder already has this feature implemented and a solution is there (lens shifts), I would rather compute shifts and continue with camera functions :slight_smile:

Hi,

so how did you calculate the matrices? Or do you obtain them from other code? Because if you are calculating them yourself, you should have all the information (vertical field of view, distance from target, orientation, aspect ratio, etc.) already and you could use that to initialize the camera.

Like I said, some of those values can be extracted from the view and projection matrices, but not all of it. For instance:

vec3 camWorldPosition = vec3( glm::inverse( viewMatrix )[3] );

, but most values are non-trivial to extract, especially for asymmetric frustums (frusti?). Your best bet is still to try and obtain the values needed to construct the matrices.

-Paul

Camera data was obtained from opencv (and stored in a 3x3 classic camera matrix). Matrices were then converted to opengl and adjusted for cinder. World camera position and orientation were no-brainers, but the issue is still the projection matrix. I am creating projection matrix with glm::frustum.

I am leaning towards this. Calculate initial farclip coordinates with default projection matrix (no shifts), make transformation and calculate new poin’t ray intersection with camera’s eye point. Calculate relative distance between each pair.

Hi,

then why not use CameraPersp to setup a projection that you like and then do:

gl::ScopedMatrices scpMatrices;
gl::setViewMatrix( viewMatrixFromOpenCV );
gl::setProjectionMatrix( mCamera.getProjectionMatrix() );

? After all, if you’re going to draw to only half the window, you’ll need to adjust your horizontal field of view and aspect ratio, so you’re basically throwing away your old projection anyway.

-Paul

I calculate view matrix and projection matrix. I can use both matrices directly and get the result I want. But if I do, this camera’s frustum is wrong and misleading (the gl::drawfrustum). I want to fix this part and this is the projection view matrix.

Currently I use view matrix as mentioned above (this part works), but I want to extract vertical and horizontal lens shifts from projection matrix. Everything is already set (fov, aspect) dynamically.

So to get to the clean gl::setMatrices(mCamera), I need to fix the vertical and horizontal shifts. This way projection matrix will be in “native format” (view matrix already is, but I can’t call setMatrices(mCamera) if projection matrix is not ok).

Edit: setting correct vertical and horizontal lens shifts does produce the correct projection matrix. I just need the two numbers to get there.

To calculate the lens shift, you’d need the left and right extremes of the frustum (for horizontal lens shift) and the top and bottom extremes for the vertical lens shift.

If LEFT == -RIGHT and TOP == -BOTTOM, there is no lens shift and the frustum is symmetrical.

If you look at the definition of an asymmetrical projection matrix, I think you may find the horizontal lens shift described as (l+r)/(r-l) and the vertical lens shift as (t+b)/(t-b). You could try to use those values from the matrix, just remember that you may have to swap column and row as the documentation is for DirectX which uses a different matrix notation.

Let me know if that worked.

-Paul

Edit: tried it and yes!

float lensShiftHorizontal = projectionMatrix[2][0];
float lensShiftVertical = projectionMatrix[2][1];

Bingo, thats it.
Thank you, Paul!