Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL ES Screen Projection Matrix and Camera Projection Matrix

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:

  • 1280x720 video on an iPad
  • 640x480 video on an iPhone 5S.

The working scenarios:

  • 640x480 video on an iPad
  • 1280x720 video on an iPhone 5S.

Goal: I want to handle this screen / camera aspect ratio mismatch in a general way.

Example of letterbox format

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.

like image 329
Cameron Lowell Palmer Avatar asked Feb 11 '15 10:02

Cameron Lowell Palmer


People also ask

What are the two main projection methods used in OpenGL?

OpenGL consists of two general classes of projection transformations: orthographic (parallel) and perspective.

What is projection matrix in OpenGL?

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.

What is the difference between the model view matrix and projection matrix in OpenGL?

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.

How do I get the projection matrix in OpenGL?

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).


1 Answers

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.

like image 127
solidpixel Avatar answered Sep 21 '22 12:09

solidpixel