examples/eVolve/channel.cpp

00001 
00002 /* Copyright (c) 2006-2009, Stefan Eilemann <eile@equalizergraphics.com>
00003                  2007       Maxim Makhinya
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include "channel.h"
00020 
00021 #include "frameData.h"
00022 #include "initData.h"
00023 #include "node.h"
00024 #include "pipe.h"
00025 #include "window.h"
00026 #include "hlp.h"
00027 #include "framesOrderer.h"
00028 #include <eq/client/zoom.h>
00029 
00030 using namespace eq::base;
00031 using namespace std;
00032 
00033 namespace eVolve
00034 {
00035 Channel::Channel( eq::Window* parent )
00036     : eq::Channel( parent )
00037     , _bgColor( eq::Vector3f::ZERO )
00038     , _drawRange( eq::Range::ALL )
00039 {
00040     eq::FrameData* frameData = new eq::FrameData;
00041     frameData->setBuffers( eq::Frame::BUFFER_COLOR );
00042     _frame.setData( frameData );
00043 }
00044 
00045 static void checkError( const std::string& msg ) 
00046 {
00047     const GLenum error = glGetError();
00048     if (error != GL_NO_ERROR)
00049         EQERROR << msg << " GL Error: " << error << endl;
00050 }
00051 
00052 
00053 bool Channel::configInit( const uint32_t initID )
00054 {
00055     if( !eq::Channel::configInit( initID ))
00056         return false;
00057     EQINFO << "Init channel initID " << initID << " ptr " << this << endl;
00058 
00059     // chose projection type
00060     setNearFar( 0.001f, 10.0f );
00061 
00062     if( getenv( "EQ_TAINT_CHANNELS" ))
00063     {
00064         _bgColor = getUniqueColor();
00065         _bgColor /= 255.f;
00066     }
00067 
00068     return true;
00069 }
00070 
00071 void Channel::frameStart( const uint32_t frameID, const uint32_t frameNumber )
00072 {
00073     _drawRange = eq::Range::ALL;
00074     eq::Channel::frameStart( frameID, frameNumber );
00075 }
00076 
00077 void Channel::frameClear( const uint32_t frameID )
00078 {
00079     applyBuffer();
00080     applyViewport();
00081 
00082     if( getRange() == eq::Range::ALL )
00083         glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00084     else
00085         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00086 
00087     glClear( GL_COLOR_BUFFER_BIT );
00088 }
00089 
00090 
00091 static void setLights( eq::Matrix4f& invRotationM )
00092 {
00093     GLfloat lightAmbient[]  = {0.05f, 0.05f, 0.05f, 1.0f};
00094     GLfloat lightDiffuse[]  = {0.9f , 0.9f , 0.9f , 1.0f};
00095     GLfloat lightSpecular[] = {0.8f , 0.8f , 0.8f , 1.0f};
00096     GLfloat lightPosition[] = {1.0f , 1.0f , 1.0f , 0.0f};
00097 
00098     glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
00099     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00100     glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00101 
00102     // rotate light in the opposite direction of the model rotation to keep
00103     // light position constant and avoid recalculating normals in the fragment
00104     // shader
00105     glPushMatrix();
00106     glMultMatrixf( invRotationM.array );
00107     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00108     glPopMatrix();
00109 }
00110 
00111 
00112 void Channel::frameDraw( const uint32_t frameID )
00113 {
00114     // Setup frustum
00115     eq::Channel::frameDraw( frameID );
00116 
00117     const FrameData::Data& frameData = _getFrameData();
00118     eq::Matrix4f         invRotationM;
00119     frameData.rotation.inverse( invRotationM );
00120     setLights( invRotationM );
00121 
00122     glTranslatef(  frameData.translation.x(), frameData.translation.y(), 
00123                    frameData.translation.z() );
00124     glMultMatrixf( frameData.rotation.array );
00125 
00126     Pipe*     pipe     = static_cast<Pipe*>( getPipe( ));
00127     Renderer* renderer = pipe->getRenderer();
00128     EQASSERT( renderer );
00129 
00130     eq::Matrix4f  modelviewM;     // modelview matrix
00131     eq::Matrix3f  modelviewITM;   // modelview inversed transposed matrix
00132     _calcMVandITMV( modelviewM, modelviewITM );
00133 
00134     const eq::Range& range = getRange();
00135     renderer->render( range, modelviewM, modelviewITM, invRotationM );
00136 
00137     checkError( "error during rendering " );
00138 
00139     _drawRange = range;
00140 
00141 #ifndef NDEBUG
00142     outlineViewport();
00143 #endif
00144 }
00145 
00146 const FrameData::Data& Channel::_getFrameData() const
00147 {
00148     const Pipe* pipe = static_cast< const Pipe* >( getPipe( ));
00149     return pipe->getFrameData();
00150 }
00151 
00152 void Channel::applyFrustum() const
00153 {
00154     const FrameData::Data& frameData = _getFrameData();
00155 
00156     if( frameData.ortho )
00157         eq::Channel::applyOrtho();
00158     else
00159         eq::Channel::applyFrustum();
00160 }
00161 
00162 
00163 void Channel::_calcMVandITMV(
00164                             eq::Matrix4f& modelviewM,
00165                             eq::Matrix3f& modelviewITM ) const
00166 {
00167     const FrameData::Data& frameData = _getFrameData();
00168     const Pipe*            pipe      = static_cast< const Pipe* >( getPipe( ));
00169     const Renderer*        renderer  = pipe->getRenderer();
00170 
00171     if( renderer )
00172     {
00173         const VolumeScaling& volScaling = renderer->getVolumeScaling();
00174         
00175         eq::Matrix4f scale( eq::Matrix4f::ZERO );
00176         scale.at(0,0) = volScaling.W;
00177         scale.at(1,1) = volScaling.H;
00178         scale.at(2,2) = volScaling.D;
00179         scale.at(3,3) = 1.f;
00180         
00181         modelviewM = scale * frameData.rotation;
00182     }
00183     modelviewM.set_translation( frameData.translation );
00184 
00185     modelviewM = getHeadTransform() * modelviewM;
00186 
00187     //calculate inverse transposed matrix
00188     eq::Matrix4f modelviewIM;
00189     modelviewM.inverse( modelviewIM );
00190     eq::Matrix3f( modelviewIM ).transpose_to(  modelviewITM  );
00191 }
00192 
00193 
00194 static void _expandPVP( eq::PixelViewport& pvp, 
00195                         const vector< eq::Image* >& images,
00196                         const eq::Vector2i& offset )
00197 {
00198     for( vector< eq::Image* >::const_iterator i = images.begin();
00199          i != images.end(); ++i )
00200     {
00201         const eq::PixelViewport imagePVP = (*i)->getPixelViewport() + offset;
00202         pvp.merge( imagePVP );
00203     }
00204 }
00205 
00206 
00207 void Channel::clearViewport( const eq::PixelViewport &pvp )
00208 {
00209     // clear given area
00210     glScissor(  pvp.x, pvp.y, pvp.w, pvp.h );
00211     glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00212     glClear( GL_COLOR_BUFFER_BIT );
00213 
00214     // restore assembly state
00215     const eq::PixelViewport& windowPVP = getWindow()->getPixelViewport();
00216     glScissor( 0, 0, windowPVP.w, windowPVP.h );
00217 }
00218 
00219 void Channel::_orderFrames( eq::FrameVector& frames )
00220 {
00221     eq::Matrix4f           modelviewM;   // modelview matrix
00222     eq::Matrix3f           modelviewITM; // modelview inversed transposed matrix
00223     const FrameData::Data& frameData = _getFrameData();
00224     const eq::Matrix4f&    rotation  = frameData.rotation;
00225 
00226     if( !frameData.ortho )
00227         _calcMVandITMV( modelviewM, modelviewITM );
00228 
00229     orderFrames( frames, modelviewM, modelviewITM, rotation, frameData.ortho );
00230 }
00231 
00232 
00233 void Channel::frameAssemble( const uint32_t frameID )
00234 {
00235     const bool composeOnly = (_drawRange == eq::Range::ALL);
00236 
00237     _startAssemble();
00238 
00239     const eq::FrameVector& frames = getInputFrames();
00240     eq::PixelViewport  coveredPVP;
00241     eq::FrameVector    dbFrames;
00242     eq::Zoom           zoom( eq::Zoom::NONE );
00243 
00244     // Make sure all frames are ready and gather some information on them
00245     for( eq::FrameVector::const_iterator i = frames.begin();
00246          i != frames.end(); ++i )
00247     {
00248         eq::Frame* frame = *i;
00249         {
00250             eq::ChannelStatistics stat(eq::Statistic::CHANNEL_WAIT_FRAME, this);
00251             frame->waitReady( );
00252         }
00253         const eq::Range& curRange = frame->getRange();
00254         if( curRange == eq::Range::ALL ) // 2D frame, assemble directly
00255             eq::Compositor::assembleFrame( frame, this );
00256         else
00257         {
00258             dbFrames.push_back( frame );
00259             zoom = frame->getZoom();
00260             _expandPVP( coveredPVP, frame->getImages(), frame->getOffset() );
00261         }
00262     }
00263     coveredPVP.intersect( getPixelViewport( ));
00264 
00265     if( dbFrames.empty( ))
00266     {
00267         resetAssemblyState();
00268         return;
00269     }
00270 
00271     //calculate correct frames sequence
00272     if( !composeOnly && coveredPVP.hasArea( ))
00273     {
00274         _frame.clear();
00275         _frame.setRange( _drawRange );
00276         dbFrames.push_back( &_frame );
00277     }
00278 
00279     _orderFrames( dbFrames );
00280 
00281     // check if current frame is in proper position, read back if not
00282     if( !composeOnly )
00283     {
00284         if( _bgColor == eq::Vector3f::ZERO && dbFrames.front() == &_frame )
00285             dbFrames.erase( dbFrames.begin( ));
00286         else if( coveredPVP.hasArea())
00287         {
00288             eq::Window::ObjectManager* glObjects = getObjectManager();
00289 
00290             _frame.setOffset( eq::Vector2i( 0, 0 ));
00291             _frame.setZoom( zoom );
00292             _frame.setPixelViewport( coveredPVP );
00293             _frame.startReadback( glObjects );
00294             clearViewport( coveredPVP );
00295             _frame.syncReadback();
00296 
00297             // offset for assembly
00298             _frame.setOffset( eq::Vector2i( coveredPVP.x, coveredPVP.y ));
00299         }
00300     }
00301 
00302     // blend DB frames in order
00303     eq::Compositor::assembleFramesSorted( dbFrames, this, true /*blendAlpha*/ );
00304     resetAssemblyState();
00305 
00306     // Update range
00307     _drawRange = getRange();
00308 }
00309 
00310 void Channel::_startAssemble()
00311 {
00312     applyBuffer();
00313     applyViewport();
00314     setupAssemblyState();
00315 }   
00316 
00317 void Channel::frameReadback( const uint32_t frameID )
00318 {
00319     // Drop depth buffer flag from all output frames
00320     const eq::FrameVector& frames = getOutputFrames();
00321     for( eq::FrameVector::const_iterator i = frames.begin(); 
00322          i != frames.end(); ++i )
00323     {
00324         (*i)->disableBuffer( eq::Frame::BUFFER_DEPTH );
00325     }
00326 
00327     eq::Channel::frameReadback( frameID );
00328 }
00329 
00330 void Channel::frameViewFinish( const uint32_t frameID )
00331 {
00332     // Draw the overlay logo
00333     const Window*  window      = static_cast<Window*>( getWindow( ));
00334     GLuint         texture;
00335     eq::Vector2i size;
00336 
00337     window->getLogoTexture( texture, size );
00338     if( !texture )
00339         return;
00340     
00341     glMatrixMode( GL_PROJECTION );
00342     glLoadIdentity();
00343     applyScreenFrustum();
00344     glMatrixMode( GL_MODELVIEW );
00345     glLoadIdentity();
00346 
00347     glDisable( GL_DEPTH_TEST );
00348     glDisable( GL_LIGHTING );
00349     glEnable( GL_BLEND );
00350     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00351 
00352     glEnable( GL_TEXTURE_RECTANGLE_ARB );
00353     glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
00354     glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
00355                      GL_LINEAR );
00356     glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, 
00357                      GL_LINEAR );
00358 
00359     glColor3f( 1.0f, 1.0f, 1.0f );
00360     glBegin( GL_TRIANGLE_STRIP ); {
00361         glTexCoord2f( 0.0f, 0.0f );
00362         glVertex3f( 5.0f, 5.0f, 0.0f );
00363 
00364         glTexCoord2f( size.x(), 0.0f );
00365         glVertex3f( size.x() + 5.0f, 5.0f, 0.0f );
00366 
00367         glTexCoord2f( 0.0f, size.y() );
00368         glVertex3f( 5.0f, size.y() + 5.0f, 0.0f );
00369 
00370         glTexCoord2f( size.x(), size.y() );
00371         glVertex3f( size.x() + 5.0f, size.y() + 5.0f, 0.0f );
00372     } glEnd();
00373 
00374     glDisable( GL_TEXTURE_RECTANGLE_ARB );
00375     glDisable( GL_BLEND );
00376 }
00377 
00378 }
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8