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