Equalizer  1.6.1
eqPly/config.cpp
1 
2 /* Copyright (c) 2006-2013, Stefan Eilemann <eile@equalizergraphics.com>
3  * 2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
4  * 2010, Cedric Stalder <cedric.stalder@gmail.com>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * - Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * - Neither the name of Eyescale Software GmbH nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "configEvent.h"
33 #include "view.h"
34 #include "modelAssigner.h"
35 
36 #include <admin/addWindow.h>
37 #include <admin/removeWindow.h>
38 
39 namespace eqPly
40 {
41 
42 Config::Config( eq::ServerPtr parent )
43  : eq::Config( parent )
44  , _spinX( 5 )
45  , _spinY( 5 )
46  , _advance( 0 )
47  , _currentCanvas( 0 )
48  , _messageTime( 0 )
49  , _redraw( true )
50  , _useIdleAA( true )
51  , _numFramesAA( 0 )
52 {
53 }
54 
56 {
57  for( ModelsCIter i = _models.begin(); i != _models.end(); ++i )
58  delete *i;
59  _models.clear();
60 
61  for( ModelDistsCIter i = _modelDist.begin(); i != _modelDist.end(); ++i )
62  {
63  LBASSERT( !(*i)->isAttached() );
64  delete *i;
65  }
66  _modelDist.clear();
67 }
68 
70 {
71  if( !_animation.isValid( ))
72  _animation.loadAnimation( _initData.getPathFilename( ));
73 
74  // init distributed objects
75  if( !_initData.useColor( ))
76  _frameData.setColorMode( COLOR_WHITE );
77 
78  _frameData.setRenderMode( _initData.getRenderMode( ));
79  registerObject( &_frameData );
80  _frameData.setAutoObsolete( getLatency( ));
81 
82  _initData.setFrameDataID( _frameData.getID( ));
83  registerObject( &_initData );
84 
85  // init config
86  if( !eq::Config::init( _initData.getID( )))
87  {
88  _deregisterData();
89  return false;
90  }
91 
92  _loadModels();
93  _registerModels();
94 
95  const eq::Canvases& canvases = getCanvases();
96  if( canvases.empty( ))
97  _currentCanvas = 0;
98  else
99  _currentCanvas = canvases.front();
100 
101  _setMessage( "Welcome to eqPly\nPress F1 for help" );
102  return true;
103 }
104 
106 {
107  const bool ret = eq::Config::exit();
108  _deregisterData();
109  _closeAdminServer();
110 
111  // retain model & distributors for possible other config runs, dtor deletes
112  return ret;
113 }
114 
115 namespace
116 {
117 static bool _isPlyfile( const std::string& filename )
118 {
119  const size_t size = filename.length();
120  if( size < 5 )
121  return false;
122 
123  if( filename[size-4] != '.' || filename[size-3] != 'p' ||
124  filename[size-2] != 'l' || filename[size-1] != 'y' )
125  {
126  return false;
127  }
128  return true;
129 }
130 }
131 
132 void Config::_loadModels()
133 {
134  if( !_models.empty( )) // only load on the first config run
135  return;
136 
137  eq::Strings filenames = _initData.getFilenames();
138  while( !filenames.empty( ))
139  {
140  const std::string filename = filenames.back();
141  filenames.pop_back();
142 
143  if( _isPlyfile( filename ))
144  {
145  Model* model = new Model;
146 
147  if( _initData.useInvertedFaces() )
148  model->useInvertedFaces();
149 
150  if( !model->readFromFile( filename.c_str( )))
151  {
152  LBWARN << "Can't load model: " << filename << std::endl;
153  delete model;
154  }
155  else
156  _models.push_back( model );
157  }
158  else
159  {
160  const std::string basename = lunchbox::getFilename( filename );
161  if( basename == "." || basename == ".." )
162  continue;
163 
164  // recursively search directories
165  const eq::Strings subFiles = lunchbox::searchDirectory( filename,
166  ".*" );
167  for(eq::StringsCIter i = subFiles.begin(); i != subFiles.end(); ++i)
168  filenames.push_back( filename + '/' + *i );
169  }
170  }
171 }
172 
173 void Config::_registerModels()
174 {
175  // Register distribution helpers on each config run
176  const bool createDist = _modelDist.empty(); //first run, create distributors
177  const size_t nModels = _models.size();
178  LBASSERT( createDist || _modelDist.size() == nModels );
179 
180  for( size_t i = 0; i < nModels; ++i )
181  {
182  const Model* model = _models[i];
183  ModelDist* modelDist = 0;
184  if( createDist )
185  {
186  modelDist = new ModelDist( model );
187  _modelDist.push_back( modelDist );
188  }
189  else
190  modelDist = _modelDist[i];
191 
192  modelDist->registerTree( getClient( ));
193  LBASSERT( modelDist->isAttached() );
194 
195  _frameData.setModelID( modelDist->getID( ));
196  }
197 
198  LBASSERT( _modelDist.size() == nModels );
199 
200  if( !_modelDist.empty( ))
201  {
202  ModelAssigner assigner( _modelDist );
203  accept( assigner );
204  }
205 }
206 
207 void Config::_deregisterData()
208 {
209  for( ModelDistsCIter i = _modelDist.begin(); i != _modelDist.end(); ++i )
210  {
211  ModelDist* modelDist = *i;
212  if( !modelDist->isAttached() ) // already done
213  continue;
214 
215  LBASSERT( modelDist->isMaster( ));
216  modelDist->deregisterTree();
217  }
218 
219  deregisterObject( &_initData );
220  deregisterObject( &_frameData );
221 
222  _initData.setFrameDataID( eq::UUID( ));
223  _frameData.setModelID( eq::UUID( ));
224 }
225 
226 bool Config::loadData( const eq::uint128_t& initDataID )
227 {
228  if( !_initData.isAttached( ))
229  {
230  const uint32_t request = mapObjectNB( &_initData, initDataID,
231  co::VERSION_OLDEST,
232  getApplicationNode( ));
233  if( !mapObjectSync( request ))
234  return false;
235  unmapObject( &_initData ); // data was retrieved, unmap immediately
236  }
237  else // appNode, _initData is registered already
238  {
239  LBASSERT( _initData.getID() == initDataID );
240  }
241  return true;
242 }
243 
244 const Model* Config::getModel( const eq::uint128_t& modelID )
245 {
246  if( modelID == 0 )
247  return 0;
248 
249  // Protect if accessed concurrently from multiple pipe threads
250  const eq::Node* node = getNodes().front();
251  const bool needModelLock = (node->getPipes().size() > 1);
252  lunchbox::ScopedWrite _mutex( needModelLock ? &_modelLock : 0 );
253 
254  const size_t nModels = _models.size();
255  LBASSERT( _modelDist.size() == nModels );
256 
257  for( size_t i = 0; i < nModels; ++i )
258  {
259  const ModelDist* dist = _modelDist[ i ];
260  if( dist->getID() == modelID )
261  return _models[ i ];
262  }
263 
264  _modelDist.push_back( new ModelDist );
265  Model* model = _modelDist.back()->loadModel( getApplicationNode(),
266  getClient(), modelID );
267  LBASSERT( model );
268  _models.push_back( model );
269 
270  return model;
271 }
272 
274 {
275  _updateData();
276  const eq::uint128_t& version = _frameData.commit();
277 
278  _redraw = false;
279  return eq::Config::startFrame( version );
280 }
281 
282 void Config::_updateData()
283 {
284  // update camera
285  if( _animation.isValid( ))
286  {
287  const eq::Vector3f& modelRotation = _animation.getModelRotation();
288  const CameraAnimation::Step& curStep = _animation.getNextStep();
289 
290  _frameData.setModelRotation( modelRotation);
291  _frameData.setRotation( curStep.rotation );
292  _frameData.setCameraPosition( curStep.position );
293  }
294  else
295  {
296  if( _frameData.usePilotMode())
297  _frameData.spinCamera( -0.001f * _spinX, -0.001f * _spinY );
298  else
299  _frameData.spinModel( -0.001f * _spinX, -0.001f * _spinY, 0.f );
300 
301  _frameData.moveCamera( 0.0f, 0.0f, 0.001f * _advance );
302  }
303 
304  // idle mode
305  if( isIdleAA( ))
306  {
307  LBASSERT( _numFramesAA > 0 );
308  _frameData.setIdle( true );
309  }
310  else
311  _frameData.setIdle( false );
312 
313  _numFramesAA = 0;
314 }
315 
316 bool Config::isIdleAA()
317 {
318  return ( !_needNewFrame() && _numFramesAA > 0 );
319 }
320 
321 bool Config::needRedraw()
322 {
323  return( _needNewFrame() || _numFramesAA > 0 );
324 }
325 
326 uint32_t Config::getAnimationFrame()
327 {
328  return _animation.getCurrentFrame();
329 }
330 
331 bool Config::_needNewFrame()
332 {
333  if( _messageTime > 0 )
334  {
335  if( getTime() - _messageTime > 2000 ) // reset message after two seconds
336  {
337  _messageTime = 0;
338  _frameData.setMessage( "" );
339  }
340  return true;
341  }
342 
343  return ( _spinX != 0 || _spinY != 0 || _advance != 0 || _redraw );
344 }
345 
347 {
348  switch( event->data.type )
349  {
351  {
352  if( _handleKeyEvent( event->data.keyPress ))
353  {
354  _redraw = true;
355  return true;
356  }
357  break;
358  }
359 
361  {
362  const eq::uint128_t& viewID = event->data.context.view.identifier;
363  _frameData.setCurrentViewID( viewID );
364  if( viewID == 0 )
365  {
366  _currentCanvas = 0;
367  return false;
368  }
369 
370  const View* view = _getCurrentView();
371  const eq::Layout* layout = view->getLayout();
372  const eq::Canvases& canvases = getCanvases();
373  for( eq::CanvasesCIter i = canvases.begin();
374  i != canvases.end(); ++i )
375  {
376  eq::Canvas* canvas = *i;
377  const eq::Layout* canvasLayout = canvas->getActiveLayout();
378 
379  if( canvasLayout == layout )
380  {
381  _currentCanvas = canvas;
382  return true;
383  }
384  }
385  return true;
386  }
387 
389  {
390  const eq::PointerEvent& releaseEvent =
391  event->data.pointerButtonRelease;
392  if( releaseEvent.buttons == eq::PTR_BUTTON_NONE)
393  {
394  if( releaseEvent.button == eq::PTR_BUTTON1 )
395  {
396  _spinX = releaseEvent.dy;
397  _spinY = releaseEvent.dx;
398  _redraw = true;
399  return true;
400  }
401  if( releaseEvent.button == eq::PTR_BUTTON2 )
402  {
403  _advance = -releaseEvent.dy;
404  _redraw = true;
405  return true;
406  }
407  }
408  break;
409  }
410  case eq::Event::CHANNEL_POINTER_MOTION:
411  {
412  switch( event->data.pointerMotion.buttons )
413  {
414  case eq::PTR_BUTTON1:
415  _spinX = 0;
416  _spinY = 0;
417 
418  if( _frameData.usePilotMode())
419  _frameData.spinCamera(
420  -0.005f * event->data.pointerMotion.dy,
421  -0.005f * event->data.pointerMotion.dx );
422  else
423  _frameData.spinModel(
424  -0.005f * event->data.pointerMotion.dy,
425  -0.005f * event->data.pointerMotion.dx, 0.f );
426  _redraw = true;
427  return true;
428 
429  case eq::PTR_BUTTON2:
430  _advance = -event->data.pointerMotion.dy;
431  _frameData.moveCamera( 0.f, 0.f, .005f * _advance );
432  _redraw = true;
433  return true;
434 
435  case eq::PTR_BUTTON3:
436  _frameData.moveCamera( .0005f * event->data.pointerMotion.dx,
437  -.0005f * event->data.pointerMotion.dy,
438  0.f );
439  _redraw = true;
440  return true;
441  }
442  break;
443  }
444 
446  {
447  _frameData.moveCamera( -0.05f * event->data.pointerWheel.yAxis,
448  0.f,
449  0.05f * event->data.pointerWheel.xAxis );
450  _redraw = true;
451  return true;
452  }
453 
455  {
456  _spinX = 0;
457  _spinY = 0;
458  _advance = 0;
459  _frameData.spinModel( 0.0001f * event->data.magellan.xRotation,
460  0.0001f * event->data.magellan.yRotation,
461  0.0001f * event->data.magellan.zRotation );
462  _frameData.moveCamera( 0.0001f * event->data.magellan.xAxis,
463  0.0001f * event->data.magellan.yAxis,
464  0.0001f * event->data.magellan.zAxis );
465  _redraw = true;
466  return true;
467  }
468 
470  {
471  if( event->data.magellan.button == eq::PTR_BUTTON1 )
472  _frameData.toggleColorMode();
473 
474  _redraw = true;
475  return true;
476  }
477 
482  _redraw = true;
483  break;
484 
485  default:
486  break;
487  }
488 
489  _redraw |= eq::Config::handleEvent( event );
490  return _redraw;
491 }
492 
494 {
495  switch( command.getEventType( ))
496  {
497  case IDLE_AA_LEFT:
498  if( _useIdleAA )
499  {
500  const int32_t steps = command.get< int32_t >();
501  _numFramesAA = LB_MAX( _numFramesAA, steps );
502  }
503  else
504  _numFramesAA = 0;
505  return false;
506 
507  default:
508  break;
509  }
510 
511  _redraw |= eq::Config::handleEvent( command );
512  return _redraw;
513 }
514 
515 bool Config::_handleKeyEvent( const eq::KeyEvent& event )
516 {
517  switch( event.key )
518  {
519  case 'z':
520  _adjustEyeBase( -0.1f );
521  return true;
522  case 'Z':
523  _adjustEyeBase( 0.1f );
524  return true;
525  case 'y':
526  _adjustModelScale( 0.1f );
527  return true;
528  case 'Y':
529  _adjustModelScale( 10.0f );
530  return true;
531  case 't':
532  _adjustTileSize( -1 );
533  return true;
534  case 'T':
535  _adjustTileSize( 1 );
536  return true;
537  case 'u':
538  _frameData.toggleCompression();
539  return true;
540 
541  case 'n':
542  case 'N':
543  _frameData.togglePilotMode();
544  return true;
545  case ' ':
546  stopFrames();
547  _spinX = 0;
548  _spinY = 0;
549  _advance = 0;
550  _frameData.reset();
551  _setHeadMatrix( eq::Matrix4f::IDENTITY );
552  return true;
553 
554  case 'i':
555  _useIdleAA = !_useIdleAA;
556  return true;
557 
558  case 'k':
559  {
560  lunchbox::RNG rng;
561  if( rng.get< bool >( ))
562  _frameData.toggleOrtho();
563  if( rng.get< bool >( ))
564  _frameData.toggleStatistics();
565  if( rng.get< bool >( ))
566  _switchCanvas();
567  if( rng.get< bool >( ))
568  _switchView();
569  if( rng.get< bool >( ))
570  _switchLayout( 1 );
571  if( rng.get< bool >( ))
572  _switchModel();
573  if( rng.get< bool >( ))
574  eqAdmin::addWindow( _getAdminServer(), rng.get< bool >( ));
575  if( rng.get< bool >( ))
576  {
577  eqAdmin::removeWindow( _getAdminServer( ));
578  _currentCanvas = 0;
579  }
580  if( rng.get< bool >( ))
581  _switchViewMode();
582  return true;
583  }
584 
585  case 'o':
586  case 'O':
587  _frameData.toggleOrtho();
588  return true;
589 
590  case 's':
591  case 'S':
592  _frameData.toggleStatistics();
593  return true;
594 
595  case 'f':
596  _freezeLoadBalancing( true );
597  return true;
598 
599  case 'F':
600  _freezeLoadBalancing( false );
601  return true;
602 
603  case eq::KC_F1:
604  case 'h':
605  case 'H':
606  _frameData.toggleHelp();
607  return true;
608 
609  case 'd':
610  case 'D':
611  _frameData.toggleColorMode();
612  return true;
613 
614  case 'q':
615  _frameData.adjustQuality( -.1f );
616  return true;
617 
618  case 'Q':
619  _frameData.adjustQuality( .1f );
620  return true;
621 
622  case 'c':
623  case 'C':
624  _switchCanvas();
625  return true;
626 
627  case 'v':
628  case 'V':
629  _switchView();
630  return true;
631 
632  case 'm':
633  case 'M':
634  _switchModel();
635  return true;
636 
637  case 'l':
638  _switchLayout( 1 );
639  return true;
640  case 'L':
641  _switchLayout( -1 );
642  return true;
643 
644  case 'w':
645  case 'W':
646  _frameData.toggleWireframe();
647  return true;
648 
649  case 'r':
650  case 'R':
651  _frameData.toggleRenderMode();
652  return true;
653  case 'g':
654  case 'G':
655  _switchViewMode();
656  return true;
657  case 'a':
658  eqAdmin::addWindow( _getAdminServer(), false /* active stereo */ );
659  return true;
660  case 'p':
661  eqAdmin::addWindow( _getAdminServer(), true /* passive stereo */ );
662  return true;
663  case 'x':
664  eqAdmin::removeWindow( _getAdminServer( ));
665  _currentCanvas = 0;
666  LBASSERT( update() );
667  return false;
668 
669  // Head Tracking Emulation
670  case eq::KC_UP:
671  {
672  eq::Matrix4f headMatrix = _getHeadMatrix();
673  headMatrix.y() += 0.1f;
674  _setHeadMatrix( headMatrix );
675  return true;
676  }
677  case eq::KC_DOWN:
678  {
679  eq::Matrix4f headMatrix = _getHeadMatrix();
680  headMatrix.y() -= 0.1f;
681  _setHeadMatrix( headMatrix );
682  return true;
683  }
684  case eq::KC_RIGHT:
685  {
686  eq::Matrix4f headMatrix = _getHeadMatrix();
687  headMatrix.x() += 0.1f;
688  _setHeadMatrix( headMatrix );
689  return true;
690  }
691  case eq::KC_LEFT:
692  {
693  eq::Matrix4f headMatrix = _getHeadMatrix();
694  headMatrix.x() -= 0.1f;
695  _setHeadMatrix( headMatrix );
696  return true;
697  }
698  case eq::KC_PAGE_DOWN:
699  {
700  eq::Matrix4f headMatrix = _getHeadMatrix();
701  headMatrix.z() += 0.1f;
702  _setHeadMatrix( headMatrix );
703  return true;
704  }
705  case eq::KC_PAGE_UP:
706  {
707  eq::Matrix4f headMatrix = _getHeadMatrix();
708  headMatrix.z() -= 0.1f;
709  _setHeadMatrix( headMatrix );
710  return true;
711  }
712  case '.':
713  {
714  eq::Matrix4f headMatrix = _getHeadMatrix();
715  headMatrix.pre_rotate_x( .1f );
716  _setHeadMatrix( headMatrix );
717  return true;
718  }
719  case ',':
720  {
721  eq::Matrix4f headMatrix = _getHeadMatrix();
722  headMatrix.pre_rotate_x( -.1f );
723  _setHeadMatrix( headMatrix );
724  return true;
725  }
726  case ';':
727  {
728  eq::Matrix4f headMatrix = _getHeadMatrix();
729  headMatrix.pre_rotate_y( .1f );
730  _setHeadMatrix( headMatrix );
731  return true;
732  }
733  case '\'':
734  {
735  eq::Matrix4f headMatrix = _getHeadMatrix();
736  headMatrix.pre_rotate_y( -.1f );
737  _setHeadMatrix( headMatrix );
738  return true;
739  }
740  case '[':
741  {
742  eq::Matrix4f headMatrix = _getHeadMatrix();
743  headMatrix.pre_rotate_z( -.1f );
744  _setHeadMatrix( headMatrix );
745  return true;
746  }
747  case ']':
748  {
749  eq::Matrix4f headMatrix = _getHeadMatrix();
750  headMatrix.pre_rotate_z( .1f );
751  _setHeadMatrix( headMatrix );
752  return true;
753  }
754 
755  case '+':
756  _changeFocusDistance( .1f );
757  return true;
758 
759  case '-':
760  _changeFocusDistance( -.1f );
761  return true;
762 
763  case '1':
764  _setFocusMode( eq::FOCUSMODE_FIXED );
765  return true;
766 
767  case '2':
768  _setFocusMode( eq::FOCUSMODE_RELATIVE_TO_ORIGIN );
769  return true;
770 
771  case '3':
772  _setFocusMode( eq::FOCUSMODE_RELATIVE_TO_OBSERVER );
773  return true;
774 
775  case '4':
776  _adjustResistance( 1 );
777  return true;
778 
779  case '5':
780  _adjustResistance( -1 );
781  return true;
782 
783  case 'j':
784  stopFrames();
785  return true;
786 
787  case 'e':
788  _toggleEqualizer();
789  return true;
790 
791  default:
792  return false;
793  }
794 }
795 
796 co::uint128_t Config::sync( const co::uint128_t& version )
797 {
798  if( _admin.isValid() && _admin->isConnected( ))
799  _admin->syncConfig( getID(), version );
800 
801  return eq::Config::sync( version );
802 }
803 
804 void Config::_switchCanvas()
805 {
806  const eq::Canvases& canvases = getCanvases();
807  if( canvases.empty( ))
808  return;
809 
810  _frameData.setCurrentViewID( eq::UUID( ));
811 
812  if( !_currentCanvas )
813  {
814  _currentCanvas = canvases.front();
815  return;
816  }
817 
818  eq::CanvasesCIter i = stde::find( canvases, _currentCanvas );
819  LBASSERT( i != canvases.end( ));
820 
821  ++i;
822  if( i == canvases.end( ))
823  _currentCanvas = canvases.front();
824  else
825  _currentCanvas = *i;
826  _switchView(); // activate first view on canvas
827 }
828 
829 void Config::_switchView()
830 {
831  const eq::Canvases& canvases = getCanvases();
832  if( !_currentCanvas && !canvases.empty( ))
833  _currentCanvas = canvases.front();
834 
835  if( !_currentCanvas )
836  return;
837 
838  const eq::Layout* layout = _currentCanvas->getActiveLayout();
839  if( !layout )
840  return;
841 
842  const View* view = _getCurrentView();
843  const eq::Views& views = layout->getViews();
844  LBASSERT( !views.empty( ));
845 
846  if( !view )
847  {
848  _frameData.setCurrentViewID( views.front()->getID( ));
849  return;
850  }
851 
852  eq::ViewsCIter i = std::find( views.begin(), views.end(), view );
853  if( i != views.end( ))
854  ++i;
855  if( i == views.end( ))
856  _frameData.setCurrentViewID( eq::UUID( ));
857  else
858  _frameData.setCurrentViewID( (*i)->getID( ));
859 }
860 
861 void Config::_switchModel()
862 {
863  if( _modelDist.empty( )) // no models
864  return;
865 
866  // current model of current view
867  View* view = _getCurrentView();
868  const eq::uint128_t& currentID = view ? view->getModelID() :
869  _frameData.getModelID();
870  // next model
871  ModelDistsCIter i;
872  for( i = _modelDist.begin(); i != _modelDist.end(); ++i )
873  {
874  if( (*i)->getID() != currentID )
875  continue;
876 
877  ++i;
878  break;
879  }
880  if( i == _modelDist.end( ))
881  i = _modelDist.begin(); // wrap around
882 
883  // set identifier on view or frame data (default model)
884  const eq::uint128_t& modelID = (*i)->getID();
885  if( view )
886  view->setModelID( modelID );
887  else
888  _frameData.setModelID( modelID );
889 
890  if( view )
891  {
892  const Model* model = getModel( modelID );
893  _setMessage( "Using " + lunchbox::getFilename( model->getName( )));
894  }
895 }
896 
897 void Config::_switchViewMode()
898 {
899  View* view = _getCurrentView();
900  if( !view )
901  return;
902 
903  const eq::View::Mode mode = view->getMode();
904  if( mode == eq::View::MODE_MONO )
905  {
906  view->changeMode( eq::View::MODE_STEREO );
907  _setMessage( "Switched to stereoscopic rendering" );
908  }
909  else
910  {
911  view->changeMode( eq::View::MODE_MONO );
912  _setMessage( "Switched to monoscopic rendering" );
913  }
914 }
915 
916 void Config::_freezeLoadBalancing( const bool onOff )
917 {
918  View* view = _getCurrentView();
919  if ( view )
920  view->getEqualizer().setFrozen( onOff );
921 }
922 
923 void Config::_adjustEyeBase( const float delta )
924 {
925  const eq::Observers& observers = getObservers();
926  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
927  {
928  eq::Observer* observer = *i;
929  observer->setEyePosition( eq::EYE_LEFT,
930  observer->getEyePosition( eq::EYE_LEFT ) +
931  eq::Vector3f( -delta, 0.f, 0.f ));
932  observer->setEyePosition( eq::EYE_RIGHT,
933  observer->getEyePosition( eq::EYE_RIGHT ) +
934  eq::Vector3f( delta, 0.f, 0.f ));
935  std::ostringstream stream;
936  stream << "Set eyes to " << observer->getEyePosition( eq::EYE_LEFT )
937  << ", " << observer->getEyePosition( eq::EYE_RIGHT );
938  _setMessage( stream.str( ));
939  }
940 }
941 
942 void Config::_adjustTileSize( const int delta )
943 {
944  View* view = _getCurrentView();
945  if( !view )
946  return;
947 
948  eq::Vector2i tileSize = view->getEqualizer().getTileSize();
949  if( tileSize == eq::Vector2i( -1, -1 ) )
950  tileSize = eq::Vector2i( 64, 64 );
951  tileSize += delta;
952  view->getEqualizer().setTileSize( tileSize );
953 }
954 
955 void Config::_adjustResistance( const int delta )
956 {
957  View* view = _getCurrentView();
958  if( !view )
959  return;
960 
961  eq::Vector2i size = view->getEqualizer().getResistance2i();
962  size += delta;
963  size.x() = LB_MAX( size.x(), 0 );
964  size.y() = LB_MAX( size.y(), 0 );
965  std::ostringstream stream;
966  stream << "Set load equalizer resistance to " << size;
967  _setMessage( stream.str( ));
968  view->getEqualizer().setResistance( size );
969 }
970 
971 void Config::_adjustModelScale( const float factor )
972 {
973  View* view = _getCurrentView();
974  if( !view )
975  return;
976 
977  const float current = view->getModelUnit() * factor;
978  if( current > std::numeric_limits<float>::epsilon( ))
979  view->setModelUnit( current );
980 
981  std::ostringstream stream;
982  stream << "Set model unit to " << view->getModelUnit();
983  _setMessage( stream.str( ));
984 }
985 
986 void Config::_switchLayout( int32_t increment )
987 {
988  if( !_currentCanvas )
989  return;
990 
991  _frameData.setCurrentViewID( eq::UUID( ));
992 
993  int64_t index = _currentCanvas->getActiveLayoutIndex() + increment;
994  const eq::Layouts& layouts = _currentCanvas->getLayouts();
995  LBASSERT( !layouts.empty( ));
996 
997  index = ( index % layouts.size( ));
998  _currentCanvas->useLayout( uint32_t( index ));
999 
1000  const eq::Layout* layout = layouts[index];
1001  std::ostringstream stream;
1002  stream << "Layout ";
1003  if( layout )
1004  {
1005  const std::string& name = layout->getName();
1006  if( name.empty( ))
1007  stream << index;
1008  else
1009  stream << name;
1010  }
1011  else
1012  stream << "NONE";
1013 
1014  stream << " active";
1015  _setMessage( stream.str( ));
1016 }
1017 
1018 void Config::_toggleEqualizer()
1019 {
1020  View* view = _getCurrentView();
1021  if ( view )
1022  view->toggleEqualizer();
1023 }
1024 
1025 // Note: real applications would use one tracking device per observer
1026 void Config::_setHeadMatrix( const eq::Matrix4f& matrix )
1027 {
1028  const eq::Observers& observers = getObservers();
1029  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1030  {
1031  (*i)->setHeadMatrix( matrix );
1032  }
1033 
1034  eq::Vector3f trans;
1035  matrix.get_translation( trans );
1036  std::ostringstream stream;
1037  stream << "Observer at " << trans;
1038  _setMessage( stream.str( ));
1039 }
1040 
1041 const eq::Matrix4f& Config::_getHeadMatrix() const
1042 {
1043  const eq::Observers& observers = getObservers();
1044  if( observers.empty( ))
1045  return eq::Matrix4f::IDENTITY;
1046 
1047  return observers[0]->getHeadMatrix();
1048 }
1049 
1050 void Config::_changeFocusDistance( const float delta )
1051 {
1052  const eq::Observers& observers = getObservers();
1053  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1054  {
1055  eq::Observer* observer = *i;
1056  observer->setFocusDistance( observer->getFocusDistance() + delta );
1057  std::ostringstream stream;
1058  stream << "Set focus distance to " << observer->getFocusDistance();
1059  _setMessage( stream.str( ));
1060  }
1061 }
1062 
1063 void Config::_setFocusMode( const eq::FocusMode mode )
1064 {
1065  const eq::Observers& observers = getObservers();
1066  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1067  (*i)->setFocusMode( mode );
1068 
1069  std::ostringstream stream;
1070  stream << "Set focus mode to " << mode;
1071  _setMessage( stream.str( ));
1072 }
1073 
1074 void Config::_setMessage( const std::string& message )
1075 {
1076  _frameData.setMessage( message );
1077  _messageTime = getTime();
1078 }
1079 
1080 eq::admin::ServerPtr Config::_getAdminServer()
1081 {
1082  // Debug: _closeAdminServer();
1083  if( _admin.isValid() && _admin->isConnected( ))
1084  return _admin;
1085 
1086  eq::admin::init( 0, 0 );
1087  eq::admin::ClientPtr client = new eq::admin::Client;
1088  if( !client->initLocal( 0, 0 ))
1089  {
1090  _setMessage( "Can't init admin client" );
1091  eq::admin::exit();
1092  }
1093 
1094  _admin = new eq::admin::Server;
1095  if( !client->connectServer( _admin ))
1096  {
1097  _setMessage( "Can't open connection to administrate server" );
1098  client->exitLocal();
1099  _admin = 0;
1100  eq::admin::exit();
1101  }
1102  return _admin;
1103 }
1104 
1105 void Config::_closeAdminServer()
1106 {
1107  if( !_admin )
1108  return;
1109 
1110  eq::admin::ClientPtr client = _admin->getClient();
1111  client->disconnectServer( _admin );
1112  client->exitLocal();
1113  LBASSERT( client->getRefCount() == 1 );
1114  LBASSERT( _admin->getRefCount() == 1 );
1115 
1116  _admin = 0;
1117  eq::admin::exit();
1118 }
1119 
1120 View* Config::_getCurrentView()
1121 {
1122  const eq::uint128_t& viewID = _frameData.getCurrentViewID();
1123  eq::View* view = find< eq::View >( viewID );
1124  return static_cast< View* >( view );
1125 }
1126 
1127 const View* Config::_getCurrentView() const
1128 {
1129  const eq::uint128_t& viewID = _frameData.getCurrentViewID();
1130  const eq::View* view = find< eq::View >( viewID );
1131  return static_cast< const View* >( view );
1132 }
1133 
1134 }
SpaceMouse button data in magellan.
Definition: event.h:230
A command specialization for config events.
Definition: eventICommand.h:38
int32_t dx
X position change since last event.
Definition: event.h:119
Event for a pointer (mouse) motion or click.
Definition: event.h:115
A window has been closed.
Definition: event.h:181
int32_t xAxis
x wheel rotation
Definition: event.h:123
int32_t yAxis
y wheel rotation
Definition: event.h:124
Window resize data in resize.
Definition: event.h:180
const Pipes & getPipes() const
virtual bool init(const uint128_t &initID)
Initialize this configuration.
Canvases::const_iterator CanvasesCIter
A const_iterator over a eq::Canvas vector.
virtual ~Config()
Destruct a config.
A View is a 2D area of a Layout.
Window pointer Mouse wheel data in wheel.
Definition: event.h:208
uint32_t button
fired button
Definition: event.h:140
int64_t getTime() const
Get the current time in milliseconds.
int16_t yRotation
Y rotation.
Definition: event.h:146
int32_t dy
Y position change since last event.
Definition: event.h:120
A layout groups one or more View, logically belonging together.
Definition: client/layout.h:44
co::NodePtr getApplicationNode()
A canvas represents a logical 2D projection surface.
Definition: client/canvas.h:51
virtual void unmapObject(co::Object *object)
Unmap a mapped object.
float getFocusDistance() const
View resize data in resize.
Definition: event.h:227
uint32_t getEventType() const
Returns the event type.
A Node represents a single computer in the cluster.
void stopFrames()
Asynchronously signal all channels to interrupt their rendering.
std::vector< Layout * > Layouts
A vector of pointers to eq::Layout.
const Views & getViews() const
Get the list of views.
Definition: fabric/layout.h:47
bool exit()
De-initialize the Equalizer fabric namespace.
lunchbox::RefPtr< Server > ServerPtr
A reference-counted pointer to an eq::Server.
virtual void deregisterObject(co::Object *object)
Deregister a distributed object.
virtual uint32_t mapObjectNB(co::Object *object, const UUID &id, const uint128_t &version=co::VERSION_OLDEST)
Start mapping a distributed object.
Key press data in keyPress.
Definition: event.h:223
virtual bool handleEvent(const ConfigEvent *event)
Handle one (old) config event.
virtual uint32_t startFrame(const uint128_t &frameID)
Request a new frame of rendering.
int16_t xRotation
X rotation.
Definition: event.h:145
co::Object to distribute a model, holds a VertexBufferBase node.
Render in solid white (mostly for anaglyph stereo)
Definition: eqPly.h:80
EQFABRIC_INL const Vector3f & getEyePosition(const Eye eye) const
A window is dirty.
Definition: event.h:179
std::vector< View * > Views
A vector of pointers to eq::View.
virtual uint32_t startFrame(const eq::uint128_t &frameID)
PointerEvent pointerWheel
Mouse wheel motion data.
Definition: event.h:268
ClientPtr getClient()
uint32_t buttons
current state of all buttons
Definition: event.h:121
int16_t xAxis
X translation.
Definition: event.h:142
std::vector< Observer * > Observers
A vector of pointers to eq::Observer.
std::vector< Canvas * > Canvases
A vector of pointers to eq::Canvas.
An Observer looks at one or more views from a certain position (head matrix) with a given eye separat...
Channel pointer button press data in pointerButtonPress.
Definition: event.h:204
uint32_t type
The event type.
Definition: event.h:246
int16_t zAxis
Z translation.
Definition: event.h:144
KeyEvent keyPress
Key press event data.
Definition: event.h:271
virtual bool registerObject(co::Object *object)
Register a distributed object.
bool update()
Update the configuration.
EQFABRIC_INL void setFocusDistance(const float focusDistance)
Set the focal distance.
MagellanEvent magellan
SpaceMouse data.
Definition: event.h:275
EQFABRIC_INL const L * getActiveLayout() const
uint32_t button
fired button
Definition: event.h:122
Channel pointer button release data in pointerButtonRelease.
Definition: event.h:206
PointerEvent pointerMotion
Pointer motion data.
Definition: event.h:265
Views::const_iterator ViewsCIter
A const_iterator over a eq::View vector.
SpaceMouse movement data in magellan.
Definition: event.h:229
virtual bool exit()
Exit this configuration.
int16_t zRotation
Z rotation.
Definition: event.h:147
virtual bool mapObjectSync(const uint32_t requestID)
Finalize the mapping of a distributed object.
const std::string & getName() const
virtual bool handleEvent(eq::EventICommand command)
int16_t yAxis
Y translation.
Definition: event.h:143
EQFABRIC_INL VisitorResult accept(ConfigVisitor &visitor)
Perform a depth-first traversal of this config.
Event for a key press or release.
Definition: event.h:128
uint32_t key
KeyCode for special keys, ascii code otherwise.
Definition: event.h:130
EQFABRIC_INL void setEyePosition(const Eye eye, const Vector3f &pos)
Set the position of the given eye relative to the observer.
Observers::const_iterator ObserversCIter
A const_iterator over a eq::Observer vector.
bool init(const int argc, char **argv)
Initialize the Equalizer fabric namespace.