examples/eqPly/config.cpp

00001 
00002 /* Copyright (c) 2006-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include "view.h"
00021 #include "modelAssigner.h"
00022 
00023 namespace eqPly
00024 {
00025 
00026 Config::Config( eq::base::RefPtr< eq::Server > parent )
00027         : eq::Config( parent )
00028         , _spinX( 5 )
00029         , _spinY( 5 )
00030         , _advance( 0 )
00031         , _currentCanvas( 0 )
00032         , _messageTime( 0 )
00033         , _redraw( true )
00034         , _freeze( false )
00035 {
00036 }
00037 
00038 Config::~Config()
00039 {
00040     for( ModelVector::const_iterator i = _models.begin(); 
00041          i != _models.end(); ++i )
00042     {
00043         delete *i;
00044     }
00045     _models.clear();
00046 
00047     for( ModelDistVector::const_iterator i = _modelDist.begin(); 
00048          i != _modelDist.end(); ++i )
00049     {
00050         EQASSERT( (*i)->getID() == EQ_ID_INVALID );
00051         delete *i;
00052     }
00053     _modelDist.clear();
00054 }
00055 
00056 bool Config::init()
00057 {
00058     _loadModels();
00059 
00060     if( !_animation.isValid( ))
00061         _animation.loadAnimation( _initData.getPathFilename( ));
00062 
00063     // init distributed objects
00064     if( !_initData.useColor( ))
00065         _frameData.setColorMode( COLOR_WHITE );
00066 
00067     _frameData.setRenderMode( _initData.getRenderMode( ));
00068     registerObject( &_frameData );
00069     _frameData.setAutoObsolete( getLatency( ));
00070 
00071     _initData.setFrameDataID( _frameData.getID( ));
00072     registerObject( &_initData );
00073 
00074     // init config
00075     if( !eq::Config::init( _initData.getID( )))
00076     {
00077         _deregisterData();
00078         return false;
00079     }
00080 
00081     // init tracker
00082     if( !_initData.getTrackerPort().empty( ))
00083     {
00084         if( !_tracker.init( _initData.getTrackerPort() ))
00085             EQWARN << "Failed to initialise tracker" << std::endl;
00086         else
00087         {
00088             // Set up position of tracking system wrt world space
00089             // Note: this depends on the physical installation.
00090             eq::Matrix4f m( eq::Matrix4f::IDENTITY );
00091             m.scale( 1.f, 1.f, -1.f );
00092             _tracker.setWorldToEmitter( m );
00093 
00094             m = eq::Matrix4f::IDENTITY;
00095             m.rotate_z( -M_PI_2 );
00096             _tracker.setSensorToObject( m );
00097             EQINFO << "Tracker initialized" << std::endl;
00098         }
00099     }
00100 
00101     const eq::CanvasVector& canvases = getCanvases();
00102     if( canvases.empty( ))
00103         _currentCanvas = 0;
00104     else
00105         _currentCanvas = canvases.front();
00106 
00107     _setMessage( "Welcome to eqPly\nPress F1 for help" );
00108     return true;
00109 }
00110 
00111 bool Config::exit()
00112 {
00113     const bool ret = eq::Config::exit();
00114     _deregisterData();
00115 
00116     // retain models and distributors for possible other config runs, destructor
00117     // deletes it
00118     return ret;
00119 }
00120 
00121 namespace
00122 {
00123 static bool _isPlyfile( const std::string& filename )
00124 {
00125     const size_t size = filename.length();
00126     if( size < 5 )
00127         return false;
00128 
00129     if( filename[size-4] != '.' || filename[size-3] != 'p' ||
00130         filename[size-2] != 'l' || filename[size-1] != 'y' )
00131     {
00132         return false;
00133     }
00134     return true;
00135 }
00136 }
00137 
00138 void Config::_loadModels()
00139 {
00140     if( _models.empty( )) // only load on the first config run
00141     {
00142         eq::StringVector filenames = _initData.getFilenames();
00143         while( !filenames.empty( ))
00144         {
00145             const std::string filename = filenames.back();
00146             filenames.pop_back();
00147             EQINFO << "Loading " << filename << std::endl;
00148      
00149             if( _isPlyfile( filename ))
00150             {
00151                 Model* model = new Model;
00152 
00153                 if( _initData.useInvertedFaces() )
00154                     model->useInvertedFaces();
00155         
00156                 if( !model->readFromFile( filename.c_str() ) )
00157                 {
00158                     EQWARN << "Can't load model: " << filename << std::endl;
00159                     delete model;
00160                 }
00161                 else
00162                     _models.push_back( model );
00163             }
00164             else
00165             {
00166                 const std::string basename = eq::base::getFilename( filename );
00167                 if( basename == "." || basename == ".." )
00168                     continue;
00169 
00170                 // recursively search directories
00171                 const eq::StringVector subFiles = 
00172                     eq::base::fileSearch( filename, "*" );
00173 
00174                 for( eq::StringVector::const_iterator i = subFiles.begin();
00175                      i != subFiles.end(); ++i )
00176                 {
00177                     filenames.push_back( filename + '/' + *i );
00178                 }
00179             }
00180         }
00181     }
00182     
00183     // Register distribution helpers on each config run
00184     const bool createDist = _modelDist.empty(); //first run, create distributors
00185     const size_t  nModels = _models.size();
00186     EQASSERT( createDist || _modelDist.size() == nModels );
00187 
00188     for( size_t i = 0; i < nModels; ++i )
00189     {
00190         const Model* model = _models[i];
00191         ModelDist* modelDist = 0;
00192         if( createDist )
00193         {
00194             modelDist = new ModelDist( model );
00195             _modelDist.push_back( modelDist );
00196         }
00197         else
00198             modelDist = _modelDist[i];
00199 
00200         modelDist->registerTree( this );
00201         EQASSERT( modelDist->getID() != EQ_ID_INVALID );
00202 
00203         _frameData.setModelID( modelDist->getID( ));
00204     }
00205 
00206     EQASSERT( _modelDist.size() == nModels );
00207 
00208     if( !_modelDist.empty( ))
00209     {
00210         ModelAssigner assigner( _modelDist );
00211         accept( assigner );
00212     }
00213 }
00214 
00215 void Config::_deregisterData()
00216 {
00217     for( ModelDistVector::const_iterator i = _modelDist.begin(); 
00218          i != _modelDist.end(); ++i )
00219     {
00220         ModelDist* modelDist = *i;
00221         if( modelDist->getID() == EQ_ID_INVALID ) // already done
00222             continue;
00223 
00224         EQASSERT( modelDist->isMaster( ));
00225         modelDist->deregisterTree();
00226     }
00227 
00228     deregisterObject( &_initData );
00229     deregisterObject( &_frameData );
00230 
00231     _initData.setFrameDataID( EQ_ID_INVALID );
00232     _frameData.setModelID( EQ_ID_INVALID );
00233 }
00234 
00235 
00236 void Config::mapData( const uint32_t initDataID )
00237 {
00238     if( _initData.getID() == EQ_ID_INVALID )
00239     {
00240         EQCHECK( mapObject( &_initData, initDataID ));
00241         unmapObject( &_initData ); // data was retrieved, unmap immediately
00242     }
00243     else  // appNode, _initData is registered already
00244     {
00245         EQASSERT( _initData.getID() == initDataID );
00246     }
00247 }
00248 
00249 void Config::unmapData()
00250 {
00251     for( ModelDistVector::const_iterator i = _modelDist.begin(); 
00252          i != _modelDist.end(); ++i )
00253     {
00254         ModelDist* modelDist = *i;
00255         if( modelDist->getID() == EQ_ID_INVALID ) // already done
00256             continue;
00257 
00258         if( !modelDist->isMaster( )) // leave registered on appNode
00259             modelDist->unmapTree();
00260     }
00261 }
00262 
00263 const Model* Config::getModel( const uint32_t modelID )
00264 {
00265     if( modelID == EQ_ID_INVALID ) // no model loaded by application
00266         return 0;
00267 
00268     // Accessed concurrently from pipe threads
00269     eq::base::ScopedMutex _mutex( _modelLock );
00270 
00271     const size_t nModels = _models.size();
00272     EQASSERT( _modelDist.size() == nModels );
00273 
00274     for( size_t i = 0; i < nModels; ++i )
00275     {
00276         const ModelDist* dist = _modelDist[ i ];
00277         if( dist->getID() == modelID )
00278             return _models[ i ];
00279     }
00280     
00281     _modelDist.push_back( new ModelDist );
00282     Model* model = _modelDist.back()->mapModel( this, modelID );
00283     EQASSERT( model );
00284     _models.push_back( model );
00285 
00286     return model;
00287 }
00288 
00289 
00290 uint32_t Config::startFrame()
00291 {
00292     // update head position
00293     if( _tracker.isRunning() )
00294     {
00295         _tracker.update();
00296         const eq::Matrix4f& headMatrix = _tracker.getMatrix();
00297         _setHeadMatrix( headMatrix );
00298     }
00299 
00300     // update database
00301     if( _animation.isValid( ))
00302     {
00303         const eq::Vector3f&  modelRotation = _animation.getModelRotation();
00304         const CameraAnimation::Step& curStep = _animation.getNextStep();
00305 
00306         _frameData.setModelRotation( modelRotation        );
00307         _frameData.setRotation(     curStep.rotation      );
00308         _frameData.setTranslation(  curStep.translation   );
00309     }
00310     else
00311     {
00312         if( _frameData.usePilotMode())
00313             _frameData.spinCamera( -0.001f * _spinX, -0.001f * _spinY );
00314         else
00315             _frameData.spinModel( -0.001f * _spinX, -0.001f * _spinY );
00316 
00317         _frameData.moveCamera( 0.0f, 0.0f, 0.001f*_advance );
00318     }
00319     const uint32_t version = _frameData.commit();
00320 
00321     _redraw = false;
00322     return eq::Config::startFrame( version );
00323 }
00324 
00325 
00326 bool Config::needsRedraw()
00327 {
00328     if( _messageTime > 0 )
00329     {
00330         if( getTime() - _messageTime > 2000 ) // reset message after two seconds
00331         {
00332             _messageTime = 0;
00333             _frameData.setMessage( "" );
00334         }
00335         return true;
00336     }
00337 
00338     return ( _spinX != 0 || _spinY != 0 || _advance != 0 ||
00339              _tracker.isRunning() || _redraw );
00340 }
00341 
00342 bool Config::handleEvent( const eq::ConfigEvent* event )
00343 {
00344     switch( event->data.type )
00345     {
00346         case eq::Event::KEY_PRESS:
00347             if( _handleKeyEvent( event->data.keyPress ))
00348             {
00349                 _redraw = true;
00350                 return true;
00351             }
00352             break;
00353 
00354         case eq::Event::POINTER_BUTTON_PRESS:
00355         {
00356             const uint32_t viewID = event->data.context.view.id;
00357             _frameData.setCurrentViewID( viewID );
00358             if( viewID == EQ_ID_INVALID )
00359             {
00360                 _currentCanvas = 0;
00361                 return true;
00362             }
00363             
00364             const eq::View* view = findView( viewID );
00365             const eq::Layout* layout = view->getLayout();
00366             const eq::CanvasVector& canvases = getCanvases();
00367             for( eq::CanvasVector::const_iterator i = canvases.begin();
00368                  i != canvases.end(); ++i )
00369             {
00370                 eq::Canvas* canvas = *i;
00371                 const eq::Layout* canvasLayout = canvas->getActiveLayout();
00372 
00373                 if( canvasLayout == layout )
00374                 {
00375                     _currentCanvas = canvas;
00376                     return true;
00377                 }
00378             }
00379             return true;
00380         }
00381 
00382         case eq::Event::POINTER_BUTTON_RELEASE:
00383         {
00384             const eq::PointerEvent& releaseEvent = 
00385                 event->data.pointerButtonRelease;
00386             if( releaseEvent.buttons == eq::PTR_BUTTON_NONE)
00387             {
00388                 if( releaseEvent.button == eq::PTR_BUTTON1 )
00389                 {
00390                     _spinX = releaseEvent.dx;
00391                     _spinY = releaseEvent.dy;
00392                     _redraw = true;
00393                     return true;
00394                 }
00395                 if( releaseEvent.button == eq::PTR_BUTTON2 )
00396                 {
00397                     _advance = -releaseEvent.dy;
00398                     _redraw = true;
00399                     return true;
00400                 }
00401             }
00402             break;
00403         }
00404         case eq::Event::POINTER_MOTION:
00405             if( event->data.pointerMotion.buttons == eq::PTR_BUTTON_NONE )
00406                 return true;
00407 
00408             if( event->data.pointerMotion.buttons == eq::PTR_BUTTON1 )
00409             {
00410                 _spinX = 0;
00411                 _spinY = 0;
00412 
00413                 if( _frameData.usePilotMode())
00414                     _frameData.spinCamera(-0.005f*event->data.pointerMotion.dx,
00415                                           -0.005f*event->data.pointerMotion.dy);
00416                 else
00417                     _frameData.spinModel( -0.005f*event->data.pointerMotion.dx,
00418                                           -0.005f*event->data.pointerMotion.dy);
00419 
00420                 _redraw = true;
00421             }
00422             else if( event->data.pointerMotion.buttons == eq::PTR_BUTTON2 )
00423             {
00424                 _advance = -event->data.pointerMotion.dy;
00425                 _frameData.moveCamera( 0.f, 0.f, .005f * _advance );
00426                 _redraw = true;
00427             }
00428             else if( event->data.pointerMotion.buttons == eq::PTR_BUTTON3 )
00429             {
00430                 _frameData.moveCamera(  .0005f * event->data.pointerMotion.dx,
00431                                        -.0005f * event->data.pointerMotion.dy,
00432                                        0.f );
00433                 _redraw = true;
00434             }
00435             return true;
00436 
00437         case eq::Event::MAGELLAN_AXIS:
00438             _spinX = 0;
00439             _spinY = 0;
00440             _advance = 0;
00441             _frameData.spinModel(  0.0001f * event->data.magellan.zRotation,
00442                                   -0.0001f * event->data.magellan.xRotation,
00443                                   -0.0001f * event->data.magellan.yRotation );
00444             _frameData.moveCamera(  0.0001f * event->data.magellan.xAxis,
00445                                    -0.0001f * event->data.magellan.zAxis,
00446                                     0.0001f * event->data.magellan.yAxis );
00447             _redraw = true;
00448             return true;
00449 
00450         case eq::Event::MAGELLAN_BUTTON:
00451             if( event->data.magellan.button == eq::PTR_BUTTON1 )
00452                 _frameData.toggleColorMode();
00453 
00454             _redraw = true;
00455             return true;
00456 
00457         case eq::Event::WINDOW_EXPOSE:
00458         case eq::Event::WINDOW_RESIZE:
00459         case eq::Event::WINDOW_CLOSE:
00460         case eq::Event::VIEW_RESIZE:
00461             _redraw = true;
00462             break;
00463 
00464         default:
00465             break;
00466     }
00467 
00468     _redraw |= eq::Config::handleEvent( event );
00469     return _redraw;
00470 }
00471 
00472 bool Config::_handleKeyEvent( const eq::KeyEvent& event )
00473 {
00474     switch( event.key )
00475     {
00476         case 'p':
00477         case 'P':
00478             _frameData.togglePilotMode();
00479             return true;
00480         case ' ':
00481             _spinX   = 0;
00482             _spinY   = 0;
00483             _advance = 0;
00484             _frameData.reset();
00485             _setHeadMatrix( eq::Matrix4f::IDENTITY );
00486             return true;
00487 
00488         case 'i':
00489         case 'I':
00490             _frameData.setCameraPosition( 0.f, 0.f, 0.f );
00491             _spinX   = 0;
00492             _spinY   = 0;
00493             _advance = 0;
00494             return true;
00495 
00496         case 'o':
00497         case 'O':
00498             _frameData.toggleOrtho();
00499             return true;
00500 
00501         case 's':
00502         case 'S':
00503             _frameData.toggleStatistics();
00504             return true;
00505             
00506         case 'f':
00507         case 'F':
00508             _freeze = !_freeze;
00509             freezeLoadBalancing( _freeze );
00510             return true;
00511 
00512         case eq::KC_F1:
00513         case 'h':
00514         case 'H':
00515             _frameData.toggleHelp();
00516             return true;
00517 
00518         case 'd':
00519         case 'D':
00520             _frameData.toggleColorMode();
00521             return true;
00522 
00523         case 'c':
00524         case 'C':
00525         {
00526             const eq::CanvasVector& canvases = getCanvases();
00527             if( canvases.empty( ))
00528                 return true;
00529 
00530             _frameData.setCurrentViewID( EQ_ID_INVALID );
00531 
00532             if( !_currentCanvas )
00533             {
00534                 _currentCanvas = canvases.front();
00535                 return true;
00536             }
00537 
00538             eq::CanvasVector::const_iterator i = std::find( canvases.begin(),
00539                                                             canvases.end(), 
00540                                                             _currentCanvas );
00541             EQASSERT( i != canvases.end( ));
00542 
00543             ++i;
00544             if( i == canvases.end( ))
00545                 _currentCanvas = canvases.front();
00546             else
00547                 _currentCanvas = *i;
00548             return true;
00549         }
00550 
00551         case 'v':
00552         case 'V':
00553         {
00554             const eq::CanvasVector& canvases = getCanvases();
00555             if( !_currentCanvas && !canvases.empty( ))
00556                 _currentCanvas = canvases.front();
00557 
00558             if( !_currentCanvas )
00559                 return true;
00560 
00561             const eq::Layout* layout = _currentCanvas->getActiveLayout();
00562             if( !layout )
00563                 return true;
00564 
00565             const eq::View* current = findView( _frameData.getCurrentViewID( ));
00566             const eq::ViewVector& views = layout->getViews();
00567             EQASSERT( !views.empty( ))
00568 
00569             if( !current )
00570             {
00571                 _frameData.setCurrentViewID( views.front()->getID( ));
00572                 return true;
00573             }
00574 
00575             eq::ViewVector::const_iterator i = std::find( views.begin(),
00576                                                           views.end(), current);
00577             EQASSERT( i != views.end( ));
00578 
00579             ++i;
00580             if( i == views.end( ))
00581                 _frameData.setCurrentViewID( EQ_ID_INVALID );
00582             else
00583                 _frameData.setCurrentViewID( (*i)->getID( ));
00584             return true;
00585         }
00586 
00587         case 'm':
00588         case 'M':
00589         {
00590             if( _modelDist.empty( )) // no models
00591                 return true;
00592 
00593             // current model
00594             const uint32_t viewID = _frameData.getCurrentViewID();
00595             View* view = static_cast< View* >( findView( viewID ));
00596             const uint32_t currentID = view ? 
00597                 view->getModelID() : _frameData.getModelID();
00598 
00599             // next model
00600             ModelDistVector::const_iterator i;
00601             for( i = _modelDist.begin(); i != _modelDist.end(); ++i )
00602             {
00603                 if( (*i)->getID() != currentID )
00604                     continue;
00605                 
00606                 ++i;
00607                 break;
00608             }
00609             if( i == _modelDist.end( ))
00610                 i = _modelDist.begin(); // wrap around
00611             
00612             // set identifier on view or frame data (default model)
00613             const uint32_t modelID = (*i)->getID();
00614             if( view )
00615                 view->setModelID( modelID );
00616             else
00617                 _frameData.setModelID( modelID );
00618             
00619             if( view )
00620             {
00621                 const Model* model = getModel( modelID );
00622                 _setMessage( "Model " + eq::base::getFilename( model->getName( ))
00623                              + " active" );
00624             }
00625             return true;
00626         }
00627 
00628         case 'l':
00629         case 'L':
00630         {
00631             if( !_currentCanvas )
00632                 return true;
00633 
00634             _frameData.setCurrentViewID( EQ_ID_INVALID );
00635 
00636             uint32_t index = _currentCanvas->getActiveLayoutIndex() + 1;
00637             const eq::LayoutVector& layouts = _currentCanvas->getLayouts();
00638             EQASSERT( !layouts.empty( ))
00639 
00640             if( index >= layouts.size( ))
00641                 index = 0;
00642 
00643             _currentCanvas->useLayout( index );
00644             
00645             const eq::Layout* layout = _currentCanvas->getLayouts()[index];
00646             std::ostringstream stream;
00647             stream << "Layout ";
00648             if( layout )
00649             {
00650                 const std::string& name = layout->getName();
00651                 if( name.empty( ))
00652                     stream << index;
00653                 else
00654                     stream << name;
00655             }
00656             else
00657                 stream << "NONE";
00658             
00659             stream << " active";
00660             _setMessage( stream.str( ));
00661             return true;
00662         }
00663 
00664         case 'w':
00665         case 'W':
00666             _frameData.toggleWireframe();
00667             return true;
00668 
00669         case 'r':
00670         case 'R':
00671             _frameData.toggleRenderMode();
00672             return true;
00673 
00674         // Head Tracking Emulation
00675         case eq::KC_UP:
00676         {
00677             eq::Matrix4f headMatrix = _getHeadMatrix();
00678             headMatrix.y() += 0.1f;
00679             _setHeadMatrix( headMatrix );
00680             return true;
00681         }
00682         case eq::KC_DOWN:
00683         {
00684             eq::Matrix4f headMatrix = _getHeadMatrix();
00685             headMatrix.y() -= 0.1f;
00686             _setHeadMatrix( headMatrix );
00687             return true;
00688         }
00689         case eq::KC_RIGHT:
00690         {
00691             eq::Matrix4f headMatrix = _getHeadMatrix();
00692             headMatrix.x() += 0.1f;
00693             _setHeadMatrix( headMatrix );
00694             return true;
00695         }
00696         case eq::KC_LEFT:
00697         {
00698             eq::Matrix4f headMatrix = _getHeadMatrix();
00699             headMatrix.x() -= 0.1f;
00700             _setHeadMatrix( headMatrix );
00701             return true;
00702         }
00703         case eq::KC_PAGE_DOWN:
00704         {
00705             eq::Matrix4f headMatrix = _getHeadMatrix();
00706             headMatrix.z() += 0.1f;
00707             _setHeadMatrix( headMatrix );
00708             return true;
00709         }
00710         case eq::KC_PAGE_UP:
00711         {
00712             eq::Matrix4f headMatrix = _getHeadMatrix();
00713             headMatrix.z() -= 0.1f;
00714             _setHeadMatrix( headMatrix );
00715             return true;
00716         }
00717         case '.':
00718         {
00719             eq::Matrix4f headMatrix = _getHeadMatrix();
00720             headMatrix.pre_rotate_x( .1f );
00721             _setHeadMatrix( headMatrix );
00722             return true;
00723         }
00724         case ',':
00725         {
00726             eq::Matrix4f headMatrix = _getHeadMatrix();
00727             headMatrix.pre_rotate_x( -.1f );
00728             _setHeadMatrix( headMatrix );
00729             return true;
00730         }
00731         case ';':
00732         {
00733             eq::Matrix4f headMatrix = _getHeadMatrix();
00734             headMatrix.pre_rotate_y( .1f );
00735             _setHeadMatrix( headMatrix );
00736             return true;
00737         }
00738         case '\'':
00739         {
00740             eq::Matrix4f headMatrix = _getHeadMatrix();
00741             headMatrix.pre_rotate_y( -.1f );
00742             _setHeadMatrix( headMatrix );
00743             return true;
00744         }
00745         case '[':
00746         {
00747             eq::Matrix4f headMatrix = _getHeadMatrix();
00748             headMatrix.pre_rotate_z( -.1f );
00749             _setHeadMatrix( headMatrix );
00750             return true;
00751         }
00752         case ']':
00753         {
00754             eq::Matrix4f headMatrix = _getHeadMatrix();
00755             headMatrix.pre_rotate_z( .1f );
00756             _setHeadMatrix( headMatrix );
00757             return true;
00758         }
00759 
00760         default:
00761             return false;
00762     }
00763 }
00764 
00765 // Note: real applications would use one tracking device per observer
00766 void Config::_setHeadMatrix( const eq::Matrix4f& matrix )
00767 {
00768     const eq::ObserverVector& observers = getObservers();
00769     for( eq::ObserverVector::const_iterator i = observers.begin();
00770          i != observers.end(); ++i )
00771     {
00772         (*i)->setHeadMatrix( matrix );
00773     }
00774 }
00775 
00776 const eq::Matrix4f& Config::_getHeadMatrix() const
00777 {
00778     const eq::ObserverVector& observers = getObservers();
00779     if( observers.empty( ))
00780         return eq::Matrix4f::IDENTITY;
00781 
00782     return observers[0]->getHeadMatrix();
00783 }
00784 
00785 void Config::_setMessage( const std::string& message )
00786 {
00787     _frameData.setMessage( message );
00788     _messageTime = getTime();
00789 }
00790 
00791 }
Generated on Mon Aug 10 18:58:32 2009 for Equalizer 0.9 by  doxygen 1.5.8