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