Equalizer
1.2.1
|
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 }