Equalizer  1.4.1
eqPly/channel.cpp
00001 
00002 /* Copyright (c) 2006-2012, Stefan Eilemann <eile@equalizergraphics.com>
00003  *               2010, Cedric Stalder <cedric.stalder@gmail.com>
00004  *               2007, Tobias Wolf <twolf@access.unizh.ch>
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright notice, this
00010  *   list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright notice,
00012  *   this list of conditions and the following disclaimer in the documentation
00013  *   and/or other materials provided with the distribution.
00014  * - Neither the name of Eyescale Software GmbH nor the names of its
00015  *   contributors may be used to endorse or promote products derived from this
00016  *   software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include "channel.h"
00032 
00033 #include "initData.h"
00034 #include "config.h"
00035 #include "configEvent.h"
00036 #include "pipe.h"
00037 #include "view.h"
00038 #include "window.h"
00039 #include "vertexBufferState.h"
00040 
00041 // light parameters
00042 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
00043 static GLfloat lightAmbient[]  = {0.1f, 0.1f, 0.1f, 1.0f};
00044 static GLfloat lightDiffuse[]  = {0.8f, 0.8f, 0.8f, 1.0f};
00045 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
00046 
00047 // material properties
00048 static GLfloat materialAmbient[]  = {0.2f, 0.2f, 0.2f, 1.0f};
00049 static GLfloat materialDiffuse[]  = {0.8f, 0.8f, 0.8f, 1.0f};
00050 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
00051 static GLint  materialShininess   = 64;
00052 
00053 #ifndef M_SQRT3_2
00054 #  define M_SQRT3_2  0.86603f  /* sqrt(3)/2 */
00055 #endif
00056 
00057 namespace eqPly
00058 {
00059 
00060 Channel::Channel( eq::Window* parent )
00061         : eq::Channel( parent )
00062         , _model(0)
00063         , _modelID( lunchbox::UUID::ZERO )
00064         , _frameRestart( 0 )
00065 {
00066 }
00067 
00068 bool Channel::configInit( const eq::uint128_t& initID )
00069 {
00070     if( !eq::Channel::configInit( initID ))
00071         return false;
00072 
00073     setNearFar( 0.1f, 10.0f );
00074     _model = 0;
00075     _modelID = lunchbox::UUID::ZERO;
00076     return true;
00077 }
00078 
00079 bool Channel::configExit()
00080 {
00081     for( size_t i = 0; i < eq::NUM_EYES; ++i )
00082     {
00083         delete _accum[ i ].buffer;
00084         _accum[ i ].buffer = 0;
00085     }
00086 
00087     return eq::Channel::configExit();
00088 }
00089 
00090 void Channel::frameClear( const eq::uint128_t& frameID )
00091 {
00092     if( stopRendering( ))
00093         return;
00094 
00095     _initJitter();
00096     resetRegions();
00097 
00098     const FrameData& frameData = _getFrameData();
00099     const int32_t eyeIndex = lunchbox::getIndexOfLastBit( getEye() );
00100     if( _isDone() && !_accum[ eyeIndex ].transfer )
00101         return;
00102 
00103     applyBuffer();
00104     applyViewport();
00105 
00106     const eq::View* view = getView();
00107     if( view && frameData.getCurrentViewID() == view->getID( ))
00108         glClearColor( 1.f, 1.f, 1.f, 1.f );
00109 #ifndef NDEBUG
00110     else if( getenv( "EQ_TAINT_CHANNELS" ))
00111     {
00112         const eq::Vector3ub color = getUniqueColor();
00113         glClearColor( color.r()/255.0f,
00114                       color.g()/255.0f,
00115                       color.b()/255.0f, 1.0f );
00116     }
00117 #endif // NDEBUG
00118     else
00119         glClearColor( 0.f, 0.f, 0.f, 1.0f );
00120 
00121     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00122 }
00123 
00124 void Channel::frameDraw( const eq::uint128_t& frameID )
00125 {
00126     if( stopRendering( ))
00127         return;
00128 
00129     _initJitter();
00130     if( _isDone( ))
00131         return;
00132 
00133     Window* window = static_cast< Window* >( getWindow( ));
00134     VertexBufferState& state = window->getState();
00135     const Model* oldModel = _model;
00136     const Model* model = _getModel();
00137 
00138     if( oldModel != model )
00139         state.setFrustumCulling( false ); // create all display lists/VBOs
00140 
00141     if( model )
00142         _updateNearFar( model->getBoundingSphere( ));
00143 
00144     eq::Channel::frameDraw( frameID ); // Setup OpenGL state
00145 
00146     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00147     glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
00148     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00149     glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00150 
00151     glMaterialfv( GL_FRONT, GL_AMBIENT,   materialAmbient );
00152     glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
00153     glMaterialfv( GL_FRONT, GL_SPECULAR,  materialSpecular );
00154     glMateriali(  GL_FRONT, GL_SHININESS, materialShininess );
00155 
00156     const FrameData& frameData = _getFrameData();
00157     glPolygonMode( GL_FRONT_AND_BACK, 
00158                    frameData.useWireframe() ? GL_LINE : GL_FILL );
00159 
00160     const eq::Vector3f& position = frameData.getCameraPosition();
00161 
00162     glMultMatrixf( frameData.getCameraRotation().array );
00163     glTranslatef( position.x(), position.y(), position.z() );
00164     glMultMatrixf( frameData.getModelRotation().array );
00165 
00166     if( frameData.getColorMode() == COLOR_DEMO )
00167     {
00168         const eq::Vector3ub color = getUniqueColor();
00169         glColor3ub( color.r(), color.g(), color.b() );
00170     }
00171     else
00172         glColor3f( .75f, .75f, .75f );
00173 
00174     if( model )
00175         _drawModel( model );
00176     else
00177     {
00178         glNormal3f( 0.f, -1.f, 0.f );
00179         glBegin( GL_TRIANGLE_STRIP );
00180             glVertex3f(  .25f, 0.f,  .25f );
00181             glVertex3f( -.25f, 0.f,  .25f );
00182             glVertex3f(  .25f, 0.f, -.25f );
00183             glVertex3f( -.25f, 0.f, -.25f );
00184         glEnd();
00185     }
00186 
00187     state.setFrustumCulling( true );
00188     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00189     accum.stepsDone = LB_MAX( accum.stepsDone, 
00190                               getSubPixel().size * getPeriod( ));
00191     accum.transfer = true;
00192 }
00193 
00194 void Channel::frameAssemble( const eq::uint128_t& frameID )
00195 {
00196     if( stopRendering( ))
00197         return;
00198 
00199     if( _isDone( ))
00200         return;
00201 
00202     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00203 
00204     if( getPixelViewport() != _currentPVP )
00205     {
00206         accum.transfer = true;
00207 
00208         if( accum.buffer && !accum.buffer->usesFBO( ))
00209         {
00210             LBWARN << "Current viewport different from view viewport, "
00211                    << "idle anti-aliasing not implemented." << std::endl;
00212             accum.step = 0;
00213         }
00214 
00215         eq::Channel::frameAssemble( frameID );
00216         return;
00217     }
00218     // else
00219     
00220     accum.transfer = true;
00221     const eq::Frames& frames = getInputFrames();
00222 
00223     for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i )
00224     {
00225         eq::Frame* frame = *i;
00226         const eq::SubPixel& curSubPixel = frame->getSubPixel();
00227 
00228         if( curSubPixel != eq::SubPixel::ALL )
00229             accum.transfer = false;
00230 
00231         accum.stepsDone = LB_MAX( accum.stepsDone, frame->getSubPixel().size * 
00232                                                    frame->getPeriod( ));
00233     }
00234 
00235     applyBuffer();
00236     applyViewport();
00237     setupAssemblyState();
00238 
00239     try
00240     {
00241         eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer );
00242     }
00243     catch( const co::Exception& e )
00244     {
00245         LBWARN << e.what() << std::endl;
00246     }
00247 
00248     resetAssemblyState();
00249 }
00250 
00251 void Channel::frameReadback( const eq::uint128_t& frameID )
00252 {
00253     if( stopRendering() || _isDone( ))
00254         return;
00255 
00256     const FrameData& frameData = _getFrameData();
00257     const eq::Frames& frames = getOutputFrames();
00258     for( eq::FramesCIter i = frames.begin(); i != frames.end(); ++i )
00259     {
00260         eq::Frame* frame = *i;
00261         // OPT: Drop alpha channel from all frames during network transport
00262         frame->setAlphaUsage( false );
00263         
00264         if( frameData.isIdle( ))
00265             frame->setQuality( eq::Frame::BUFFER_COLOR, 1.f );
00266         else
00267             frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality());
00268 
00269         if( frameData.useCompression( ))
00270             frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_AUTO );
00271         else
00272             frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_NONE );
00273     }
00274 
00275     eq::Channel::frameReadback( frameID );
00276 }
00277 
00278 void Channel::frameStart( const eq::uint128_t& frameID,
00279                           const uint32_t frameNumber )
00280 {
00281     if( stopRendering( ))
00282         return;
00283 
00284     for( size_t i = 0; i < eq::NUM_EYES; ++i )
00285         _accum[ i ].stepsDone = 0;
00286 
00287     eq::Channel::frameStart( frameID, frameNumber );
00288 }
00289 
00290 void Channel::frameViewStart( const eq::uint128_t& frameID )
00291 {
00292     if( stopRendering( ))
00293         return;
00294 
00295     _currentPVP = getPixelViewport();
00296     _initJitter();
00297     eq::Channel::frameViewStart( frameID );
00298 }
00299 
00300 void Channel::frameFinish( const eq::uint128_t& frameID,
00301                            const uint32_t frameNumber )
00302 {
00303     if( stopRendering( ))
00304         return;
00305 
00306     for( size_t i = 0; i < eq::NUM_EYES; ++i )
00307     {
00308         Accum& accum = _accum[ i ];
00309         if( accum.step > 0 )
00310         {
00311             if( int32_t( accum.stepsDone ) > accum.step )
00312                 accum.step = 0;
00313             else
00314                 accum.step -= accum.stepsDone;
00315         }
00316     }
00317 
00318     eq::Channel::frameFinish( frameID, frameNumber );
00319 }
00320 
00321 void Channel::frameViewFinish( const eq::uint128_t& frameID )
00322 {
00323     if( stopRendering( ))
00324         return;
00325 
00326     applyBuffer();
00327 
00328     const FrameData& frameData = _getFrameData();
00329     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00330 
00331     if( accum.buffer )
00332     {
00333         const eq::PixelViewport& pvp = getPixelViewport();
00334         const bool isResized = accum.buffer->resize( pvp.w, pvp.h );
00335 
00336         if( isResized )
00337         {
00338             const View* view = static_cast< const View* >( getView( ));
00339             accum.buffer->clear();
00340             accum.step = view->getIdleSteps();
00341             accum.stepsDone = 0;
00342         }
00343         else if( frameData.isIdle( ))
00344         {
00345             setupAssemblyState();
00346 
00347             if( !_isDone() && accum.transfer )
00348                 accum.buffer->accum();
00349             accum.buffer->display();
00350 
00351             resetAssemblyState();
00352         }
00353     }
00354 
00355     applyViewport();
00356     _drawOverlay();
00357     _drawHelp();
00358 
00359     if( frameData.useStatistics())
00360         drawStatistics();
00361 
00362     ConfigEvent event;
00363     event.data.originator = getID();
00364     event.data.type = ConfigEvent::IDLE_AA_LEFT;
00365 
00366     if( frameData.isIdle( ))
00367     {
00368         event.steps = 0;
00369         for( size_t i = 0; i < eq::NUM_EYES; ++i )
00370             event.steps = LB_MAX( event.steps, _accum[i].step );
00371     }
00372     else
00373     {
00374         const View* view = static_cast< const View* >( getView( ));
00375         event.steps = view ? view->getIdleSteps() : 0;
00376     }
00377 
00378     // if _jitterStep == 0 and no user redraw event happened, the app will exit
00379     // FSAA idle mode and block on the next redraw event.
00380     eq::Config* config = getConfig();
00381     config->sendEvent( event );
00382 }
00383 
00384 bool Channel::useOrtho() const
00385 {
00386     const FrameData& frameData = _getFrameData();
00387     return frameData.useOrtho();
00388 }
00389 
00390 const FrameData& Channel::_getFrameData() const
00391 {
00392     const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
00393     return pipe->getFrameData();
00394 }
00395 
00396 bool Channel::_isDone() const
00397 {
00398     const FrameData& frameData = _getFrameData();
00399     if( !frameData.isIdle( ))
00400         return false;
00401 
00402     const eq::SubPixel& subpixel = getSubPixel();
00403     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00404     return int32_t( subpixel.index ) >= accum.step;
00405 }
00406 
00407 void Channel::_initJitter()
00408 {
00409     if( !_initAccum( ))
00410         return;
00411 
00412     const FrameData& frameData = _getFrameData();
00413     if( frameData.isIdle( ))
00414         return;
00415 
00416     const View* view = static_cast< const View* >( getView( ));
00417     if( !view )
00418         return;
00419 
00420     const int32_t idleSteps = view->getIdleSteps();
00421     if( idleSteps == 0 )
00422         return;
00423 
00424     // ready for the next FSAA
00425     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00426     if( accum.buffer )
00427         accum.buffer->clear();
00428     accum.step = idleSteps;
00429 }
00430 
00431 bool Channel::_initAccum()
00432 {
00433     View* view = static_cast< View* >( getNativeView( ));
00434     if( !view ) // Only alloc accum for dest
00435         return true;
00436 
00437     const eq::Eye eye = getEye();
00438     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( eye ) ];
00439 
00440     if( accum.buffer ) // already done
00441         return true;
00442 
00443     if( accum.step == -1 ) // accum init failed last time
00444         return false;
00445 
00446     // Check unsupported cases
00447     if( !eq::util::Accum::usesFBO( glewGetContext( )))
00448     {
00449         for( size_t i = 0; i < eq::NUM_EYES; ++i )
00450         {
00451             if( _accum[ i ].buffer )
00452             {
00453                 LBWARN << "glAccum-based accumulation does not support "
00454                        << "stereo, disabling idle anti-aliasing."
00455                        << std::endl;
00456                 for( size_t j = 0; j < eq::NUM_EYES; ++j )
00457                 {
00458                     delete _accum[ j ].buffer;
00459                     _accum[ j ].buffer = 0;
00460                     _accum[ j ].step = -1;
00461                 }
00462 
00463                 view->setIdleSteps( 0 );
00464                 return false;
00465             }
00466         }
00467     }
00468 
00469     // set up accumulation buffer
00470     accum.buffer = new eq::util::Accum( glewGetContext( ));
00471     const eq::PixelViewport& pvp = getPixelViewport();
00472     LBASSERT( pvp.isValid( ));
00473 
00474     if( !accum.buffer->init( pvp, getWindow()->getColorFormat( )) ||
00475         accum.buffer->getMaxSteps() < 256 )
00476     {
00477         LBWARN <<"Accumulation buffer initialization failed, "
00478                << "idle AA not available." << std::endl;
00479         delete accum.buffer;
00480         accum.buffer = 0;
00481         accum.step = -1;
00482         return false;
00483     }
00484 
00485     // else
00486     LBVERB << "Initialized "
00487            << (accum.buffer->usesFBO() ? "FBO accum" : "glAccum")
00488            << " buffer for " << getName() << " " << getEye() 
00489            << std::endl;
00490 
00491     view->setIdleSteps( accum.buffer ? 256 : 0 );
00492     return true;
00493 }
00494 
00495 bool Channel::stopRendering() const
00496 { 
00497     return getPipe()->getCurrentFrame() < _frameRestart; 
00498 }
00499 
00500 eq::Vector2f Channel::getJitter() const
00501 {
00502     const FrameData& frameData = _getFrameData();
00503     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00504 
00505     if( !frameData.isIdle() || accum.step <= 0 )
00506         return eq::Channel::getJitter();
00507 
00508     const View* view = static_cast< const View* >( getView( ));
00509     if( !view || view->getIdleSteps() != 256 )
00510         return eq::Vector2f::ZERO;
00511 
00512     const eq::Vector2i jitterStep = _getJitterStep();
00513     if( jitterStep == eq::Vector2i::ZERO )
00514         return eq::Vector2f::ZERO;
00515 
00516     const eq::PixelViewport& pvp = getPixelViewport();
00517     const float pvp_w = float( pvp.w );
00518     const float pvp_h = float( pvp.h );
00519     const float frustum_w = float(( getFrustum().get_width( )));
00520     const float frustum_h = float(( getFrustum().get_height( )));
00521 
00522     const float pixel_w = frustum_w / pvp_w;
00523     const float pixel_h = frustum_h / pvp_h;
00524 
00525     const float sampleSize = 16.f; // sqrt( 256 )
00526     const float subpixel_w = pixel_w / sampleSize;
00527     const float subpixel_h = pixel_h / sampleSize;
00528 
00529     // Sample value randomly computed within the subpixel
00530     lunchbox::RNG rng;
00531     const eq::Pixel& pixel = getPixel();
00532 
00533     const float i = ( rng.get< float >() * subpixel_w +
00534                       float( jitterStep.x( )) * subpixel_w ) / float( pixel.w );
00535     const float j = ( rng.get< float >() * subpixel_h +
00536                       float( jitterStep.y( )) * subpixel_h ) / float( pixel.h );
00537 
00538     return eq::Vector2f( i, j );
00539 }
00540 
00541 static const uint32_t _primes[100] = {
00542     739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
00543     839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
00544     947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
00545     1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109,
00546     1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
00547     1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
00548     1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
00549     1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 };
00550 
00551 eq::Vector2i Channel::_getJitterStep() const
00552 {
00553     const eq::SubPixel& subPixel = getSubPixel();
00554     const uint32_t channelID = subPixel.index;
00555     const View* view = static_cast< const View* >( getView( ));
00556     if( !view )
00557         return eq::Vector2i::ZERO;
00558 
00559     const uint32_t totalSteps = uint32_t( view->getIdleSteps( ));
00560     if( totalSteps != 256 )
00561         return eq::Vector2i::ZERO;
00562 
00563     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00564     const uint32_t subset = totalSteps / getSubPixel().size;
00565     const uint32_t index = ( accum.step * _primes[ channelID % 100 ] )%subset +
00566                            ( channelID * subset );
00567     const uint32_t sampleSize = 16;
00568     const int dx = index % sampleSize;
00569     const int dy = index / sampleSize;
00570 
00571     return eq::Vector2i( dx, dy );
00572 }
00573 
00574 const Model* Channel::_getModel()
00575 {
00576     Config* config = static_cast< Config* >( getConfig( ));
00577     const View* view = static_cast< const View* >( getView( ));
00578     const FrameData& frameData = _getFrameData();
00579     LBASSERT( !view || dynamic_cast< const View* >( getView( )));
00580 
00581     eq::uint128_t id = view ? view->getModelID() : frameData.getModelID();
00582     if( id == lunchbox::UUID::ZERO )
00583         id = frameData.getModelID();
00584     if( id != _modelID )
00585     {
00586         _model = config->getModel( id );
00587         _modelID = id;
00588     }
00589 
00590     return _model;
00591 }
00592 
00593 void Channel::_drawModel( const Model* scene )
00594 {
00595     Window* window = static_cast< Window* >( getWindow( ));
00596     VertexBufferState& state = window->getState();
00597     const FrameData& frameData = _getFrameData();
00598 
00599     if( frameData.getColorMode() == COLOR_MODEL && scene->hasColors( ))
00600         state.setColors( true );
00601     else
00602         state.setColors( false );
00603     state.setChannel( this );
00604 
00605     // Compute cull matrix
00606     const eq::Matrix4f& rotation = frameData.getCameraRotation();
00607     const eq::Matrix4f& modelRotation = frameData.getModelRotation();
00608     eq::Matrix4f position = eq::Matrix4f::IDENTITY;
00609     position.set_translation( frameData.getCameraPosition());
00610 
00611     const eq::Frustumf& frustum = getFrustum();
00612     const eq::Matrix4f projection = useOrtho() ? frustum.compute_ortho_matrix():
00613                                                  frustum.compute_matrix();
00614     const eq::Matrix4f& view = getHeadTransform();
00615     const eq::Matrix4f model = rotation * position * modelRotation;
00616 
00617     state.setProjectionModelViewMatrix( projection * view * model );
00618     state.setRange( &getRange().start);
00619 
00620     const eq::Pipe* pipe = getPipe();
00621     const GLuint program = state.getProgram( pipe );
00622     if( program != VertexBufferState::INVALID )
00623         glUseProgram( program );
00624     
00625     scene->cullDraw( state );
00626 
00627     state.setChannel( 0 );
00628     if( program != VertexBufferState::INVALID )
00629         glUseProgram( 0 );
00630 
00631     const InitData& initData =
00632         static_cast<Config*>( getConfig( ))->getInitData();
00633     if( !initData.useROI( ))
00634     {
00635         declareRegion( getPixelViewport( ));
00636         return;
00637     }
00638 
00639 #ifndef NDEBUG // region border
00640     const eq::PixelViewport& pvp = getPixelViewport();
00641     const eq::PixelViewport& region = getRegion();
00642 
00643     glMatrixMode( GL_PROJECTION );
00644     glLoadIdentity();
00645     glOrtho( 0.f, pvp.w, 0.f, pvp.h, -1.f, 1.f );
00646     glMatrixMode( GL_MODELVIEW );
00647     glLoadIdentity();
00648 
00649     const eq::View* currentView = getView();
00650     if( frameData.getColorMode() == COLOR_DEMO )
00651     {
00652         const eq::Vector3ub color = getUniqueColor();
00653         glColor3ub( color.r(), color.g(), color.b() );
00654     }
00655     else if( currentView && 
00656              frameData.getCurrentViewID() == currentView->getID( ))
00657     {
00658         glColor3f( 0.f, 0.f, 0.f );
00659     }
00660     else
00661         glColor3f( 1.f, 1.f, 1.f );
00662     glNormal3f( 0.f, 0.f, 1.f );
00663 
00664     const eq::Vector4f rect( float( region.x ) + .5f, float( region.y ) + .5f,
00665                              float( region.getXEnd( )) - .5f,
00666                              float( region.getYEnd( )) - .5f );
00667     glBegin( GL_LINE_LOOP ); {
00668         glVertex3f( rect[0], rect[1], -.99f );
00669         glVertex3f( rect[2], rect[1], -.99f );
00670         glVertex3f( rect[2], rect[3], -.99f );
00671         glVertex3f( rect[0], rect[3], -.99f );
00672     } glEnd();
00673 #endif
00674 }
00675 
00676 void Channel::_drawOverlay()
00677 {
00678     // Draw the overlay logo
00679     const Window* window = static_cast<Window*>( getWindow( ));
00680     const eq::util::Texture* texture = window->getLogoTexture();
00681     if( !texture )
00682         return;
00683 
00684     glMatrixMode( GL_PROJECTION );
00685     glLoadIdentity();
00686     applyScreenFrustum();
00687     glMatrixMode( GL_MODELVIEW );
00688     glLoadIdentity();
00689 
00690     glDisable( GL_DEPTH_TEST );
00691     glDisable( GL_LIGHTING );
00692     glColor3f( 1.0f, 1.0f, 1.0f );
00693     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00694 
00695     // logo
00696     glEnable( GL_BLEND );
00697     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00698     const GLenum target = texture->getTarget();
00699     glEnable( target );
00700     texture->bind();
00701     glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00702     glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00703     
00704     const float tWidth = float( texture->getWidth( ) );
00705     const float tHeight = float( texture->getHeight( ) );
00706 
00707     const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
00708     const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
00709 
00710     glBegin( GL_QUADS ); {
00711         glTexCoord2f( 0, 0 );
00712         glVertex3f( 5.0f, 5.0f, 0.0f );
00713 
00714         glTexCoord2f( width, 0 );
00715         glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
00716 
00717         glTexCoord2f( width, height );
00718         glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
00719 
00720         glTexCoord2f( 0, height );
00721         glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
00722 
00723     } glEnd();
00724 
00725     glDisable( target );
00726     glDisable( GL_BLEND );
00727     glEnable( GL_LIGHTING );
00728     glEnable( GL_DEPTH_TEST );
00729 }
00730 
00731 void Channel::_drawHelp()
00732 {
00733     const FrameData& frameData = _getFrameData();
00734     std::string message = frameData.getMessage();
00735 
00736     if( !frameData.showHelp() && message.empty( ))
00737         return;
00738 
00739     applyBuffer();
00740     applyViewport();
00741     setupAssemblyState();
00742 
00743     glLogicOp( GL_XOR );
00744     glEnable( GL_COLOR_LOGIC_OP );
00745     glDisable( GL_LIGHTING );
00746     glDisable( GL_DEPTH_TEST );
00747 
00748     glColor3f( 1.f, 1.f, 1.f );
00749 
00750     const eq::PixelViewport& pvp = getPixelViewport();
00751     const eq::Viewport& vp = getViewport();
00752     const float height = pvp.h / vp.h;
00753 
00754     if( !message.empty( ))
00755     {
00756         const eq::Window::Font* font = getWindow()->getMediumFont();
00757 
00758         const float width = pvp.w / vp.w;
00759         const float xOffset = vp.x * width;
00760 
00761         const float yOffset = vp.y * height;
00762         const float yPos = 0.618f * height;
00763         float y = yPos - yOffset;
00764 
00765         for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00766              pos = message.find( '\n' ))
00767         {
00768             glRasterPos3f( 10.f - xOffset, y, 0.99f );
00769             font->draw( message.substr( 0, pos ));
00770             message = message.substr( pos + 1 );
00771             y -= 22.f;
00772         }
00773         // last line
00774         glRasterPos3f( 10.f - xOffset, y, 0.99f );
00775         font->draw( message );
00776     }
00777 
00778     glMatrixMode( GL_PROJECTION );
00779     glLoadIdentity();
00780     applyScreenFrustum();
00781     glMatrixMode( GL_MODELVIEW );
00782 
00783     if( frameData.showHelp( ))
00784     {
00785         const eq::Window::Font* font = getWindow()->getSmallFont();
00786         std::string help = EqPly::getHelp();
00787         float y = height - 16.f;
00788 
00789         for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00790              pos = help.find( '\n' ))
00791         {
00792             glRasterPos3f( 10.f, y, 0.99f );
00793             
00794             font->draw( help.substr( 0, pos ));
00795             help = help.substr( pos + 1 );
00796             y -= 16.f;
00797         }
00798         // last line
00799         glRasterPos3f( 10.f, y, 0.99f );
00800         font->draw( help );
00801     }
00802 
00803     resetAssemblyState();
00804 }
00805 
00806 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
00807 {
00808     // compute dynamic near/far plane of whole model
00809     const FrameData& frameData = _getFrameData();
00810 
00811     const eq::Matrix4f& rotation     = frameData.getCameraRotation();
00812     const eq::Matrix4f headTransform = getHeadTransform() * rotation;
00813 
00814     eq::Matrix4f modelInv;
00815     compute_inverse( headTransform, modelInv );
00816 
00817     const eq::Vector3f zero  = modelInv * eq::Vector3f::ZERO;
00818     eq::Vector3f       front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
00819 
00820     front -= zero;
00821     front.normalize();
00822     front *= boundingSphere.w();
00823 
00824     const eq::Vector3f center =  
00825         frameData.getCameraPosition().get_sub_vector< 3 >() -
00826         boundingSphere.get_sub_vector< 3 >();
00827     const eq::Vector3f nearPoint  = headTransform * ( center - front );
00828     const eq::Vector3f farPoint   = headTransform * ( center + front );
00829 
00830     if( useOrtho( ))
00831     {
00832         LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) > 
00833                       std::numeric_limits< float >::epsilon(),
00834                       nearPoint << " == " << farPoint );
00835         setNearFar( -nearPoint.z(), -farPoint.z() );
00836     }
00837     else
00838     {
00839         // estimate minimal value of near plane based on frustum size
00840         const eq::Frustumf& frustum = getFrustum();
00841         const float width  = fabs( frustum.right() - frustum.left() );
00842         const float height = fabs( frustum.top() - frustum.bottom() );
00843         const float size   = LB_MIN( width, height );
00844         const float minNear = frustum.near_plane() / size * .001f;
00845 
00846         const float zNear = LB_MAX( minNear, -nearPoint.z() );
00847         const float zFar  = LB_MAX( zNear * 2.f, -farPoint.z() );
00848 
00849         setNearFar( zNear, zFar );
00850     }
00851 }
00852 
00853 }
Generated on Mon Nov 26 2012 14:41:48 for Equalizer 1.4.1 by  doxygen 1.7.6.1