Statistics
| Revision:

root / PyOpenGL-Demo / proesch / stereo / stereoCamera.py @ 1

History | View | Annotate | Download (3.9 kB)

1
# helper class for stereo visualisation using OpenGL
2
# The underlying equations and their implementation are by courtesy of 
3
# Paul Bourke, http://local.wasp.uwa.edu.au/~pbourke/projection/stereorender/
4
# 
5
# Copyright (C) 2007  "Peter Roesch" <Peter.Roesch@fh-augsburg.de>
6
#
7
# This code is licensed under the PyOpenGL License.
8
# Details are given in the file license.txt included in this distribution.
9

    
10
import sys
11
import math
12

    
13
try:
14
  from OpenGL.GLUT import *
15
  from OpenGL.GL import *
16
  from OpenGL.GLU import *
17
except:
18
  print ''' Error: PyOpenGL not installed properly !!'''
19
  sys.exit(  )
20

    
21
class StereoCamera( object ):
22
        """Helper class for stereo frustum calculation.
23

24
        Frustum settings for left and right camera are
25
        calculated according to parameters e.g. eye
26
        separtion"""
27
        DEG2RAD = math.pi / 180.0
28

    
29
        def __init__( self ):
30
                self.centerPosition = [ 0, 0, 10 ]
31
                self.viewingDirection = [ 0, 0, -1 ]
32
                self.upVector = [ 0, 1, 0 ]
33
                self.near, self.far, self.focalLength = 0.1, 100.0, 10.0
34
                self.whRatio = 4.0/3.0
35
                self.aperture = 60.0
36
                self.eyeSeparation = self.focalLength / 20.0
37
                self.eyePositionLeft, self.eyePositionRight = [ ], [ ]
38
                self.frustumLeft = ( )
39
                self.frustumRight = ( )
40
                self.lookAtRight = ( )
41
                self.lookAtLeft = ( )
42

    
43
        def difference( self, a, b):
44
                """Calculate difference vector."""
45
                if not (len( a ) == len ( b )):
46
                        print ''' Error: different vector length in sub'''
47
                        sys.exit(  )
48
                c=[ 0 for i in range( len( a ) ) ]
49
                for i in range( len( a )):
50
                        c[i] = a[i]-b[i]
51
                return c
52

    
53
        def sum( self, a, b ):
54
                """Calculate sum vector."""
55
                if not (len( a ) == len ( b )):
56
                        print ''' Error: different vector length in add'''
57
                        sys.exit(  )
58
                c=[ 0 for i in range( len( a ) ) ]
59
                for i in range( len( a ) ):
60
                        c[i] = a[i]+b[i]
61
                return c
62

    
63
        def scale( self, a, f ):
64
                """Scale a vector."""
65
                for i in range( len( a ) ):
66
                        a[i] = a[i]*f
67

    
68
        def crossProduct( self, a, b ):
69
                """Cross product of two 3D vectors."""
70
                if len( a ) != 3 or len( b ) != 3:
71
                        print ''' Error: cross product needs 3D vectors as input'''
72
                        sys.exit(  )
73
                c=[ 0, 0, 0 ]
74
                c[0] = a[1]*b[2]-a[2]*b[1]
75
                c[1] = a[2]*b[0]-a[0]*b[2]
76
                c[2] = a[0]*b[1]-a[1]*b[0]
77
                return c
78

    
79
        def update( self ):
80
                """Calculate left and right frustum."""
81
                betweenTheEyes = self.crossProduct( self.viewingDirection, self.upVector )
82
                self.scale( betweenTheEyes, self.eyeSeparation/2.0 )
83
                self.eyePositionLeft = self.difference( self.centerPosition,
84
                        betweenTheEyes )
85
                self.eyePositionRight = self.sum( self.centerPosition, betweenTheEyes )
86
                self.lookAtLeft = ( 
87
                        self.eyePositionLeft[0],
88
                        self.eyePositionLeft[1],
89
                        self.eyePositionLeft[2],
90
                        self.eyePositionLeft[0]+self.viewingDirection[0],
91
                        self.eyePositionLeft[1]+self.viewingDirection[1],
92
                        self.eyePositionLeft[2]+self.viewingDirection[2],
93
                        self.upVector[0], self.upVector[1], self.upVector[2] )
94
                self.lookAtRight = ( 
95
                        self.eyePositionRight[0],
96
                        self.eyePositionRight[1],
97
                        self.eyePositionRight[2],
98
                        self.eyePositionRight[0]+self.viewingDirection[0],
99
                        self.eyePositionRight[1]+self.viewingDirection[1],
100
                        self.eyePositionRight[2]+self.viewingDirection[2],
101
                        self.upVector[0], self.upVector[1], self.upVector[2] )
102
                perpDelta = self.near * math.tan( self.aperture*StereoCamera.DEG2RAD/2.0 )
103
                parallaxCorrection = self.near/self.focalLength;
104
                self.frustumLeft = (
105
                        -self.whRatio*perpDelta+self.eyeSeparation/2.0*parallaxCorrection,
106
                        self.whRatio*perpDelta+self.eyeSeparation/2.0*parallaxCorrection,
107
                        -perpDelta, perpDelta, self.near, self.far )
108
                self.frustumRight = (
109
                        -self.whRatio*perpDelta-self.eyeSeparation/2.0*parallaxCorrection,
110
                        self.whRatio*perpDelta-self.eyeSeparation/2.0*parallaxCorrection,
111
                        -perpDelta, perpDelta, self.near, self.far )
112

    
113
# test program
114
if __name__ == '__main__' :
115
        sC = StereoCamera( )
116
        a=[1,0,0]
117
        b=[0,0,1]
118
        print sC.crossProduct( a, b )
119
        sC.update( )
120
        print sC.lookAtLeft
121
        print sC.frustumLeft
122
        print sC.lookAtRight
123
        print sC.frustumRight