/*===========================================================================*\
* *
* 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
#include
#include
#include "crc32.hh"
//== NAMESPACES ===============================================================
//== IMPLEMENTATION ==========================================================
#include
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()
{
// ======================================================================================================
// creating a color texture
// ======================================================================================================
ACG::Texture2D colorTexture;
colorTexture.enable();
colorTexture.bind();
GLenum texTarget = GL_TEXTURE_2D;
GLenum texInternalFormat = GL_RGBA;
GLenum texFormat = GL_RGBA;
GLenum texType = GL_UNSIGNED_BYTE;
GLenum texFilterMode = GL_NEAREST;
glTexImage2D(texTarget, 0, texInternalFormat, glWidth(), glHeight(), 0, texFormat, texType, NULL);
glTexParameterf(texTarget, GL_TEXTURE_MIN_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_MAG_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
// ======================================================================================================
// creating an 24-bit depth + 8-bit stencil texture
// ======================================================================================================
ACG::Texture2D depthStencilTexture;
depthStencilTexture.enable();
depthStencilTexture.bind();
texTarget = GL_TEXTURE_2D;
texInternalFormat = GL_DEPTH24_STENCIL8_EXT;
texFormat = GL_DEPTH_STENCIL_EXT;
texType = GL_UNSIGNED_INT_24_8_EXT;
texFilterMode = GL_NEAREST;
glTexImage2D(texTarget, 0, texInternalFormat, glWidth(), glHeight(), 0, texFormat, texType, NULL);
glTexParameterf(texTarget, GL_TEXTURE_MIN_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_MAG_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
// ======================================================================================================
// creating the framebuffer object
// ======================================================================================================
GLuint frameBuffer_id;
glGenFramebuffersEXT(1, &frameBuffer_id);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer_id);
// ======================================================================================================
// connect a color texture
// ======================================================================================================
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTexture.id(), 0);
// ======================================================================================================
// connect a depth stencil texture
// ======================================================================================================
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texTarget , depthStencilTexture.id(), 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, texTarget , depthStencilTexture.id(), 0);
// ======================================================================================================
// Render the scene
// ======================================================================================================
drawScene_mono();
// ======================================================================================================
// Disable textures
// ======================================================================================================
depthStencilTexture.disable();
colorTexture.disable();
// ======================================================================================================
// Disable and discard the framebuffer
// ======================================================================================================
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &frameBuffer_id);
// ======================================================================================================
// Setup the shaders used to render color and depth info next to each other
// ======================================================================================================
GLSL::PtrVertexShader vertexShader;
GLSL::PtrFragmentShader fragmentShader;
GLSL::PtrProgram program;
QString vshaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "Philips/Vertex.glsl";
QString fshaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + "Philips/Fragment.glsl";
////
vertexShader = GLSL::loadVertexShader( vshaderFile.toStdString().c_str() );
fragmentShader = GLSL::loadFragmentShader( fshaderFile.toStdString().c_str() );
program = GLSL::PtrProgram(new GLSL::Program());
if ( (vertexShader == 0) ||
(fragmentShader == 0) ||
(program == 0) ) {
std::cerr << "Unable to load shaders for philips display rendering!";
return;
}
program->attach(vertexShader);
program->attach(fragmentShader);
program->link();
program->use();
// ======================================================================================================
// Bind textures to different texture units and tell shader where to find them
// ======================================================================================================
glActiveTextureARB(GL_TEXTURE0_ARB);
colorTexture.bind();
glActiveTextureARB(GL_TEXTURE1_ARB);
depthStencilTexture.bind();
program->setUniform("ColorTexture",0);
program->setUniform("DepthStencil",1);
// ======================================================================================================
// Render plain textured
// ======================================================================================================
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_DEPTH_TEST);
// ======================================================================================================
// Setup orthogonal projection
// ======================================================================================================
glstate_->push_projection_matrix();
glstate_->push_modelview_matrix();
glstate_->reset_projection();
glstate_->reset_modelview();
glstate_->ortho(0, glWidth(), 0, glHeight(), 0, 1);
// ======================================================================================================
// Bind textures to different texture units and tell shader where to find them
// ======================================================================================================
glColor3f(1.0,1.0,1.0);
// ======================================================================================================
// Clear buffers
// ======================================================================================================
glClearColor(.0, .0, .0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// ======================================================================================================
// Render a simple quad (rest is done by shader)
// ======================================================================================================
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex2i( 0, glHeight());
glTexCoord2f(1.0f, 1.0f); glVertex2i( glWidth(), glHeight());
glTexCoord2f(1.0f, 0.0f); glVertex2i( glWidth(), 0);
glTexCoord2f(0.0f, 0.0f); glVertex2i( 0, 0);
glEnd();
program->disable();
glBindTexture(GL_TEXTURE_2D, 0);
// ======================================================================================================
// Cleanup (color and depth textures)
// ======================================================================================================
depthStencilTexture.del();
colorTexture.del();
// ======================================================================================================
// Compute the header required for the display
// ======================================================================================================
uchar *header = new uchar[ 6 ];
header[0] = 241; // Header_ID1 = 11110001
header[1] = 3; // Hdr_Content_type (Game) = 00000011 (Gaming Mode)
header[2] = 64; // Hdr_Factor
header[3] = 128; // Hdr_Offset_CC
header[4] = 0; // Hdr_Factor_select(1) + Hdr_Offset_select(1) + reserved(6)
header[5] = 0; // Reserved
//unsigned long has 32bit = 4Byte
unsigned long checksum = CalcCRC32(&header[0], 6);
std::vector< uchar > bitVector;
// For all bytes of the header
for (int i = 0; i < 6; i++) {
// for each bit of a headers byte
for ( int j = 7 ; j >= 0 ; --j ) {
bitVector.push_back(0);
bitVector.push_back(0);
// If bit is set, the full component will be set to one otherwise zero
if ( header[i] & (1 << j ) ) {
bitVector.push_back(255);
} else {
bitVector.push_back(0);
}
bitVector.push_back(0);
bitVector.push_back(0);
bitVector.push_back(0);
}
}
// Append checksum to header.
for (int i=31; i >= 0; i--) {
bitVector.push_back(0);
bitVector.push_back(0);
if ( checksum & (1 << i ) )
bitVector.push_back( 255 );
else
bitVector.push_back( 0 );
bitVector.push_back(0);
bitVector.push_back(0);
bitVector.push_back(0);
}
//render the header
glRasterPos2i (0,glHeight()-1);
glDrawPixels(bitVector.size()/3, 1,GL_RGB ,GL_UNSIGNED_BYTE , &bitVector[0]);
// ======================================================================================================
// Reset projection and modelview
// ======================================================================================================
glstate_->pop_projection_matrix();
glstate_->pop_modelview_matrix();
}
//-----------------------------------------------------------------------------
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);
}
//=============================================================================
//=============================================================================