1 #ifndef STEREOCONTEXT_H
2 #define STEREOCONTEXT_H
3 
4 
5 class StereoContext
6 {
7   public:
8 
9     StereoContext(bool do_quad_buffered_stereo=false) :
quadbuffered(do_quad_buffered_stereo)10       quadbuffered(do_quad_buffered_stereo),
11       aperture(90),
12       focallength(1.22),
13       eyeseparation(0.07),
14       near(0.4),
15       far(250),
16       winw(1024),
17       winh(768)
18     {
19       contexts[0] = new ssgContext();
20       contexts[1] = new ssgContext();
21       contexts[0]->setNearFar(near, far);
22       contexts[1]->setNearFar(near, far);
23     }
24 
~StereoContext()25     ~StereoContext()
26     {
27       delete contexts[0];
28       delete contexts[1];
29     }
30 
MakeCurrent(const std::string & channel)31     void MakeCurrent(const std::string &channel)
32     {
33       assert(channel=="left" || channel=="right" || channel=="center");
34 
35       ssgContext *context=0;
36       if (channel=="left")  context=contexts[0];
37       if (channel=="right") context=contexts[1];
38       assert(context);
39 
40       if (quadbuffered)
41       {
42         if (channel=="left")  glDrawBuffer(GL_BACK_LEFT);
43         if (channel=="right") glDrawBuffer(GL_BACK_RIGHT);
44         glViewport(0,0,winw,winh);
45       }
46       else
47       {
48         // Do viewport
49         if (channel=="right")
50           glViewport(winw, 0, winw, winh);
51         if (channel=="left")
52           glViewport(0,0, winw, winh);
53         if (channel=="center")
54           glViewport(0,0, winw*2, winh);
55       }
56 
57       // Do Frustum
58       float ratio  = winw / (float) winh;
59       float wd2    = near * tan(0.5 * aperture * M_PI / 180);
60       float ndfl   = near / focallength;
61       float left   = -ratio * wd2;
62       float right  =  ratio * wd2;
63       float top    =  wd2;
64       float bottom = -wd2;
65       // For the left camera, the frustum should be shifted to the right.
66       float separation_in_near_plane = eyeseparation * ndfl;
67       if (channel == "left")
68       {
69         left  = -ratio * wd2 + 0.5 * separation_in_near_plane;
70         right =  ratio * wd2 + 0.5 * separation_in_near_plane;
71       }
72       if (channel == "right")
73       {
74         left  = -ratio * wd2 - 0.5 * separation_in_near_plane;
75         right =  ratio * wd2 - 0.5 * separation_in_near_plane;
76       }
77       context->setFrustum(left, right, bottom, top, near, far);
78 
79       // Do camera
80       sgVec3 r={0,0,0};
81       sgVectorProductVec3(r, cam_dir, cam_up);
82 
83       if (channel=="left")
84         sgScaleVec3(r, -0.5 * eyeseparation);
85       if (channel=="right")
86         sgScaleVec3(r,  0.5 * eyeseparation);
87 
88       sgVec3 eye = { cam_eye[0] + r[0], cam_eye[1] + r[1], cam_eye[2] + r[2] };
89       sgVec3 coi = { cam_eye[0] + cam_dir[0] + r[0], cam_eye[1] + cam_dir[1] + r[1], cam_eye[2] + cam_dir[2] + r[2] };
90       sgVec3 up  = { cam_up[0], cam_up[1], cam_up[2] };
91 
92       context->setCameraLookAt(eye, coi, up);
93       context->makeCurrent();
94     }
95 
SetAperture(float a)96     void SetAperture(float a) { aperture = a; }
SetFocalLength(float f)97     void SetFocalLength(float f) { focallength = f; }
SetEyeSeparation(float e)98     void SetEyeSeparation(float e) { eyeseparation = e; }
SetNear(float n)99     void SetNear(float n) { near = n; }
SetFar(float f)100     void SetFar(float f) { far = f; }
SetWindowSize(int w,int h)101     void SetWindowSize(int w, int h)
102     {
103       winw=w;
104       winh=h;
105     }
SetCameraLookAt(const sgVec3 eye,const sgVec3 coi,const sgVec3 up)106     void SetCameraLookAt(const sgVec3 eye, const sgVec3 coi, const sgVec3 up)
107     {
108       sgCopyVec3(cam_up,  up);
109       sgCopyVec3(cam_eye, eye);
110       sgCopyVec3(cam_dir, coi);
111       sgSubVec3(cam_dir,  eye);
112       sgNormalizeVec3(cam_dir);
113     }
IsQuadBuffered(void)114     bool IsQuadBuffered(void) const { return quadbuffered; }
115 
116   protected:
117 
118     bool  quadbuffered;		// When false, do passive stereo
119     float aperture;		// degrees
120     float focallength;		// meters
121     float eyeseparation;	// meters
122     float near;			// meters
123     float far;			// meters
124     int   winw;			// pixels
125     int   winh;			// pixels
126     sgVec3 cam_eye;		// position
127     sgVec3 cam_dir;		// unit vector
128     sgVec3 cam_up;		// unit vector
129 
130     ssgContext *contexts[2];	// 0 is L, 1 is R
131 };
132 
133 #endif
134 
135