00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "channel.h"
00020
00021 #include "initData.h"
00022 #include "config.h"
00023 #include "configEvent.h"
00024 #include "pipe.h"
00025 #include "view.h"
00026 #include "window.h"
00027 #include "vertexBufferState.h"
00028
00029
00030 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
00031 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
00032 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00033 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
00034
00035
00036 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
00037 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00038 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
00039 static GLint materialShininess = 64;
00040
00041 #ifndef M_SQRT3_2
00042 # define M_SQRT3_2 0.86603f
00043 #endif
00044
00045 namespace eqPly
00046 {
00047
00048 Channel::Channel( eq::Window* parent )
00049 : eq::Channel( parent )
00050 , _model(0)
00051 , _modelID( EQ_ID_INVALID )
00052 {
00053 }
00054
00055 bool Channel::configInit( const uint32_t initID )
00056 {
00057 EQINFO << getID() << ": " << getName() << std::endl;
00058 if( !eq::Channel::configInit( initID ))
00059 return false;
00060
00061 setNearFar( 0.1f, 10.0f );
00062 _model = 0;
00063 _modelID = EQ_ID_INVALID;
00064 return true;
00065 }
00066
00067 bool Channel::configExit()
00068 {
00069 for( size_t i = 0; i < eq::EYE_ALL; ++i )
00070 {
00071 delete _accum[ i ].buffer;
00072 _accum[ i ].buffer = 0;
00073 }
00074
00075 return true;
00076 }
00077
00078 void Channel::frameClear( const uint32_t frameID )
00079 {
00080 _initJitter();
00081 const FrameData& frameData = _getFrameData();
00082 if( _isDone() && !_accum[ getEye() ].transfer )
00083 return;
00084
00085 applyBuffer();
00086 applyViewport();
00087
00088 const eq::View* view = getView();
00089 if( view && frameData.getCurrentViewID() == view->getID( ))
00090 glClearColor( .4f, .4f, .4f, 1.0f );
00091 #ifndef NDEBUG
00092 else if( getenv( "EQ_TAINT_CHANNELS" ))
00093 {
00094 const eq::Vector3ub color = getUniqueColor();
00095 glClearColor( color.r()/255.0f,
00096 color.g()/255.0f,
00097 color.b()/255.0f, 1.0f );
00098 }
00099 #endif // NDEBUG
00100 else
00101 glClearColor( 0.f, 0.f, 0.f, 1.0f );
00102
00103 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00104 }
00105
00106 void Channel::frameDraw( const uint32_t frameID )
00107 {
00108 _initJitter();
00109 if( _isDone( ))
00110 return;
00111
00112 const Model* model = _getModel();
00113 if( model )
00114 _updateNearFar( model->getBoundingSphere( ));
00115
00116
00117 eq::Channel::frameDraw( frameID );
00118
00119 glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00120 glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00121 glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse );
00122 glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00123
00124 glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
00125 glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
00126 glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
00127 glMateriali( GL_FRONT, GL_SHININESS, materialShininess );
00128
00129 const FrameData& frameData = _getFrameData();
00130 glPolygonMode( GL_FRONT_AND_BACK,
00131 frameData.useWireframe() ? GL_LINE : GL_FILL );
00132
00133 const eq::Vector3f& translation = frameData.getCameraTranslation();
00134
00135 glMultMatrixf( frameData.getCameraRotation().array );
00136 glTranslatef( translation.x(), translation.y(), translation.z() );
00137 glMultMatrixf( frameData.getModelRotation().array );
00138
00139 if( frameData.getColorMode() == COLOR_DEMO )
00140 {
00141 const eq::Vector3ub color = getUniqueColor();
00142 glColor3ub( color.r(), color.g(), color.b() );
00143 }
00144 else
00145 glColor3f( .75f, .75f, .75f );
00146
00147 if( model )
00148 {
00149 _drawModel( model );
00150 }
00151 else
00152 {
00153 glNormal3f( 0.f, -1.f, 0.f );
00154 glBegin( GL_TRIANGLE_STRIP );
00155 glVertex3f( .25f, 0.f, .25f );
00156 glVertex3f( -.25f, 0.f, .25f );
00157 glVertex3f( .25f, 0.f, -.25f );
00158 glVertex3f( -.25f, 0.f, -.25f );
00159 glEnd();
00160 }
00161
00162 Accum& accum = _accum[ getEye() ];
00163 accum.stepsDone = EQ_MAX( accum.stepsDone,
00164 getSubPixel().size * getPeriod( ));
00165 accum.transfer = true;
00166 }
00167
00168 void Channel::frameAssemble( const uint32_t frameID )
00169 {
00170 if( _isDone( ))
00171 return;
00172
00173 Accum& accum = _accum[ getEye() ];
00174
00175 if( getPixelViewport() != _currentPVP )
00176 {
00177 accum.transfer = true;
00178
00179 if( accum.buffer && !accum.buffer->usesFBO( ))
00180 {
00181 EQWARN << "Current viewport different from view viewport, ";
00182 EQWARN << "idle anti-aliasing not implemented." << std::endl;
00183 accum.step = 0;
00184 }
00185
00186 eq::Channel::frameAssemble( frameID );
00187 return;
00188 }
00189
00190
00191 bool subPixelALL = true;
00192 const eq::FrameVector& frames = getInputFrames();
00193
00194 for( eq::FrameVector::const_iterator i = frames.begin();
00195 i != frames.end(); ++i )
00196 {
00197 eq::Frame* frame = *i;
00198 const eq::SubPixel& curSubPixel = frame->getSubPixel();
00199
00200 if( curSubPixel != eq::SubPixel::ALL )
00201 subPixelALL = false;
00202
00203 accum.stepsDone = EQ_MAX( accum.stepsDone,
00204 frame->getSubPixel().size*frame->getPeriod());
00205 }
00206
00207 accum.transfer = subPixelALL;
00208
00209 applyBuffer();
00210 applyViewport();
00211 setupAssemblyState();
00212
00213 eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer );
00214
00215 resetAssemblyState();
00216 }
00217
00218 void Channel::frameReadback( const uint32_t frameID )
00219 {
00220 if( _isDone( ))
00221 return;
00222
00223
00224 const eq::FrameVector& frames = getOutputFrames();
00225 for( eq::FrameVector::const_iterator i = frames.begin();
00226 i != frames.end(); ++i )
00227 {
00228 (*i)->setAlphaUsage( false );
00229 }
00230
00231 eq::Channel::frameReadback( frameID );
00232 }
00233
00234 void Channel::frameStart( const uint32_t frameID, const uint32_t frameNumber )
00235 {
00236 for( size_t i = 0; i < eq::EYE_ALL; ++i )
00237 _accum[ i ].stepsDone = 0;
00238
00239 eq::Channel::frameStart( frameID, frameNumber );
00240 }
00241
00242 void Channel::frameViewStart( const uint32_t frameID )
00243 {
00244 _currentPVP = getPixelViewport();
00245 _initJitter();
00246 eq::Channel::frameViewStart( frameID );
00247 }
00248
00249 void Channel::frameFinish( const uint32_t frameID,
00250 const uint32_t frameNumber )
00251 {
00252 for( size_t i = 0; i < eq::EYE_ALL; ++i )
00253 {
00254 Accum& accum = _accum[ i ];
00255 if( accum.step > 0 )
00256 {
00257 if( static_cast< int32_t >( accum.stepsDone ) > accum.step )
00258 accum.step = 0;
00259 else
00260 accum.step -= accum.stepsDone;
00261 }
00262 }
00263
00264 eq::Channel::frameFinish( frameID, frameNumber );
00265 }
00266
00267 void Channel::frameViewFinish( const uint32_t frameID )
00268 {
00269 applyBuffer();
00270
00271 const FrameData& frameData = _getFrameData();
00272 Accum& accum = _accum[ getEye() ];
00273
00274 if( accum.buffer )
00275 {
00276 const eq::PixelViewport& pvp = getPixelViewport();
00277 const bool isResized = accum.buffer->resize( pvp.w, pvp.h );
00278
00279 if( isResized )
00280 {
00281 const View* view = static_cast< const View* >( getView( ));
00282 accum.buffer->clear();
00283 accum.step = view->getIdleSteps();
00284 accum.stepsDone = 0;
00285 }
00286 else if( frameData.isIdle( ))
00287 {
00288 setupAssemblyState();
00289
00290 if( !_isDone() && accum.transfer )
00291 accum.buffer->accum();
00292 accum.buffer->display();
00293
00294 resetAssemblyState();
00295 }
00296 }
00297
00298 applyViewport();
00299 _drawOverlay();
00300 _drawHelp();
00301
00302 if( frameData.useStatistics())
00303 drawStatistics();
00304
00305 ConfigEvent event;
00306 event.data.originator = getID();
00307 event.data.type = ConfigEvent::IDLE_AA_LEFT;
00308
00309 const bool isIdle = frameData.isIdle();
00310
00311 if( isIdle )
00312 {
00313 int32_t maxSteps = 0;
00314 for( size_t i = 0; i < eq::EYE_ALL; ++i )
00315 maxSteps = EQ_MAX( maxSteps, _accum[i].step );
00316
00317 event.steps = maxSteps;
00318 }
00319 else
00320 {
00321 const View* view = static_cast< const View* >( getView( ));
00322 if( view )
00323 event.steps = view->getIdleSteps();
00324 else
00325 event.steps = 0;
00326 }
00327
00328
00329
00330 eq::Config* config = getConfig();
00331 config->sendEvent( event );
00332 }
00333
00334 void Channel::applyFrustum() const
00335 {
00336 const FrameData& frameData = _getFrameData();
00337 const eq::Vector2f jitter = _getJitter();
00338
00339 if( frameData.useOrtho( ))
00340 {
00341 eq::Frustumf ortho = getOrtho();
00342 ortho.apply_jitter( jitter );
00343
00344 glOrtho( ortho.left(), ortho.right(),
00345 ortho.bottom(), ortho.top(),
00346 ortho.near_plane(), ortho.far_plane( ));
00347 }
00348 else
00349 {
00350 eq::Frustumf frustum = getFrustum();
00351 frustum.apply_jitter( jitter );
00352
00353 glFrustum( frustum.left(), frustum.right(),
00354 frustum.bottom(), frustum.top(),
00355 frustum.near_plane(), frustum.far_plane( ));
00356 }
00357 }
00358
00359 const FrameData& Channel::_getFrameData() const
00360 {
00361 const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
00362 return pipe->getFrameData();
00363 }
00364
00365 bool Channel::_isDone() const
00366 {
00367 const FrameData& frameData = _getFrameData();
00368 if( !frameData.isIdle( ))
00369 return false;
00370
00371 const eq::SubPixel& subpixel = getSubPixel();
00372 const Accum& accum = _accum[ getEye() ];
00373 return static_cast< int32_t >( subpixel.index ) >= accum.step;
00374 }
00375
00376 void Channel::_initJitter()
00377 {
00378 if( !_initAccum( ))
00379 return;
00380
00381 const FrameData& frameData = _getFrameData();
00382 if( frameData.isIdle( ))
00383 return;
00384
00385 const View* view = static_cast< const View* >( getView( ));
00386 const uint32_t totalSteps = view->getIdleSteps();
00387
00388 if( totalSteps == 0 )
00389 return;
00390
00391
00392 Accum& accum = _accum[ getEye() ];
00393
00394 if( accum.buffer )
00395 accum.buffer->clear();
00396 accum.step = totalSteps;
00397 }
00398
00399 bool Channel::_initAccum()
00400 {
00401 if( !getNativeView( ))
00402 return true;
00403
00404 const eq::Eye eye = getEye();
00405 Accum& accum = _accum[ eye ];
00406
00407 if( accum.buffer )
00408 return true;
00409
00410 if( accum.step == -1 )
00411 return false;
00412
00413
00414 if( !eq::util::Accum::usesFBO( glewGetContext( )))
00415 {
00416 for( size_t i = 0; i < eq::EYE_ALL; ++i )
00417 {
00418 if( _accum[ i ].buffer )
00419 {
00420 EQWARN << "glAccum-based accumulation does not support "
00421 << "stereo, disabling idle anti-aliasing."
00422 << std::endl;
00423 for( size_t j = 0; j < eq::EYE_ALL; ++j )
00424 {
00425 delete _accum[ j ].buffer;
00426 _accum[ j ].buffer = 0;
00427 _accum[ j ].step = -1;
00428 }
00429
00430 ConfigEvent event;
00431 event.data.type = ConfigEvent::IDLE_AA_TOTAL;
00432 event.data.originator = getNativeView()->getID();
00433 event.steps = 0;
00434
00435 eq::Config* config = getConfig();
00436 config->sendEvent( event );
00437 return false;
00438 }
00439 }
00440 }
00441
00442
00443 accum.buffer = new eq::util::Accum( glewGetContext( ));
00444 const eq::PixelViewport& pvp = getPixelViewport();
00445 EQASSERT( pvp.isValid( ));
00446
00447 if( !accum.buffer->init( pvp, getWindow()->getColorFormat( )) ||
00448 accum.buffer->getMaxSteps() < 256 )
00449 {
00450 EQWARN <<"Accumulation buffer initialization failed, "
00451 << "idle AA not available." << std::endl;
00452 delete accum.buffer;
00453 accum.buffer = 0;
00454 accum.step = -1;
00455 return false;
00456 }
00457
00458
00459 EQINFO << "Initialized "
00460 << (accum.buffer->usesFBO() ? "FBO accum" : "glAccum")
00461 << " buffer for " << getName() << " " << getEye()
00462 << std::endl;
00463
00464 ConfigEvent event;
00465 event.data.type = ConfigEvent::IDLE_AA_TOTAL;
00466 event.data.originator = getNativeView()->getID();
00467 event.steps = accum.buffer ? 256 : 0;
00468
00469 eq::Config* config = getConfig();
00470 config->sendEvent( event );
00471 return true;
00472 }
00473
00474 eq::Vector2f Channel::_getJitter() const
00475 {
00476 const FrameData& frameData = _getFrameData();
00477 const Accum& accum = _accum[ getEye() ];
00478
00479 if( !frameData.isIdle() || accum.step <= 0 )
00480 return eq::Channel::getJitter();
00481
00482 const View* view = static_cast< const View* >( getView( ));
00483 if( !view || view->getIdleSteps() != 256 )
00484 return eq::Vector2f::ZERO;
00485
00486 eq::Vector2i jitterStep = _getJitterStep();
00487 if( jitterStep == eq::Vector2i::ZERO )
00488 return eq::Vector2f::ZERO;
00489
00490 const eq::PixelViewport& pvp = getPixelViewport();
00491 const float pvp_w = static_cast<float>( pvp.w );
00492 const float pvp_h = static_cast<float>( pvp.h );
00493 const float frustum_w = static_cast<float>(( getFrustum().get_width( )));
00494 const float frustum_h = static_cast<float>(( getFrustum().get_height( )));
00495
00496 const float pixel_w = frustum_w / pvp_w;
00497 const float pixel_h = frustum_h / pvp_h;
00498
00499 const float sampleSize = 16.f;
00500 const float subpixel_w = pixel_w / sampleSize;
00501 const float subpixel_h = pixel_h / sampleSize;
00502
00503
00504 eq::base::RNG rng;
00505 float value_i = rng.get< float >() * subpixel_w
00506 + static_cast<float>( jitterStep.x( )) * subpixel_w;
00507
00508 float value_j = rng.get< float >() * subpixel_h
00509 + static_cast<float>( jitterStep.y( )) * subpixel_h;
00510
00511 const eq::Pixel& pixel = getPixel();
00512 value_i /= static_cast<float>( pixel.w );
00513 value_j /= static_cast<float>( pixel.h );
00514
00515 return eq::Vector2f( value_i, value_j );
00516 }
00517
00518 eq::Vector2i Channel::_getJitterStep() const
00519 {
00520 const eq::SubPixel& subPixel = getSubPixel();
00521 uint32_t channelID = subPixel.index;
00522 const View* view = static_cast< const View* >( getView( ));
00523 if( !view )
00524 return eq::Vector2i::ZERO;
00525
00526 const uint32_t totalSteps = view->getIdleSteps();
00527 if( totalSteps != 256 )
00528 return eq::Vector2i::ZERO;
00529
00530 const Accum& accum = _accum[ getEye() ];
00531 const uint32_t subset = totalSteps / getSubPixel().size;
00532 const uint32_t idx =
00533 ( accum.step * primeNumberTable[ channelID ] ) % subset +
00534 ( channelID * subset );
00535
00536 const uint32_t sampleSize = 16;
00537 const int dx = idx % sampleSize;
00538 const int dy = idx / sampleSize;
00539
00540 return eq::Vector2i( dx, dy );
00541 }
00542
00543 const Model* Channel::_getModel()
00544 {
00545 Config* config = static_cast< Config* >( getConfig( ));
00546 const View* view = static_cast< const View* >( getView( ));
00547 const FrameData& frameData = _getFrameData();
00548 EQASSERT( !view || dynamic_cast< const View* >( getView( )));
00549
00550 const uint32_t id = view ? view->getModelID() : frameData.getModelID();
00551 if( id != _modelID )
00552 {
00553 _model = config->getModel( id );
00554 _modelID = id;
00555 }
00556
00557 return _model;
00558 }
00559
00560 void Channel::_drawModel( const Model* model )
00561 {
00562 Window* window = static_cast<Window*>( getWindow() );
00563 VertexBufferState& state = window->getState();
00564 const FrameData& frameData = _getFrameData();
00565 const eq::Range& range = getRange();
00566 eq::FrustumCullerf culler;
00567
00568 if( frameData.getColorMode() == COLOR_MODEL && model->hasColors( ))
00569 state.setColors( true );
00570 else
00571 state.setColors( false );
00572
00573 _initFrustum( culler, model->getBoundingSphere( ));
00574
00575 const eq::Pipe* pipe = getPipe();
00576 const GLuint program = state.getProgram( pipe );
00577 if( program != VertexBufferState::INVALID )
00578 glUseProgram( program );
00579
00580 model->beginRendering( state );
00581
00582
00583 std::vector< const mesh::VertexBufferBase* > candidates;
00584 candidates.push_back( model );
00585
00586 #ifndef NDEBUG
00587 size_t verticesRendered = 0;
00588 size_t verticesOverlap = 0;
00589 #endif
00590
00591 while( !candidates.empty() )
00592 {
00593 const mesh::VertexBufferBase* treeNode = candidates.back();
00594 candidates.pop_back();
00595
00596
00597 if( treeNode->getRange()[0] >= range.end ||
00598 treeNode->getRange()[1] < range.start )
00599 continue;
00600
00601
00602 const vmml::Visibility visibility =
00603 culler.test_sphere( treeNode->getBoundingSphere( ));
00604
00605 switch( visibility )
00606 {
00607 case vmml::VISIBILITY_FULL:
00608
00609 if( range == eq::Range::ALL ||
00610 ( treeNode->getRange()[0] >= range.start &&
00611 treeNode->getRange()[1] < range.end ))
00612 {
00613 treeNode->render( state );
00614
00615 #ifndef NDEBUG
00616 verticesRendered += treeNode->getNumberOfVertices();
00617 #endif
00618 break;
00619 }
00620
00621
00622 case vmml::VISIBILITY_PARTIAL:
00623 {
00624 const mesh::VertexBufferBase* left = treeNode->getLeft();
00625 const mesh::VertexBufferBase* right = treeNode->getRight();
00626
00627 if( !left && !right )
00628 {
00629 if( treeNode->getRange()[0] >= range.start )
00630 {
00631 treeNode->render( state );
00632
00633 #ifndef NDEBUG
00634 verticesRendered += treeNode->getNumberOfVertices();
00635 if( visibility == vmml::VISIBILITY_PARTIAL )
00636 verticesOverlap += treeNode->getNumberOfVertices();
00637 #endif
00638 }
00639
00640 }
00641 else
00642 {
00643 if( left )
00644 candidates.push_back( left );
00645 if( right )
00646 candidates.push_back( right );
00647 }
00648 break;
00649 }
00650 case vmml::VISIBILITY_NONE:
00651
00652 break;
00653 }
00654 }
00655
00656 model->endRendering( state );
00657
00658 if( program != VertexBufferState::INVALID )
00659 glUseProgram( 0 );
00660
00661 #ifndef NDEBUG
00662 const size_t verticesTotal = model->getNumberOfVertices();
00663 EQLOG( LOG_CULL )
00664 << getName() << " rendered " << verticesRendered * 100 / verticesTotal
00665 << "% of model, overlap <= " << verticesOverlap * 100 / verticesTotal
00666 << "%" << std::endl;
00667 #endif
00668 }
00669
00670 void Channel::_drawOverlay()
00671 {
00672
00673 const Window* window = static_cast<Window*>( getWindow( ));
00674 GLuint texture;
00675 eq::Vector2i size;
00676
00677 window->getLogoTexture( texture, size );
00678
00679 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00680 glMatrixMode( GL_PROJECTION );
00681 glLoadIdentity();
00682 applyScreenFrustum();
00683 glMatrixMode( GL_MODELVIEW );
00684 glLoadIdentity();
00685
00686 glDisable( GL_DEPTH_TEST );
00687 glDisable( GL_LIGHTING );
00688 glColor3f( 1.0f, 1.0f, 1.0f );
00689
00690 #if 1
00691
00692 const eq::PixelViewport& pvp = getPixelViewport();
00693 const eq::Viewport& vp = getViewport();
00694 const float w = pvp.w / vp.w - .5f;
00695 const float h = pvp.h / vp.h - .5f;
00696
00697 glBegin( GL_LINE_LOOP );
00698 {
00699 glVertex3f( .5f, .5f, 0.f );
00700 glVertex3f( w, .5f, 0.f );
00701 glVertex3f( w, h, 0.f );
00702 glVertex3f( .5f, h, 0.f );
00703 }
00704 glEnd();
00705 #endif
00706
00707
00708 if( texture )
00709 {
00710 glEnable( GL_BLEND );
00711 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00712
00713 glEnable( GL_TEXTURE_RECTANGLE_ARB );
00714 glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
00715 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
00716 GL_LINEAR );
00717 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
00718 GL_LINEAR );
00719
00720 glBegin( GL_TRIANGLE_STRIP ); {
00721 glTexCoord2f( 0.0f, 0.0f );
00722 glVertex3f( 5.0f, 5.0f, 0.0f );
00723
00724 glTexCoord2f( size.x(), 0.0f );
00725 glVertex3f( size.x() + 5.0f, 5.0f, 0.0f );
00726
00727 glTexCoord2f( 0.0f, size.y() );
00728 glVertex3f( 5.0f, size.y() + 5.0f, 0.0f );
00729
00730 glTexCoord2f( size.x(), size.y() );
00731 glVertex3f( size.x() + 5.0f, size.y() + 5.0f, 0.0f );
00732 } glEnd();
00733
00734 glDisable( GL_TEXTURE_RECTANGLE_ARB );
00735 glDisable( GL_BLEND );
00736 }
00737 glEnable( GL_LIGHTING );
00738 glEnable( GL_DEPTH_TEST );
00739 }
00740
00741 void Channel::_drawHelp()
00742 {
00743 const FrameData& frameData = _getFrameData();
00744 std::string message = frameData.getMessage();
00745
00746 if( !frameData.showHelp() && message.empty( ))
00747 return;
00748
00749 applyBuffer();
00750 applyViewport();
00751 setupAssemblyState();
00752
00753 glDisable( GL_LIGHTING );
00754 glDisable( GL_DEPTH_TEST );
00755
00756 glColor3f( 1.f, 1.f, 1.f );
00757
00758 if( frameData.showHelp( ))
00759 {
00760 const eq::Window::Font* font = getWindow()->getSmallFont();
00761 std::string help = EqPly::getHelp();
00762 float y = 340.f;
00763
00764 for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00765 pos = help.find( '\n' ))
00766 {
00767 glRasterPos3f( 10.f, y, 0.99f );
00768
00769 font->draw( help.substr( 0, pos ));
00770 help = help.substr( pos + 1 );
00771 y -= 16.f;
00772 }
00773
00774 glRasterPos3f( 10.f, y, 0.99f );
00775 font->draw( help );
00776 }
00777
00778 if( !message.empty( ))
00779 {
00780 const eq::Window::Font* font = getWindow()->getMediumFont();
00781
00782 const eq::Viewport& vp = getViewport();
00783 const eq::PixelViewport& pvp = getPixelViewport();
00784
00785 const float width = pvp.w / vp.w;
00786 const float xOffset = vp.x * width;
00787
00788 const float height = pvp.h / vp.h;
00789 const float yOffset = vp.y * height;
00790 const float yMiddle = 0.5f * height;
00791 float y = yMiddle - yOffset;
00792
00793 for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00794 pos = message.find( '\n' ))
00795 {
00796 glRasterPos3f( 10.f - xOffset, y, 0.99f );
00797
00798 font->draw( message.substr( 0, pos ));
00799 message = message.substr( pos + 1 );
00800 y -= 22.f;
00801 }
00802
00803 glRasterPos3f( 10.f - xOffset, y, 0.99f );
00804 font->draw( message );
00805 }
00806
00807 resetAssemblyState();
00808 }
00809
00810 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
00811 {
00812
00813 const FrameData& frameData = _getFrameData();
00814 const bool ortho = frameData.useOrtho();
00815
00816 const eq::Matrix4f& rotation = frameData.getCameraRotation();
00817 const eq::Matrix4f headTransform = getHeadTransform() * rotation;
00818
00819 eq::Matrix4f modelInv;
00820 compute_inverse( headTransform, modelInv );
00821
00822 const eq::Vector3f zero = modelInv * eq::Vector3f::ZERO;
00823 eq::Vector3f front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
00824
00825 front -= zero;
00826 front.normalize();
00827 front *= boundingSphere.w();
00828
00829 const eq::Vector3f center = boundingSphere.get_sub_vector< 3 >() +
00830 frameData.getCameraTranslation( ).get_sub_vector< 3 >();
00831 const eq::Vector3f nearPoint = headTransform * ( center - front );
00832 const eq::Vector3f farPoint = headTransform * ( center + front );
00833
00834 if( ortho )
00835 {
00836 EQASSERT( fabs( farPoint.z() - nearPoint.z() ) >
00837 std::numeric_limits< float >::epsilon( ));
00838 setNearFar( -nearPoint.z(), -farPoint.z() );
00839 }
00840 else
00841 {
00842
00843 const eq::Frustumf& frustum = getFrustum();
00844 const float width = fabs( frustum.right() - frustum.left() );
00845 const float height = fabs( frustum.top() - frustum.bottom() );
00846 const float size = EQ_MIN( width, height );
00847 const float minNear = frustum.near_plane() / size * .001f;
00848
00849 const float zNear = EQ_MAX( minNear, -nearPoint.z() );
00850 const float zFar = EQ_MAX( zNear * 2.f, -farPoint.z() );
00851
00852 setNearFar( zNear, zFar );
00853 }
00854 }
00855
00856 void Channel::_initFrustum( eq::FrustumCullerf& culler,
00857 const mesh::BoundingSphere& boundingSphere )
00858 {
00859
00860 const FrameData& frameData = _getFrameData();
00861 const eq::Matrix4f& rotation = frameData.getCameraRotation();
00862 const eq::Matrix4f& modelRotation = frameData.getModelRotation();
00863 eq::Matrix4f translation = eq::Matrix4f::IDENTITY;
00864 translation.set_translation( frameData.getCameraTranslation());
00865
00866 const eq::Matrix4f modelView =
00867 getHeadTransform() * rotation * translation * modelRotation;
00868
00869 const bool ortho = frameData.useOrtho();
00870 const eq::Frustumf& frustum = ortho ? getOrtho() : getFrustum();
00871 const eq::Matrix4f projection = ortho ? frustum.compute_ortho_matrix() :
00872 frustum.compute_matrix();
00873 culler.setup( projection * modelView );
00874 }
00875 }