/*===========================================================================*\ * * * OpenFlipper * * Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen * * www.openflipper.org * * * *---------------------------------------------------------------------------* * This file is part of OpenFlipper. * * * * OpenFlipper is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenFlipper is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenFlipper. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Author$ * * $Date$ * * * \*===========================================================================*/ //============================================================================= // // CLASS glViewer - IMPLEMENTATION // //============================================================================= //== INCLUDES ================================================================= #include "QtBaseViewer.hh" #include #include #include #include //== NAMESPACES =============================================================== //== IMPLEMENTATION ========================================================== static const char* customAnaglyphProg = { "!!ARBfp1.0" "TEMP left, right, lmul, rmul;" "TEX left, fragment.texcoord[0], texture[0], RECT;" "TEX right, fragment.texcoord[0], texture[1], RECT;" "DP3 lmul.r, left, program.env[0];" "DP3 lmul.g, left, program.env[1];" "DP3 lmul.b, left, program.env[2];" "DP3 rmul.r, right, program.env[3];" "DP3 rmul.g, right, program.env[4];" "DP3 rmul.b, right, program.env[5];" "ADD result.color, lmul, rmul;" "END" }; //----------------------------------------------------------------------------- void glViewer::setStereoMode(bool _b) { stereo_ = _b; if (!stereo_) { makeCurrent(); glDrawBuffer(GL_BACK); } updateProjectionMatrix (); updateGL(); } //----------------------------------------------------------------------------- void glViewer::drawScene_glStereo() { double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange; w = glWidth(); h = glHeight(); a = w / h; radians = fovy_ * 0.5 / 180.0 * M_PI; wd2 = near_ * tan(radians); zerop = near_ + ((far_ - near_) * OpenFlipper::Options::focalDistance ()); ndfl = near_ / zerop ; xrange = a * wd2 * 2 * zerop / near_; l = -a*wd2; r = a*wd2; t = wd2; b = -wd2; double offset = 0.5 * OpenFlipper::Options::eyeDistance () * xrange; double offset2 = offset * ndfl; // left eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l+offset2, r+offset2, b, t, near_, far_); glTranslatef(+offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glstate_->clearBuffers (); glClear(GL_DEPTH_BUFFER_BIT); drawScene_mono(); // right eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l-offset2, r-offset2, b, t, near_, far_); glTranslatef(-offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_RIGHT); glstate_->clearBuffers (); glClear(GL_DEPTH_BUFFER_BIT); drawScene_mono(); glDrawBuffer(GL_BACK); } void glViewer::drawScenePhilipsStereo() { std::cerr << "Rendering into new buffer" << std::endl; QGLFramebufferObject* buffer = new QGLFramebufferObject (glWidth (), glHeight (), QGLFramebufferObject::Depth); buffer->bind(); drawScene_mono(); // buffer->drawTexture(QRectF(0,0,1,1),buffer->texture()); QImage image = buffer->toImage(); image.save("test.jpg"); buffer->release(); // glBindTexture(GL_TEXTURE_2D, buffer->texture()); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // // glEnable(GL_TEXTURE_2D); // glEnable(GL_BLEND); // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glDisable(GL_DEPTH_TEST); // // glColor3f(1.0,1.0,1.0); // // // draw into the GL widget // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glMatrixMode(GL_PROJECTION); // // glPushMatrix(); // // glLoadIdentity(); // glOrtho(-1, 1, -1, 1, 10, 100); // // // glMatrixMode(GL_MODELVIEW); // // glPushMatrix(); // glLoadIdentity(); // // glViewport(0, 0, glWidth(), glHeight()); // // // // glBegin(GL_QUADS); // { // // glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 15.0f); // glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 15.0f); // glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 15.0f); // glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 15.0f); // // } // glEnd(); // // glDisable(GL_TEXTURE_2D); // // // // glPopMatrix(); // // glMatrixMode(GL_PROJECTION); // glPopMatrix(); } //----------------------------------------------------------------------------- void glViewer::drawScene_anaglyphStereo() { double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange; w = glWidth(); h = glHeight(); a = w / h; radians = fovy_ * 0.5 / 180.0 * M_PI; wd2 = near_ * tan(radians); zerop = near_ + ((far_ - near_) * OpenFlipper::Options::focalDistance ()); ndfl = near_ / zerop ; xrange = a * wd2 * 2 * zerop / near_; l = -a*wd2; r = a*wd2; t = wd2; b = -wd2; double offset = 0.5 * OpenFlipper::Options::eyeDistance () * xrange; double offset2 = offset * ndfl; // left eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l+offset2, r+offset2, b, t, near_, far_); glTranslatef(offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glstate_->clearBuffers (); glClear(GL_DEPTH_BUFFER_BIT); // draw red channel for left eye glColorMask(GL_TRUE,GL_FALSE,GL_FALSE,GL_TRUE); drawScene_mono(); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); // right eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l-offset2, r-offset2, b, t, near_, far_); glTranslatef(-offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glClear(GL_DEPTH_BUFFER_BIT); // draw green and blue channel for right eye glColorMask(GL_FALSE,GL_TRUE,GL_TRUE,GL_TRUE); drawScene_mono(); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); } //----------------------------------------------------------------------------- void glViewer::updateCustomAnaglyphStereo() { if (!customAnaglyphSupported_) return; if (!agProgram_) { GLint errorPos; glGenProgramsARB (1, &agProgram_); glGetError (); glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, agProgram_); glProgramStringARB (GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen (customAnaglyphProg), customAnaglyphProg); glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); if (glGetError () != GL_NO_ERROR || errorPos != -1) { printf("Error loading program %d %s\n",errorPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB)); glDeleteProgramsARB (1, &agProgram_); customAnaglyphSupported_ = false; return; } } if (!agTexture_[0]) glGenTextures (2, agTexture_); if (!agTexture_[0]) { finiCustomAnaglyphStereo (); customAnaglyphSupported_ = false; return; } if (glstate_->viewport_width () != agTexWidth_ || glstate_->viewport_height () != agTexHeight_) { glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]); glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width (), glstate_->viewport_height (), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]); glTexImage2D (GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, glstate_->viewport_width (), glstate_->viewport_height (), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0); agTexWidth_ = glstate_->viewport_width (); agTexHeight_ = glstate_->viewport_height (); } } //----------------------------------------------------------------------------- void glViewer::finiCustomAnaglyphStereo() { if (!customAnaglyphSupported_) return; if (agProgram_) glDeleteProgramsARB (1, &agProgram_); if (agTexture_[0]) glDeleteTextures (2, agTexture_); } //----------------------------------------------------------------------------- void glViewer::drawScene_customAnaglyphStereo() { updateCustomAnaglyphStereo (); if (!customAnaglyphSupported_) return; double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange; w = glWidth(); h = glHeight(); a = w / h; radians = fovy_ * 0.5 / 180.0 * M_PI; wd2 = near_ * tan(radians); zerop = near_ + ((far_ - near_) * OpenFlipper::Options::focalDistance ()); ndfl = near_ / zerop ; xrange = a * wd2 * 2 * zerop / near_; l = -a*wd2; r = a*wd2; t = wd2; b = -wd2; double offset = 0.5 * OpenFlipper::Options::eyeDistance () * xrange; double offset2 = offset * ndfl; int vp_l, vp_b, vp_w, vp_h; glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h); std::vector le = OpenFlipper::Options::anaglyphLeftEyeColorMatrix(); std::vector re = OpenFlipper::Options::anaglyphRightEyeColorMatrix(); // left eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l+offset2, r+offset2, b, t, near_, far_); glTranslatef(offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glstate_->clearBuffers (); glClear(GL_DEPTH_BUFFER_BIT); drawScene_mono(); glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]); glCopyTexSubImage2D (GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, vp_l, vp_b, vp_w, vp_h); glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0); // right eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(l-offset2, r-offset2, b, t, near_, far_); glTranslatef(-offset, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glstate_->clearBuffers (); glClear(GL_DEPTH_BUFFER_BIT); drawScene_mono(); glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]); glCopyTexSubImage2D (GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, vp_l, vp_b, vp_w, vp_h); glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[0]); glEnable (GL_TEXTURE_RECTANGLE_NV); glActiveTexture (GL_TEXTURE1); glBindTexture (GL_TEXTURE_RECTANGLE_NV, agTexture_[1]); glEnable (GL_TEXTURE_RECTANGLE_NV); glEnable (GL_FRAGMENT_PROGRAM_ARB); glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, agProgram_); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, le[0], le[3], le[6], 0.0); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, le[1], le[4], le[7], 0.0); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 2, le[2], le[5], le[8], 0.0); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 3, re[0], re[3], re[6], 0.0); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 4, re[1], re[4], re[7], 0.0); glProgramEnvParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 5, re[2], re[5], re[8], 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, vp_w, vp_h, 0, 0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable (GL_DEPTH_TEST); glBegin (GL_QUADS); glMultiTexCoord2f (GL_TEXTURE0, 0, vp_h); glMultiTexCoord2f (GL_TEXTURE1, 0, vp_h); glVertex2i(0, 0); glMultiTexCoord2f (GL_TEXTURE0, 0, 0); glMultiTexCoord2f (GL_TEXTURE1, 0, 0); glVertex2i(0, vp_h); glMultiTexCoord2f (GL_TEXTURE0, vp_w, 0); glMultiTexCoord2f (GL_TEXTURE1, vp_w, 0); glVertex2i(vp_w, vp_h); glMultiTexCoord2f (GL_TEXTURE0, vp_w, vp_h); glMultiTexCoord2f (GL_TEXTURE1, vp_w, vp_h); glVertex2i(vp_w, 0); glEnd (); glEnable (GL_DEPTH_TEST); glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB, 0); glDisable (GL_FRAGMENT_PROGRAM_ARB); glActiveTexture (GL_TEXTURE1); glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0); glDisable (GL_TEXTURE_RECTANGLE_NV); glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_RECTANGLE_NV, 0); glDisable (GL_TEXTURE_RECTANGLE_NV); } //============================================================================= //=============================================================================