binocularity.org
Knowledge about all aspects of 3D displays and their application.
Home3D DisplaysHuman 3D VisionCreating 3D ImagesResources

Drawing stereo pairs
Toed-in cameras
Parallel cameras
3D photography method
..3D photography equipment
3D filming
Stereoscopic OpenGL
..Toed-in OpenGL example
..Parallel OpenGL example


..Toed-in OpenGL example

Contributors: Jimmy Kay, Peter Hughes, Nick Holliman

Source code files: 
Download Binocularity OpenGL Examples (Python)
                                 Download Binocularity OpenGL Examples (C++)



The Toed-in approach involves rotation of the cameras so the camera axes verge at a single point. The diagram below shows an example of this (with an exaggerated angle for easier visualisation) with reference to the anaglyph option available with the stereo demos.




As is demonstrated in the above diagram, there is significant rotation affecting the placement of the drawn cubes, which directly results in the vertical parallax often encountered when viewing stereo images with the Toed-in camera implementation.

When viewing the stereo images, the centre cube is less affected by this rotation, and will therefore suffer less with vertical disparity. Objects drawn towards the edge of the screen pane, particularly at the corners, will be affected more dramatically, potentially causing the image to lose any stereo effect, and also making images more uncomfortable to view.

When running the demonstration program, this vertical disparity can clearly be seen, as in the image below:





The top left of the image is under magnification to highlight vertical disparity and other effects of camera rotation. Anaglyph display highlights these areas very effectively due to the Red and Green viewpoints for the left and right eye respectively.

The highlighted area clearly shows the left eye image (Red) appearing above the right eye view (Green), giving a distorted view. Effects of this kind introduce unusual effects such as an apparent horizontal curvature in the overall view when seen in stereo.


Calculating the camera positions (Toed-in) 

In both Parallel, and Toed-in examples, two files exist. stereoCamera.py is a helper class which defines the camera dimensions and orientation.

Values are defined as millimetres throughout.

The diagram below displays the X, Y and Z axis, as displayed from the viewing position, and OpenGL gluLookAt points. Values of increasing depth (into the screen) will be of a greater negative value along the Z axis, this convention follows for both parallel, and toed-in lookAt points.


For mono viewing (non-stereo) when considering the gluLookAt parameters; the centre point values of the display for X, and Y axis (as above) are 0 and the corresponding point for the Z axis (depth) is -1000; the eye point depicted in the above diagram is 0 for the X, Y and Z axes.

from the file stereoCamera.py


def update( self ):
        w = 518.4
        h = 324.0
       
        Z = 1000.0
        A = 65.0  
        Near = 800.0
        Far = 1200.0

        half_fov = math.atan( (h/2.0) / Z )
        fov = math.degrees( 2.0 * half_fov )
       
        self.lookAtLeft   = ( -A/2, 0, 0, 0, 0, -Z, 0, 1, 0 )
        self.lookAtRight = ( A/2, 0, 0, 0, 0, -Z, 0, 1, 0 )
       
        self.gluPerspective = ( fov, w/h, Near, Far )


The self.lookAtRight, and self.lookAtLeft statements are variables which can be accessed by toedin.py. These statements are updated and defined as lists, holding the values to be accessed when setting the gluLookAt points for both the Left and Right Buffers.

The lookAt points are near identical, excepting the x axis eye point (camera point), which is separated by half the average human eye separation 32.5mm (A/2). Left is set at a negative value, and right positive, in order to equal eye (camera) separation by 65mm.

The centre position (or the position of the display screen) is set at z axis (depth) -1000mm (-Z).

Finally, values for gluPerspective are set, which will be identical for each eye – again, these values are defined as a list, which will be used by toedin.py.

The gluPespective method, sets a perspective projection matrix, and will simply take four values. Field of View (fov), a width/height ratio (w/h), and values for the near and far clipping panes for the scene (Near, Far).

The Field of view is calculated, and converted to degrees (for this it is necessary to import the math library into the program). For OpenGL the field of view must be calculated vertically and therefore the value for height, rather than width is used.

Calculating the Field Of View Angle (fov)

half_fov = math.atan( (h/2.0) / Z )

where:
h = 324             therefore:  324/2 = 162  and  162/Z = 0.162
                        because Z = 1000  by definition

half_fov = atan ( 0.162 )
                        calculates the half field of view in radians

fov = math.degrees( 2.0 * half_fov )
         math.degrees converts the angle into degrees, necessary for the OpenGL gluPerspective call.

          resulting in  fov = 18.4



from the file toedin.py

def render( side ):
    """Render scene in either GLU_BACK_LEFT or GLU_BACK_RIGHT buffer"""
    boxSize = 50
    separate = 100
    glViewport( 0, 0, glutGet( GLUT_WINDOW_WIDTH ), glutGet( GLUT_WINDOW_HEIGHT ) )
    if side == GL_BACK_LEFT:
        g = sC.gluPerspective
        l = sC.lookAtLeft
    else:
        g = sC.gluPerspective
        l = sC.lookAtRight
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective( g[0], g[1], g[2], g[3] )
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    gluLookAt( l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8] )


The above code from toedin.py is concerned with using the perspective values from stereoCamera.py.

stereoCamera.py is instantiated as object sC using :

from stereoCamera import StereoCamera
sC = StereoCamera( )

The Back Left and Back Right buffers are called in turn, variables g, and l are instantiated to call values for gluPerspective and gluLookAt respectively. These values are gathered from lists created in stereoCamera.py as discussed earlier.

To initiate true stereo mode, using quad buffered hardware, the program will require SHUTTER as a second argument when initiating the program. In this instance stereo is initiated by a call to:

glutInitDisplayMode( GLUT_STEREO | GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH )

This will initialise the GLUT library for stereo viewing. If the hardware or drivers do not support this function, the SHUTTER request will fail.



Home3D DisplaysHuman 3D VisionCreating 3D ImagesResources