Equalizer  1.3.1-git
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     // Setup OpenGL state
00145     eq::Channel::frameDraw( frameID );
00146 
00147     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00148     glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
00149     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00150     glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00151 
00152     glMaterialfv( GL_FRONT, GL_AMBIENT,   materialAmbient );
00153     glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
00154     glMaterialfv( GL_FRONT, GL_SPECULAR,  materialSpecular );
00155     glMateriali(  GL_FRONT, GL_SHININESS, materialShininess );
00156 
00157     const FrameData& frameData = _getFrameData();
00158     glPolygonMode( GL_FRONT_AND_BACK, 
00159                    frameData.useWireframe() ? GL_LINE : GL_FILL );
00160 
00161     const eq::Vector3f& position = frameData.getCameraPosition();
00162 
00163     glMultMatrixf( frameData.getCameraRotation().array );
00164     glTranslatef( position.x(), position.y(), position.z() );
00165     glMultMatrixf( frameData.getModelRotation().array );
00166 
00167     if( frameData.getColorMode() == COLOR_DEMO )
00168     {
00169         const eq::Vector3ub color = getUniqueColor();
00170         glColor3ub( color.r(), color.g(), color.b() );
00171     }
00172     else
00173         glColor3f( .75f, .75f, .75f );
00174 
00175     if( model )
00176         _drawModel( model );
00177     else
00178     {
00179         glNormal3f( 0.f, -1.f, 0.f );
00180         glBegin( GL_TRIANGLE_STRIP );
00181             glVertex3f(  .25f, 0.f,  .25f );
00182             glVertex3f( -.25f, 0.f,  .25f );
00183             glVertex3f(  .25f, 0.f, -.25f );
00184             glVertex3f( -.25f, 0.f, -.25f );
00185         glEnd();
00186     }
00187 
00188     state.setFrustumCulling( true );
00189     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00190     accum.stepsDone = LB_MAX( accum.stepsDone, 
00191                               getSubPixel().size * getPeriod( ));
00192     accum.transfer = true;
00193 }
00194 
00195 void Channel::frameAssemble( const eq::uint128_t& frameID )
00196 {
00197     if( stopRendering( ))
00198         return;
00199 
00200     if( _isDone( ))
00201         return;
00202 
00203     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00204 
00205     if( getPixelViewport() != _currentPVP )
00206     {
00207         accum.transfer = true;
00208 
00209         if( accum.buffer && !accum.buffer->usesFBO( ))
00210         {
00211             LBWARN << "Current viewport different from view viewport, "
00212                    << "idle anti-aliasing not implemented." << std::endl;
00213             accum.step = 0;
00214         }
00215 
00216         eq::Channel::frameAssemble( frameID );
00217         return;
00218     }
00219     // else
00220     
00221     accum.transfer = true;
00222     const eq::Frames& frames = getInputFrames();
00223 
00224     for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i )
00225     {
00226         eq::Frame* frame = *i;
00227         const eq::SubPixel& curSubPixel = frame->getSubPixel();
00228 
00229         if( curSubPixel != eq::SubPixel::ALL )
00230             accum.transfer = false;
00231 
00232         accum.stepsDone = LB_MAX( accum.stepsDone, 
00233                                   frame->getSubPixel().size*frame->getPeriod( ));
00234     }
00235 
00236     applyBuffer();
00237     applyViewport();
00238     setupAssemblyState();
00239 
00240     try
00241     {
00242         eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer );
00243     }
00244     catch( const co::Exception& e )
00245     {
00246         LBWARN << e.what() << std::endl;
00247     }
00248 
00249     resetAssemblyState();
00250 }
00251 
00252 void Channel::frameReadback( const eq::uint128_t& frameID )
00253 {
00254     if( stopRendering() || _isDone( ))
00255         return;
00256 
00257     const FrameData& frameData = _getFrameData();
00258     const eq::Frames& frames = getOutputFrames();
00259     for( eq::FramesCIter i = frames.begin(); i != frames.end(); ++i )
00260     {
00261         eq::Frame* frame = *i;
00262         // OPT: Drop alpha channel from all frames during network transport
00263         frame->setAlphaUsage( false );
00264         
00265         if( frameData.isIdle( ))
00266             frame->setQuality( eq::Frame::BUFFER_COLOR, 1.f );
00267         else
00268             frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality());
00269 
00270         if( frameData.useCompression( ))
00271             frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_AUTO );
00272         else
00273             frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_NONE );
00274     }
00275 
00276     eq::Channel::frameReadback( frameID );
00277 }
00278 
00279 void Channel::frameStart( const eq::uint128_t& frameID,
00280                           const uint32_t frameNumber )
00281 {
00282     if( stopRendering( ))
00283         return;
00284 
00285     for( size_t i = 0; i < eq::NUM_EYES; ++i )
00286         _accum[ i ].stepsDone = 0;
00287 
00288     eq::Channel::frameStart( frameID, frameNumber );
00289 }
00290 
00291 void Channel::frameViewStart( const eq::uint128_t& frameID )
00292 {
00293     if( stopRendering( ))
00294         return;
00295 
00296     _currentPVP = getPixelViewport();
00297     _initJitter();
00298     eq::Channel::frameViewStart( frameID );
00299 }
00300 
00301 void Channel::frameFinish( const eq::uint128_t& frameID,
00302                            const uint32_t frameNumber )
00303 {
00304     if( stopRendering( ))
00305         return;
00306 
00307     for( size_t i = 0; i < eq::NUM_EYES; ++i )
00308     {
00309         Accum& accum = _accum[ i ];
00310         if( accum.step > 0 )
00311         {
00312             if( int32_t( accum.stepsDone ) > accum.step )
00313                 accum.step = 0;
00314             else
00315                 accum.step -= accum.stepsDone;
00316         }
00317     }
00318 
00319     eq::Channel::frameFinish( frameID, frameNumber );
00320 }
00321 
00322 void Channel::frameViewFinish( const eq::uint128_t& frameID )
00323 {
00324     if( stopRendering( ))
00325         return;
00326 
00327     applyBuffer();
00328 
00329     const FrameData& frameData = _getFrameData();
00330     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00331 
00332     if( accum.buffer )
00333     {
00334         const eq::PixelViewport& pvp = getPixelViewport();
00335         const bool isResized = accum.buffer->resize( pvp.w, pvp.h );
00336 
00337         if( isResized )
00338         {
00339             const View* view = static_cast< const View* >( getView( ));
00340             accum.buffer->clear();
00341             accum.step = view->getIdleSteps();
00342             accum.stepsDone = 0;
00343         }
00344         else if( frameData.isIdle( ))
00345         {
00346             setupAssemblyState();
00347 
00348             if( !_isDone() && accum.transfer )
00349                 accum.buffer->accum();
00350             accum.buffer->display();
00351 
00352             resetAssemblyState();
00353         }
00354     }
00355 
00356     applyViewport();
00357     _drawOverlay();
00358     _drawHelp();
00359 
00360     if( frameData.useStatistics())
00361         drawStatistics();
00362 
00363     ConfigEvent event;
00364     event.data.originator = getID();
00365     event.data.type = ConfigEvent::IDLE_AA_LEFT;
00366 
00367     if( frameData.isIdle( ))
00368     {
00369         event.steps = 0;
00370         for( size_t i = 0; i < eq::NUM_EYES; ++i )
00371             event.steps = LB_MAX( event.steps, _accum[i].step );
00372     }
00373     else
00374     {
00375         const View* view = static_cast< const View* >( getView( ));
00376         event.steps = view ? view->getIdleSteps() : 0;
00377     }
00378 
00379     // if _jitterStep == 0 and no user redraw event happened, the app will exit
00380     // FSAA idle mode and block on the next redraw event.
00381     eq::Config* config = getConfig();
00382     config->sendEvent( event );
00383 }
00384 
00385 bool Channel::useOrtho() const
00386 {
00387     const FrameData& frameData = _getFrameData();
00388     return frameData.useOrtho();
00389 }
00390 
00391 const FrameData& Channel::_getFrameData() const
00392 {
00393     const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
00394     return pipe->getFrameData();
00395 }
00396 
00397 bool Channel::_isDone() const
00398 {
00399     const FrameData& frameData = _getFrameData();
00400     if( !frameData.isIdle( ))
00401         return false;
00402 
00403     const eq::SubPixel& subpixel = getSubPixel();
00404     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00405     return int32_t( subpixel.index ) >= accum.step;
00406 }
00407 
00408 void Channel::_initJitter()
00409 {
00410     if( !_initAccum( ))
00411         return;
00412 
00413     const FrameData& frameData = _getFrameData();
00414     if( frameData.isIdle( ))
00415         return;
00416 
00417     const View* view = static_cast< const View* >( getView( ));
00418     if( !view )
00419         return;
00420 
00421     const int32_t idleSteps = view->getIdleSteps();
00422     if( idleSteps == 0 )
00423         return;
00424 
00425     // ready for the next FSAA
00426     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00427     if( accum.buffer )
00428         accum.buffer->clear();
00429     accum.step = idleSteps;
00430 }
00431 
00432 bool Channel::_initAccum()
00433 {
00434     View* view = static_cast< View* >( getNativeView( ));
00435     if( !view ) // Only alloc accum for dest
00436         return true;
00437 
00438     const eq::Eye eye = getEye();
00439     Accum& accum = _accum[ lunchbox::getIndexOfLastBit( eye ) ];
00440 
00441     if( accum.buffer ) // already done
00442         return true;
00443 
00444     if( accum.step == -1 ) // accum init failed last time
00445         return false;
00446 
00447     // Check unsupported cases
00448     if( !eq::util::Accum::usesFBO( glewGetContext( )))
00449     {
00450         for( size_t i = 0; i < eq::NUM_EYES; ++i )
00451         {
00452             if( _accum[ i ].buffer )
00453             {
00454                 LBWARN << "glAccum-based accumulation does not support "
00455                        << "stereo, disabling idle anti-aliasing."
00456                        << std::endl;
00457                 for( size_t j = 0; j < eq::NUM_EYES; ++j )
00458                 {
00459                     delete _accum[ j ].buffer;
00460                     _accum[ j ].buffer = 0;
00461                     _accum[ j ].step = -1;
00462                 }
00463 
00464                 view->setIdleSteps( 0 );
00465                 return false;
00466             }
00467         }
00468     }
00469 
00470     // set up accumulation buffer
00471     accum.buffer = new eq::util::Accum( glewGetContext( ));
00472     const eq::PixelViewport& pvp = getPixelViewport();
00473     LBASSERT( pvp.isValid( ));
00474 
00475     if( !accum.buffer->init( pvp, getWindow()->getColorFormat( )) ||
00476         accum.buffer->getMaxSteps() < 256 )
00477     {
00478         LBWARN <<"Accumulation buffer initialization failed, "
00479                << "idle AA not available." << std::endl;
00480         delete accum.buffer;
00481         accum.buffer = 0;
00482         accum.step = -1;
00483         return false;
00484     }
00485 
00486     // else
00487     LBVERB << "Initialized "
00488            << (accum.buffer->usesFBO() ? "FBO accum" : "glAccum")
00489            << " buffer for " << getName() << " " << getEye() 
00490            << std::endl;
00491 
00492     view->setIdleSteps( accum.buffer ? 256 : 0 );
00493     return true;
00494 }
00495 
00496 bool Channel::stopRendering() const
00497 { 
00498     return getPipe()->getCurrentFrame() < _frameRestart; 
00499 }
00500 
00501 eq::Vector2f Channel::getJitter() const
00502 {
00503     const FrameData& frameData = _getFrameData();
00504     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00505 
00506     if( !frameData.isIdle() || accum.step <= 0 )
00507         return eq::Channel::getJitter();
00508 
00509     const View* view = static_cast< const View* >( getView( ));
00510     if( !view || view->getIdleSteps() != 256 )
00511         return eq::Vector2f::ZERO;
00512 
00513     const eq::Vector2i jitterStep = _getJitterStep();
00514     if( jitterStep == eq::Vector2i::ZERO )
00515         return eq::Vector2f::ZERO;
00516 
00517     const eq::PixelViewport& pvp = getPixelViewport();
00518     const float pvp_w = float( pvp.w );
00519     const float pvp_h = float( pvp.h );
00520     const float frustum_w = float(( getFrustum().get_width( )));
00521     const float frustum_h = float(( getFrustum().get_height( )));
00522 
00523     const float pixel_w = frustum_w / pvp_w;
00524     const float pixel_h = frustum_h / pvp_h;
00525 
00526     const float sampleSize = 16.f; // sqrt( 256 )
00527     const float subpixel_w = pixel_w / sampleSize;
00528     const float subpixel_h = pixel_h / sampleSize;
00529 
00530     // Sample value randomly computed within the subpixel
00531     lunchbox::RNG rng;
00532     const eq::Pixel& pixel = getPixel();
00533 
00534     const float i = ( rng.get< float >() * subpixel_w +
00535                       float( jitterStep.x( )) * subpixel_w ) / float( pixel.w );
00536     const float j = ( rng.get< float >() * subpixel_h +
00537                       float( jitterStep.y( )) * subpixel_h ) / float( pixel.h );
00538 
00539     return eq::Vector2f( i, j );
00540 }
00541 
00542 static const uint32_t _primes[100] = {
00543     739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
00544     839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
00545     947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
00546     1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109,
00547     1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
00548     1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
00549     1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
00550     1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 };
00551 
00552 eq::Vector2i Channel::_getJitterStep() const
00553 {
00554     const eq::SubPixel& subPixel = getSubPixel();
00555     const uint32_t channelID = subPixel.index;
00556     const View* view = static_cast< const View* >( getView( ));
00557     if( !view )
00558         return eq::Vector2i::ZERO;
00559 
00560     const uint32_t totalSteps = uint32_t( view->getIdleSteps( ));
00561     if( totalSteps != 256 )
00562         return eq::Vector2i::ZERO;
00563 
00564     const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
00565     const uint32_t subset = totalSteps / getSubPixel().size;
00566     const uint32_t index = ( accum.step * _primes[ channelID % 100 ] )%subset +
00567                            ( channelID * subset );
00568     const uint32_t sampleSize = 16;
00569     const int dx = index % sampleSize;
00570     const int dy = index / sampleSize;
00571 
00572     return eq::Vector2i( dx, dy );
00573 }
00574 
00575 const Model* Channel::_getModel()
00576 {
00577     Config* config = static_cast< Config* >( getConfig( ));
00578     const View* view = static_cast< const View* >( getView( ));
00579     const FrameData& frameData = _getFrameData();
00580     LBASSERT( !view || dynamic_cast< const View* >( getView( )));
00581 
00582     eq::uint128_t id = view ? view->getModelID() : frameData.getModelID();
00583     if( id == lunchbox::UUID::ZERO )
00584         id = frameData.getModelID();
00585     if( id != _modelID )
00586     {
00587         _model = config->getModel( id );
00588         _modelID = id;
00589     }
00590 
00591     return _model;
00592 }
00593 
00594 void Channel::_drawModel( const Model* scene )
00595 {
00596     Window* window = static_cast< Window* >( getWindow( ));
00597     VertexBufferState& state = window->getState();
00598     const FrameData& frameData = _getFrameData();
00599 
00600     if( frameData.getColorMode() == COLOR_MODEL && scene->hasColors( ))
00601         state.setColors( true );
00602     else
00603         state.setColors( false );
00604     state.setChannel( this );
00605 
00606     // Compute cull matrix
00607     const eq::Matrix4f& rotation = frameData.getCameraRotation();
00608     const eq::Matrix4f& modelRotation = frameData.getModelRotation();
00609     eq::Matrix4f position = eq::Matrix4f::IDENTITY;
00610     position.set_translation( frameData.getCameraPosition());
00611 
00612     const eq::Frustumf& frustum = getFrustum();
00613     const eq::Matrix4f projection = useOrtho() ? frustum.compute_ortho_matrix():
00614                                                  frustum.compute_matrix();
00615     const eq::Matrix4f& view = getHeadTransform();
00616     const eq::Matrix4f model = rotation * position * modelRotation;
00617 
00618     state.setProjectionModelViewMatrix( projection * view * model );
00619     state.setRange( &getRange().start);
00620 
00621     const eq::Pipe* pipe = getPipe();
00622     const GLuint program = state.getProgram( pipe );
00623     if( program != VertexBufferState::INVALID )
00624         glUseProgram( program );
00625     
00626     scene->cullDraw( state );
00627 
00628     state.setChannel( 0 );
00629     if( program != VertexBufferState::INVALID )
00630         glUseProgram( 0 );
00631 
00632     const InitData& initData =
00633         static_cast<Config*>( getConfig( ))->getInitData();
00634     if( !initData.useROI( ))
00635     {
00636         declareRegion( getPixelViewport( ));
00637         return;
00638     }
00639 
00640 #ifndef NDEBUG // region border
00641     const eq::PixelViewport& pvp = getPixelViewport();
00642     const eq::PixelViewport& region = getRegion();
00643 
00644     glMatrixMode( GL_PROJECTION );
00645     glLoadIdentity();
00646     glOrtho( 0.f, pvp.w, 0.f, pvp.h, -1.f, 1.f );
00647     glMatrixMode( GL_MODELVIEW );
00648     glLoadIdentity();
00649 
00650     const eq::View* currentView = getView();
00651     if( currentView && frameData.getCurrentViewID() == currentView->getID( ))
00652         glColor3f( 0.f, 0.f, 0.f );
00653     else
00654         glColor3f( 1.f, 1.f, 1.f );
00655     glNormal3f( 0.f, 0.f, 1.f );
00656 
00657     const eq::Vector4f rect( float( region.x ) + .5f, float( region.y ) + .5f,
00658                              float( region.getXEnd( )) - .5f,
00659                              float( region.getYEnd( )) - .5f );
00660     glBegin( GL_LINE_LOOP ); {
00661         glVertex3f( rect[0], rect[1], -.99f );
00662         glVertex3f( rect[2], rect[1], -.99f );
00663         glVertex3f( rect[2], rect[3], -.99f );
00664         glVertex3f( rect[0], rect[3], -.99f );
00665     } glEnd();
00666 #endif
00667 }
00668 
00669 void Channel::_drawOverlay()
00670 {
00671     // Draw the overlay logo
00672     const Window* window = static_cast<Window*>( getWindow( ));
00673     const eq::util::Texture* texture = window->getLogoTexture();
00674     if( !texture )
00675         return;
00676 
00677     glMatrixMode( GL_PROJECTION );
00678     glLoadIdentity();
00679     applyScreenFrustum();
00680     glMatrixMode( GL_MODELVIEW );
00681     glLoadIdentity();
00682 
00683     glDisable( GL_DEPTH_TEST );
00684     glDisable( GL_LIGHTING );
00685     glColor3f( 1.0f, 1.0f, 1.0f );
00686     glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00687 
00688     // logo
00689     glEnable( GL_BLEND );
00690     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00691     const GLenum target = texture->getTarget();
00692     glEnable( target );
00693     texture->bind();
00694     glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00695     glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00696     
00697     const float tWidth = float( texture->getWidth( ) );
00698     const float tHeight = float( texture->getHeight( ) );
00699 
00700     const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
00701     const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
00702 
00703     glBegin( GL_QUADS ); {
00704         glTexCoord2f( 0, 0 );
00705         glVertex3f( 5.0f, 5.0f, 0.0f );
00706 
00707         glTexCoord2f( width, 0 );
00708         glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
00709 
00710         glTexCoord2f( width, height );
00711         glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
00712 
00713         glTexCoord2f( 0, height );
00714         glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
00715 
00716     } glEnd();
00717 
00718     glDisable( target );
00719     glDisable( GL_BLEND );
00720     glEnable( GL_LIGHTING );
00721     glEnable( GL_DEPTH_TEST );
00722 }
00723 
00724 void Channel::_drawHelp()
00725 {
00726     const FrameData& frameData = _getFrameData();
00727     std::string message = frameData.getMessage();
00728 
00729     if( !frameData.showHelp() && message.empty( ))
00730         return;
00731 
00732     applyBuffer();
00733     applyViewport();
00734     setupAssemblyState();
00735 
00736     glLogicOp( GL_XOR );
00737     glEnable( GL_COLOR_LOGIC_OP );
00738     glDisable( GL_LIGHTING );
00739     glDisable( GL_DEPTH_TEST );
00740 
00741     glColor3f( 1.f, 1.f, 1.f );
00742 
00743     const eq::PixelViewport& pvp = getPixelViewport();
00744     const eq::Viewport& vp = getViewport();
00745     const float height = pvp.h / vp.h;
00746 
00747     if( !message.empty( ))
00748     {
00749         const eq::Window::Font* font = getWindow()->getMediumFont();
00750 
00751         const float width = pvp.w / vp.w;
00752         const float xOffset = vp.x * width;
00753 
00754         const float yOffset = vp.y * height;
00755         const float yPos = 0.618f * height;
00756         float y = yPos - yOffset;
00757 
00758         for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00759              pos = message.find( '\n' ))
00760         {
00761             glRasterPos3f( 10.f - xOffset, y, 0.99f );
00762             font->draw( message.substr( 0, pos ));
00763             message = message.substr( pos + 1 );
00764             y -= 22.f;
00765         }
00766         // last line
00767         glRasterPos3f( 10.f - xOffset, y, 0.99f );
00768         font->draw( message );
00769     }
00770 
00771     glMatrixMode( GL_PROJECTION );
00772     glLoadIdentity();
00773     applyScreenFrustum();
00774     glMatrixMode( GL_MODELVIEW );
00775 
00776     if( frameData.showHelp( ))
00777     {
00778         const eq::Window::Font* font = getWindow()->getSmallFont();
00779         std::string help = EqPly::getHelp();
00780         float y = height - 16.f;
00781 
00782         for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00783              pos = help.find( '\n' ))
00784         {
00785             glRasterPos3f( 10.f, y, 0.99f );
00786             
00787             font->draw( help.substr( 0, pos ));
00788             help = help.substr( pos + 1 );
00789             y -= 16.f;
00790         }
00791         // last line
00792         glRasterPos3f( 10.f, y, 0.99f );
00793         font->draw( help );
00794     }
00795 
00796     resetAssemblyState();
00797 }
00798 
00799 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
00800 {
00801     // compute dynamic near/far plane of whole model
00802     const FrameData& frameData = _getFrameData();
00803 
00804     const eq::Matrix4f& rotation     = frameData.getCameraRotation();
00805     const eq::Matrix4f headTransform = getHeadTransform() * rotation;
00806 
00807     eq::Matrix4f modelInv;
00808     compute_inverse( headTransform, modelInv );
00809 
00810     const eq::Vector3f zero  = modelInv * eq::Vector3f::ZERO;
00811     eq::Vector3f       front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
00812 
00813     front -= zero;
00814     front.normalize();
00815     front *= boundingSphere.w();
00816 
00817     const eq::Vector3f center =  
00818         frameData.getCameraPosition().get_sub_vector< 3 >() -
00819         boundingSphere.get_sub_vector< 3 >();
00820     const eq::Vector3f nearPoint  = headTransform * ( center - front );
00821     const eq::Vector3f farPoint   = headTransform * ( center + front );
00822 
00823     if( useOrtho( ))
00824     {
00825         LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) > 
00826                       std::numeric_limits< float >::epsilon(),
00827                       nearPoint << " == " << farPoint );
00828         setNearFar( -nearPoint.z(), -farPoint.z() );
00829     }
00830     else
00831     {
00832         // estimate minimal value of near plane based on frustum size
00833         const eq::Frustumf& frustum = getFrustum();
00834         const float width  = fabs( frustum.right() - frustum.left() );
00835         const float height = fabs( frustum.top() - frustum.bottom() );
00836         const float size   = LB_MIN( width, height );
00837         const float minNear = frustum.near_plane() / size * .001f;
00838 
00839         const float zNear = LB_MAX( minNear, -nearPoint.z() );
00840         const float zFar  = LB_MAX( zNear * 2.f, -farPoint.z() );
00841 
00842         setNearFar( zNear, zFar );
00843     }
00844 }
00845 
00846 }
Generated on Tue May 1 2012 15:14:24 for Equalizer 1.3.1-git by  doxygen 1.8.0