I have a projection matrix derived from the camera calibration in an augmented reality app and as long as the screen aspect ratio matches the camera image aspect ratio everything is fine. When the camera image doesn't match the screen edge-for-edge you'll get distortion in the tracking.
The problem scenarios:
The working scenarios:
Goal: I want to handle this screen / camera aspect ratio mismatch in a general way.
This problem exists because the view has normalized device coordinates in the aspect ratio of the screen (4:3 for iPad), whereas the projection matrix has an aspect ratio of the camera image (16:9 for 720p). The background image needs to match up to the projection matrix or the illusion of augmented reality fails so if I want to toggle between 'fit' and 'fill' I'll need to change projection matrix to match the image size.
Note: I'm looking to deal with this problem without an OpenGL specific solution. So I'm looking for a more general mathematical answer that involves manipulating the projection matrix.
OpenGL consists of two general classes of projection transformations: orthographic (parallel) and perspective.
GL_PROJECTION matrix is used for this projection transformation. First, it transforms all vertex data from the eye coordinates to the clip coordinates. Then, these clip coordinates are also transformed to the normalized device coordinates (NDC) by dividing with w component of the clip coordinates.
The first matrix discussed below is the model matrix, which defines how you take your original model data and move it around in 3D world space. The projection matrix is used to convert world space coordinates into clip space coordinates.
Setting up the perspective projection matrix in OpenGL was done through a call to glFrustum. The function took six arguments: glFrustum(float left, float right, float bottom, float top, float near, float far); The implementation of this function can be found in the code below (line 20).
However, I realize I need to map the camera's projection matrix to the screen projection matrix or perhaps scale it.
Aspect ratio really just determines what is on screen (i.e. amount of peripheral vision you get) - it shouldn't fundamentally change the projection (assuming you keep the near and far clips the same).
First thing to note is that there isn't really a safe mapping (i.e. not every coordinate in the screen view has an equivalent in the camera view, and visa-versa).
To avoid distortion you really have two options - clip to the narrower of the two options (discard information) or scale down with letter box and keep the original aspect ratio (discard screen-area) .
Both feel like it should be possible with a simple scale factor applied to the final clip-space transform (assuming you clip equally on both sides of the frustum you should just be able to multiply up the clip-space coordinate of the axis you want to clip (scale > 1), or multiple down (scale < 1) if you want letterbox). To make letterboxing work you'll need to to use glViewport or glScissor to stop primitives outside of the letterbox being drawn.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With