QtBaseViewerStereo.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 8520 $                                                         *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2010-02-10 15:56:59 +0100 (Mi, 10. Feb 2010) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 //=============================================================================
00047 //
00048 //  CLASS glViewer - IMPLEMENTATION
00049 //
00050 //=============================================================================
00051 
00052 
00053 //== INCLUDES =================================================================
00054 
00055 #include "QtBaseViewer.hh"
00056 #include <QStatusBar>
00057 #include <QToolButton>
00058 
00059 #include <OpenFlipper/common/GlobalOptions.hh>
00060 
00061 #include <QGLFramebufferObject>
00062 
00063 #include <ACG/ShaderUtils/GLSLShader.hh>
00064 #include <ACG/GL/globjects.hh>
00065 
00066 #include <ACG/ShaderUtils/gldebug.h>
00067 
00068 #include "crc32.hh"
00069 
00070 //== NAMESPACES ===============================================================
00071 
00072 
00073 //== IMPLEMENTATION ==========================================================
00074 
00075 static const char* customAnaglyphProg = {
00076   "!!ARBfp1.0"
00077   "TEMP left, right, lmul, rmul;"
00078   "TEX left, fragment.texcoord[0], texture[0], RECT;"
00079   "TEX right, fragment.texcoord[0], texture[1], RECT;"
00080   "DP3 lmul.r, left, program.env[0];"
00081   "DP3 lmul.g, left, program.env[1];"
00082   "DP3 lmul.b, left, program.env[2];"
00083   "DP3 rmul.r, right, program.env[3];"
00084   "DP3 rmul.g, right, program.env[4];"
00085   "DP3 rmul.b, right, program.env[5];"
00086   "ADD result.color, lmul, rmul;"
00087   "END"
00088 };
00089 
00090 //-----------------------------------------------------------------------------
00091 
00092 
00093 void
00094 glViewer::setStereoMode(bool _b)
00095 {
00096   stereo_ = _b;
00097 
00098   if (!stereo_) {
00099     makeCurrent();
00100     glDrawBuffer(GL_BACK);
00101   }
00102 
00103   updateProjectionMatrix ();
00104 
00105   updateGL();
00106 }
00107 
00108 //-----------------------------------------------------------------------------
00109 
00110 
00111 void
00112 glViewer::drawScene_glStereo()
00113 {
00114   double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange;
00115 
00116   w = glWidth();
00117   h = glHeight();
00118   a = w / h;
00119 
00120   radians = fovy_ * 0.5 / 180.0 * M_PI;
00121   wd2     = near_ * tan(radians);
00122   zerop   = near_ + ((far_ - near_) * OpenFlipperSettings().value("Core/Stereo/FocalDistance").toDouble() );
00123   ndfl    = near_ / zerop ;
00124   xrange  = a * wd2 * 2 * zerop / near_;
00125 
00126   l = -a*wd2;
00127   r =  a*wd2;
00128   t =  wd2;
00129   b = -wd2;
00130 
00131   double offset  = 0.5 * OpenFlipperSettings().value("Core/Stereo/EyeDistance").toDouble()  * xrange;
00132   double offset2 = offset * ndfl;
00133 
00134   // left eye
00135   glMatrixMode(GL_PROJECTION);
00136   glLoadIdentity();
00137   glFrustum(l+offset2, r+offset2, b, t, near_, far_);
00138   glTranslatef(+offset, 0.0, 0.0);
00139   glMatrixMode(GL_MODELVIEW);
00140   glDrawBuffer(GL_BACK_LEFT);
00141   glstate_->clearBuffers ();
00142   glClear(GL_DEPTH_BUFFER_BIT);
00143   drawScene_mono();
00144 
00145 
00146   // right eye
00147   glMatrixMode(GL_PROJECTION);
00148   glLoadIdentity();
00149   glFrustum(l-offset2, r-offset2, b, t, near_, far_);
00150   glTranslatef(-offset, 0.0, 0.0);
00151   glMatrixMode(GL_MODELVIEW);
00152   glDrawBuffer(GL_BACK_RIGHT);
00153   glstate_->clearBuffers ();
00154   glClear(GL_DEPTH_BUFFER_BIT);
00155   drawScene_mono();
00156   glDrawBuffer(GL_BACK);
00157 }
00158 
00159 
00160 void glViewer::drawScenePhilipsStereo() {
00161 
00162     updateScenePhilipsStereo();
00163 
00164     if (!philipsStereoInitialized_)
00165         return;
00166 
00167     int vp_l, vp_b, vp_w, vp_h;
00168     glstate_->get_viewport(vp_l, vp_b, vp_w, vp_h);
00169 
00170     // ======================================================================================================
00171     // Disable textures
00172     // ======================================================================================================
00173     pDepthStencilTexture_.disable();
00174     pColorTexture_.disable();
00175 
00176     // ======================================================================================================
00177     // Render the scene
00178     // ======================================================================================================
00179     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00180     drawScene_mono();
00181 
00182     // ======================================================================================================
00183     // Copy Scene to Textures
00184     // ======================================================================================================
00185     pColorTexture_.enable();
00186     pColorTexture_.bind();
00187 
00188     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, vp_l, vp_b, vp_w, vp_h);
00189 
00190     pColorTexture_.disable();
00191 
00192     pDepthStencilTexture_.enable();
00193     pDepthStencilTexture_.bind();
00194 
00195     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, vp_l, vp_b, vp_w, vp_h);
00196 
00197     pDepthStencilTexture_.disable();
00198 
00199     // Turn on shader program
00200     pProgram_->use();
00201 
00202     // ======================================================================================================
00203     // Bind textures to different texture units and tell shader where to find them
00204     // ======================================================================================================
00205     glActiveTextureARB(GL_TEXTURE0_ARB);
00206     pColorTexture_.enable();
00207     pColorTexture_.bind();
00208 
00209     glActiveTextureARB(GL_TEXTURE1_ARB);
00210     pDepthStencilTexture_.enable();
00211     pDepthStencilTexture_.bind();
00212 
00213     pProgram_->setUniform("ColorTexture", 0);
00214     pProgram_->setUniform("DepthStencil", 1);
00215 
00216     // ======================================================================================================
00217     // Render plain textured
00218     // ======================================================================================================
00219     glDisable(GL_LIGHTING);
00220     glDisable(GL_COLOR_MATERIAL);
00221     glDisable(GL_DEPTH_TEST);
00222 
00223     // ======================================================================================================
00224     // Setup orthogonal projection
00225     // ======================================================================================================
00226     glstate_->push_projection_matrix();
00227     glstate_->push_modelview_matrix();
00228 
00229     glstate_->reset_projection();
00230     glstate_->reset_modelview();
00231 
00232     glstate_->ortho(0, vp_w, 0, vp_h, 0, 1);
00233 
00234     // ======================================================================================================
00235     // Bind textures to different texture units and tell shader where to find them
00236     // ======================================================================================================
00237     glColor3f(1.0, 1.0, 1.0);
00238 
00239     // ======================================================================================================
00240     // Clear buffers
00241     // ======================================================================================================
00242     glClearColor(.0, .0, .0, 0);
00243     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00244 
00245     // ======================================================================================================
00246     // Render a simple quad (rest is done by shader)
00247     // ======================================================================================================
00248     glBegin(GL_QUADS);
00249     glTexCoord2f(0.0f, 1.0f);
00250     glVertex2i(0, vp_h);
00251     glTexCoord2f(1.0f, 1.0f);
00252     glVertex2i(vp_w, vp_h);
00253     glTexCoord2f(1.0f, 0.0f);
00254     glVertex2i(vp_w, 0);
00255     glTexCoord2f(0.0f, 0.0f);
00256     glVertex2i(0, 0);
00257     glEnd();
00258 
00259     pProgram_->disable();
00260 
00261     glBindTexture(GL_TEXTURE_2D, 0);
00262 
00263     // ======================================================================================================
00264     // Cleanup (color and depth textures)
00265     // ======================================================================================================
00266     pDepthStencilTexture_.del();
00267     pColorTexture_.del();
00268 
00269     // ======================================================================================================
00270     // Compute the header required for the display
00271     // ======================================================================================================
00272     uchar *header = new uchar[6];
00273 
00274     //   Header ID
00275     //   Basic identifier used by the display to verify the header
00276     header[0] = 241; // Header_ID1 = 11110001
00277 
00278     //   Header content type
00279     //   This entry controls the displays internal rendering based on the input data specified here.
00280     //   There is no info about how this changes the rendering
00281     //   Possible values:
00282     //   0 No Depth
00283     //   1 Signage
00284     //   2 Movie
00285     //   3 Game
00286     //   4 CGI
00287     //   5 Still
00288     header[1] = OpenFlipperSettings().value("Core/Stereo/Philips/Content").toInt(); // Hdr_Content_type (Game) = 00000011 (Gaming Mode)
00289 
00290     //   Header Factor
00291     //   Each 3D Display has a 'Display recommended depth value', which corresponds to an
00292     //   acceptable maximum depth factor value for that specific type of display. This value strongly
00293     //   depends on the lens design. The factor field in the header contains the percentage to be
00294     //   used from the display recommended depth value. The value of 64 corresponds with the 100%
00295     //   of the display recommended depth value. It is allowed to use values higher than 64. The factor
00296     //   works on a linear scale and is multiplied with the factor controlled by the user in the Display
00297     //   Control Tool.
00298     //   Value range: 0-255 (default 64)
00299     header[2] = OpenFlipperSettings().value("Core/Stereo/Philips/Factor").toInt(); // Hdr_Factor
00300 
00301     //   Header Offset CC
00302     //   Values in the Depth map equal to the header-offset value will be located on the plane of the
00303     //   display. All values in the disparity map with a higher value will de displayed in front of the
00304     //   display.
00305     //   Offset_CC is the offset controlled by the Content Creator. In the system there is also an
00306     //   Offset_user present, which is controlled by the user using the Display Control Tool.
00307     //   Value Range: 0-255 (default 128)
00308     header[3] = OpenFlipperSettings().value("Core/Stereo/Philips/Offset").toInt(); // Hdr_Offset_CC
00309 
00310     //   Header select
00311     //   When all select signals are low the rendering settings are set to optimal settings for the content
00312     //   type denoted by Hdr_content_type. By making select signals high the settings for Factor and
00313     //   Offset_cc can be controlled individually by the header.
00314     //   Possible Values:
00315     //   0 Use Displays defaults and automatic optimizations
00316     //   1 Use Header provided factor
00317     //   2 Use Header provided offset
00318     //   3 Use both factor and offset
00319     header[4] = OpenFlipperSettings().value("Core/Stereo/Philips/Select").toInt(); // Hdr_Factor_select(1) + Hdr_Offset_select(1) + reserved(6)
00320 
00321     //   Unused Header entry (leave at 0 !)
00322     header[5] = 0; // Reserved
00323 
00324     //   Header checksum.
00325     //   The 4-byte EDC field H(6) − H(9) contains an Error Detection Code computed over the first 6
00326     //   header bytes. This EDC uses the standard CRC-32 polynomial as defined in IEEE 802.3 and ITU-T
00327     //   V.42. The initial value and final XOR value are both 0.
00328     //   unsigned long has 32bit = 4Byte
00329     unsigned long checksum = CalcCRC32(&header[0], 6);
00330 
00331     //   Store the complete header in a bit vector
00332     std::vector<uchar> bitVector;
00333 
00334     // For all bytes of the header
00335     for (int i = 0; i < 6; i++) {
00336 
00337         // For each bit of a headers byte
00338         for (int j = 7; j >= 0; --j) {
00339 
00340             // Red and Green component have to be 0
00341             bitVector.push_back(0);
00342             bitVector.push_back(0);
00343 
00344             // If bit is set, the full component will be set to one otherwise zero
00345             // And the order of the bits has to be reversed!
00346             if (header[i] & (1 << j)) {
00347                 bitVector.push_back(255);
00348             } else {
00349                 bitVector.push_back(0);
00350             }
00351 
00352             // Only every second pixel is used for the header
00353             // Skip every odd one by filling in 0 for RGB
00354             bitVector.push_back(0);
00355             bitVector.push_back(0);
00356             bitVector.push_back(0);
00357         }
00358     }
00359 
00360     // Append checksum to header.
00361     // Reversed bit order!
00362     for (int i = 31; i >= 0; i--) {
00363 
00364         // Red and Green component have to be 0
00365         bitVector.push_back(0);
00366         bitVector.push_back(0);
00367 
00368         if (checksum & (1 << i))
00369             bitVector.push_back(255);
00370         else
00371             bitVector.push_back(0);
00372 
00373         // Only every second pixel is used for the header
00374         // Skip every odd one by filling in 0 for RGB
00375         bitVector.push_back(0);
00376         bitVector.push_back(0);
00377         bitVector.push_back(0);
00378     }
00379 
00380     // Select the top left of the renderbuffer and
00381     // write complete header into these bits
00382     glRasterPos2i(0, glHeight() - 1);
00383     glDrawPixels(bitVector.size() / 3, 1, GL_RGB, GL_UNSIGNED_BYTE, &bitVector[0]);
00384 
00385     // ======================================================================================================
00386     // Reset projection and modelview
00387     // ======================================================================================================
00388     glstate_->pop_projection_matrix();
00389     glstate_->pop_modelview_matrix();
00390 
00391 }
00392 
00393 //-----------------------------------------------------------------------------
00394 
00395 void
00396 glViewer::updateScenePhilipsStereo()
00397 {
00398      int vp_l, vp_b, vp_w, vp_h;
00399      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
00400 
00401      // Does shader program exist?
00402      if (!pProgram_) {
00403 
00404         // ======================================================================================================
00405         // Setup the shaders used to render color and depth info next to each other
00406         // ======================================================================================================
00407         GLSL::PtrVertexShader vertexShader;
00408         GLSL::PtrFragmentShader fragmentShader;
00409 
00410         QString vshaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "Philips/Vertex.glsl";
00411         QString fshaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "Philips/Fragment42.glsl";
00412 
00413         vertexShader = GLSL::loadVertexShader(vshaderFile.toStdString().c_str());
00414         fragmentShader = GLSL::loadFragmentShader(fshaderFile.toStdString().c_str());
00415         pProgram_ = GLSL::PtrProgram(new GLSL::Program());
00416 
00417         if ((vertexShader == 0) || (fragmentShader == 0) || (pProgram_ == 0)) {
00418             std::cerr << "Unable to load shaders for philips display rendering!";
00419             philipsStereoInitialized_ = false;
00420             return;
00421         }
00422 
00423         pProgram_->attach(vertexShader);
00424         pProgram_->attach(fragmentShader);
00425         pProgram_->link();
00426     }
00427 
00428     // Does color texture exist?
00429     if (!pColorTexture_.is_valid()) {
00430         // ======================================================================================================
00431         // creating a color texture
00432         // ======================================================================================================
00433 
00434         pColorTexture_.enable();
00435         pColorTexture_.bind();
00436         GLenum texTarget = GL_TEXTURE_2D;
00437         GLenum texInternalFormat = GL_RGBA;
00438         GLenum texFormat = GL_RGBA;
00439         GLenum texType = GL_UNSIGNED_BYTE;
00440         GLenum texFilterMode = GL_NEAREST;
00441         glTexImage2D(texTarget, 0, texInternalFormat, vp_w, vp_h, 0, texFormat, texType, NULL);
00442 
00443         glTexParameterf(texTarget, GL_TEXTURE_MIN_FILTER, texFilterMode);
00444         glTexParameterf(texTarget, GL_TEXTURE_MAG_FILTER, texFilterMode);
00445         glTexParameterf(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00446         glTexParameterf(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00447         glTexParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00448 
00449         if(!pColorTexture_.is_valid()) {
00450             philipsStereoInitialized_ = false;
00451         }
00452     }
00453 
00454     // Does depth stencil texture exist?
00455     if (!pDepthStencilTexture_.is_valid()) {
00456         // ======================================================================================================
00457         // creating an 24-bit depth + 8-bit stencil texture
00458         // ======================================================================================================
00459 
00460         pDepthStencilTexture_.enable();
00461         pDepthStencilTexture_.bind();
00462         GLenum texTarget = GL_TEXTURE_2D;
00463         GLenum texInternalFormat = GL_DEPTH24_STENCIL8_EXT;
00464         GLenum texFormat = GL_DEPTH_STENCIL_EXT;
00465         GLenum texType = GL_UNSIGNED_INT_24_8_EXT;
00466         GLenum texFilterMode = GL_NEAREST;
00467         glTexImage2D(texTarget, 0, texInternalFormat, vp_w, vp_h, 0, texFormat, texType, NULL);
00468 
00469         glTexParameterf(texTarget, GL_TEXTURE_MIN_FILTER, texFilterMode);
00470         glTexParameterf(texTarget, GL_TEXTURE_MAG_FILTER, texFilterMode);
00471         glTexParameterf(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00472         glTexParameterf(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00473         glTexParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00474 
00475         if(!pDepthStencilTexture_.is_valid()) {
00476             philipsStereoInitialized_ = false;
00477         }
00478     }
00479 
00480     // Resize target textures
00481     if (glstate_->viewport_width() != pTexWidth_ ||
00482             glstate_->viewport_height() != pTexHeight_) {
00483 
00484         // Color texture
00485         pColorTexture_.bind();
00486         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width(), glstate_->viewport_height(), 0,
00487                 GL_RGB, GL_UNSIGNED_BYTE, 0);
00488 
00489         // Depth stencil texture
00490         pDepthStencilTexture_.bind();
00491         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width(), glstate_->viewport_height(), 0,
00492                 GL_RGB, GL_UNSIGNED_BYTE, 0);
00493 
00494         glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
00495 
00496         pTexWidth_ = glstate_->viewport_width();
00497         pTexHeight_ = glstate_->viewport_height();
00498     }
00499 
00500     philipsStereoInitialized_ = true;
00501 }
00502 
00503 //-----------------------------------------------------------------------------
00504 
00505 
00506 void
00507 glViewer::drawScene_anaglyphStereo()
00508 {
00509  double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange;
00510 
00511   w = glWidth();
00512   h = glHeight();
00513   a = w / h;
00514 
00515   radians = fovy_ * 0.5 / 180.0 * M_PI;
00516   wd2     = near_ * tan(radians);
00517   zerop   = near_ + ((far_ - near_) * OpenFlipperSettings().value("Core/Stereo/FocalDistance").toDouble() );
00518   ndfl    = near_ / zerop ;
00519   xrange  = a * wd2 * 2 * zerop / near_;
00520 
00521   l = -a*wd2;
00522   r =  a*wd2;
00523   t =  wd2;
00524   b = -wd2;
00525 
00526   double offset  = 0.5 * OpenFlipperSettings().value("Core/Stereo/EyeDistance").toDouble() * xrange;
00527   double offset2 = offset * ndfl;
00528 
00529   // left eye
00530   glMatrixMode(GL_PROJECTION);
00531   glLoadIdentity();
00532   glFrustum(l+offset2, r+offset2, b, t, near_, far_);
00533   glTranslatef(offset, 0.0, 0.0);
00534 
00535   glMatrixMode(GL_MODELVIEW);
00536   glstate_->clearBuffers ();
00537   glClear(GL_DEPTH_BUFFER_BIT);
00538 
00539   // draw red channel for left eye
00540   glColorMask(GL_TRUE,GL_FALSE,GL_FALSE,GL_TRUE);
00541   drawScene_mono();
00542   glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00543 
00544 
00545   // right eye
00546   glMatrixMode(GL_PROJECTION);
00547   glLoadIdentity();
00548   glFrustum(l-offset2, r-offset2, b, t, near_, far_);
00549   glTranslatef(-offset, 0.0, 0.0);
00550   glMatrixMode(GL_MODELVIEW);
00551   glClear(GL_DEPTH_BUFFER_BIT);
00552 
00553   // draw green and blue channel for right eye
00554   glColorMask(GL_FALSE,GL_TRUE,GL_TRUE,GL_TRUE);
00555   drawScene_mono();
00556   glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00557 
00558 }
00559 
00560 //-----------------------------------------------------------------------------
00561 
00562 void
00563 glViewer::updateCustomAnaglyphStereo()
00564 {
00565   if (!customAnaglyphSupported_)
00566     return;
00567 
00568   if (!agProgram_)
00569   {
00570     GLint errorPos;
00571 
00572     glGenProgramsARB (1, &agProgram_);
00573 
00574     glGetError ();
00575     glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, agProgram_);
00576     glProgramStringARB (GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
00577                         strlen (customAnaglyphProg), customAnaglyphProg);
00578 
00579     glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
00580     if (glGetError () != GL_NO_ERROR || errorPos != -1)
00581     {
00582       printf("Error loading program %d %s\n",errorPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
00583       glDeleteProgramsARB (1, &agProgram_);
00584       customAnaglyphSupported_ = false;
00585       return;
00586     }
00587   }
00588 
00589   if (!agTexture_[0])
00590     glGenTextures (2, agTexture_);
00591 
00592   if (!agTexture_[0])
00593   {
00594     finiCustomAnaglyphStereo ();
00595     customAnaglyphSupported_ = false;
00596     return;
00597   }
00598 
00599   if (glstate_->viewport_width () != agTexWidth_ ||
00600       glstate_->viewport_height () != agTexHeight_)
00601   {
00602     glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]);
00603     glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width (),
00604                   glstate_->viewport_height (), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
00605     glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]);
00606     glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width (),
00607                   glstate_->viewport_height (), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
00608     glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0);
00609 
00610     agTexWidth_ = glstate_->viewport_width ();
00611     agTexHeight_ = glstate_->viewport_height ();
00612   }
00613 }
00614 
00615 //-----------------------------------------------------------------------------
00616 
00617 void
00618 glViewer::finiCustomAnaglyphStereo()
00619 {
00620   if (!customAnaglyphSupported_)
00621     return;
00622 
00623   if (agProgram_)
00624     glDeleteProgramsARB (1, &agProgram_);
00625 
00626   if (agTexture_[0])
00627     glDeleteTextures (2, agTexture_);
00628 }
00629 
00630 //-----------------------------------------------------------------------------
00631 
00632 void
00633 glViewer::drawScene_customAnaglyphStereo()
00634 {
00635   updateCustomAnaglyphStereo ();
00636 
00637   if (!customAnaglyphSupported_)
00638     return;
00639 
00640   double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange;
00641 
00642   w = glWidth();
00643   h = glHeight();
00644   a = w / h;
00645 
00646   radians = fovy_ * 0.5 / 180.0 * M_PI;
00647   wd2     = near_ * tan(radians);
00648   zerop   = near_ + ((far_ - near_) * OpenFlipperSettings().value("Core/Stereo/FocalDistance").toDouble() );
00649   ndfl    = near_ / zerop ;
00650   xrange  = a * wd2 * 2 * zerop / near_;
00651 
00652   l = -a*wd2;
00653   r =  a*wd2;
00654   t =  wd2;
00655   b = -wd2;
00656 
00657   double offset  = 0.5 * OpenFlipperSettings().value("Core/Stereo/EyeDistance").toDouble() * xrange;
00658   double offset2 = offset * ndfl;
00659 
00660   int vp_l, vp_b, vp_w, vp_h;
00661   glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
00662 
00663   std::vector<float> le = OpenFlipper::Options::anaglyphLeftEyeColorMatrix();
00664   std::vector<float> re = OpenFlipper::Options::anaglyphRightEyeColorMatrix();
00665 
00666   // left eye
00667   glMatrixMode(GL_PROJECTION);
00668   glLoadIdentity();
00669   glFrustum(l+offset2, r+offset2, b, t, near_, far_);
00670   glTranslatef(offset, 0.0, 0.0);
00671   glMatrixMode(GL_MODELVIEW);
00672   glstate_->clearBuffers ();
00673   glClear(GL_DEPTH_BUFFER_BIT);
00674   drawScene_mono();
00675 
00676   glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]);
00677   glCopyTexSubImage2D (GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, vp_l, vp_b, vp_w, vp_h);
00678   glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0);
00679 
00680   // right eye
00681   glMatrixMode(GL_PROJECTION);
00682   glLoadIdentity();
00683   glFrustum(l-offset2, r-offset2, b, t, near_, far_);
00684   glTranslatef(-offset, 0.0, 0.0);
00685   glMatrixMode(GL_MODELVIEW);
00686   glstate_->clearBuffers ();
00687   glClear(GL_DEPTH_BUFFER_BIT);
00688   drawScene_mono();
00689 
00690   glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]);
00691   glCopyTexSubImage2D (GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, vp_l, vp_b, vp_w, vp_h);
00692   glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0);
00693 
00694   glActiveTexture (GL_TEXTURE0);
00695   glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]);
00696   glEnable (GL_TEXTURE_RECTANGLE_NV);
00697 
00698   glActiveTexture (GL_TEXTURE1);
00699   glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]);
00700   glEnable (GL_TEXTURE_RECTANGLE_NV);
00701 
00702   glEnable (GL_FRAGMENT_PROGRAM_ARB);
00703   glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, agProgram_);
00704 
00705   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, le[0], le[3], le[6], 0.0);
00706   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, le[1], le[4], le[7], 0.0);
00707   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 2, le[2], le[5], le[8], 0.0);
00708 
00709   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 3, re[0], re[3], re[6], 0.0);
00710   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 4, re[1], re[4], re[7], 0.0);
00711   glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 5, re[2], re[5], re[8], 0.0);
00712 
00713   glMatrixMode(GL_PROJECTION);
00714   glLoadIdentity();
00715   glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
00716   glMatrixMode(GL_MODELVIEW);
00717   glLoadIdentity();
00718 
00719   glDisable (GL_DEPTH_TEST);
00720 
00721   glBegin (GL_QUADS);
00722   glMultiTexCoord2f (GL_TEXTURE0, 0, vp_h);
00723   glMultiTexCoord2f (GL_TEXTURE1, 0, vp_h);
00724   glVertex2i(0, 0);
00725   glMultiTexCoord2f (GL_TEXTURE0, 0, 0);
00726   glMultiTexCoord2f (GL_TEXTURE1, 0, 0);
00727   glVertex2i(0, vp_h);
00728   glMultiTexCoord2f (GL_TEXTURE0, vp_w, 0);
00729   glMultiTexCoord2f (GL_TEXTURE1, vp_w, 0);
00730   glVertex2i(vp_w, vp_h);
00731   glMultiTexCoord2f (GL_TEXTURE0, vp_w, vp_h);
00732   glMultiTexCoord2f (GL_TEXTURE1, vp_w, vp_h);
00733   glVertex2i(vp_w, 0);
00734   glEnd ();
00735 
00736   glEnable (GL_DEPTH_TEST);
00737 
00738   glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, 0);
00739   glDisable (GL_FRAGMENT_PROGRAM_ARB);
00740 
00741   glActiveTexture (GL_TEXTURE1);
00742   glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0);
00743   glDisable (GL_TEXTURE_RECTANGLE_NV);
00744 
00745   glActiveTexture (GL_TEXTURE0);
00746   glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0);
00747   glDisable (GL_TEXTURE_RECTANGLE_NV);
00748 
00749 }
00750 
00751 
00752 //=============================================================================
00753 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .