Equalizer  1.8.0
Parallel Rendering Framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
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  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::uint128_t( ));
223  _frameData.setModelID( eq::uint128_t( ));
224 }
225 
226 bool Config::loadInitData( const eq::uint128_t& id )
227 {
228  LBASSERT( !_initData.isAttached( ));
229  return getClient()->syncObject( &_initData, getApplicationNode(), id );
230 }
231 
232 const Model* Config::getModel( const eq::uint128_t& modelID )
233 {
234  if( modelID == 0 )
235  return 0;
236 
237  // Protect if accessed concurrently from multiple pipe threads
238  const eq::Node* node = getNodes().front();
239  const bool needModelLock = (node->getPipes().size() > 1);
240  lunchbox::ScopedWrite _mutex( needModelLock ? &_modelLock : 0 );
241 
242  const size_t nModels = _models.size();
243  LBASSERT( _modelDist.size() == nModels );
244 
245  for( size_t i = 0; i < nModels; ++i )
246  {
247  const ModelDist* dist = _modelDist[ i ];
248  if( dist->getID() == modelID )
249  return _models[ i ];
250  }
251 
252  _modelDist.push_back( new ModelDist );
253  Model* model = _modelDist.back()->loadModel( getApplicationNode(),
254  getClient(), modelID );
255  LBASSERT( model );
256  _models.push_back( model );
257 
258  return model;
259 }
260 
262 {
263  _updateData();
264  const eq::uint128_t& version = _frameData.commit();
265 
266  _redraw = false;
267  return eq::Config::startFrame( version );
268 }
269 
270 void Config::_updateData()
271 {
272  // update camera
273  if( _animation.isValid( ))
274  {
275  const eq::Vector3f& modelRotation = _animation.getModelRotation();
276  const CameraAnimation::Step& curStep = _animation.getNextStep();
277 
278  _frameData.setModelRotation( modelRotation);
279  _frameData.setRotation( curStep.rotation );
280  _frameData.setCameraPosition( curStep.position );
281  }
282  else
283  {
284  if( _frameData.usePilotMode())
285  _frameData.spinCamera( -0.001f * _spinX, -0.001f * _spinY );
286  else
287  _frameData.spinModel( -0.001f * _spinX, -0.001f * _spinY, 0.f );
288 
289  _frameData.moveCamera( 0.0f, 0.0f, 0.001f * _advance );
290  }
291 
292  // idle mode
293  if( isIdleAA( ))
294  {
295  LBASSERT( _numFramesAA > 0 );
296  _frameData.setIdle( true );
297  }
298  else
299  _frameData.setIdle( false );
300 
301  _numFramesAA = 0;
302 }
303 
304 bool Config::isIdleAA()
305 {
306  return ( !_needNewFrame() && _numFramesAA > 0 );
307 }
308 
309 bool Config::needRedraw()
310 {
311  return( _needNewFrame() || _numFramesAA > 0 );
312 }
313 
314 uint32_t Config::getAnimationFrame()
315 {
316  return _animation.getCurrentFrame();
317 }
318 
319 bool Config::_needNewFrame()
320 {
321  if( _messageTime > 0 )
322  {
323  if( getTime() - _messageTime > 2000 ) // reset message after two seconds
324  {
325  _messageTime = 0;
326  _frameData.setMessage( "" );
327  }
328  return true;
329  }
330 
331  return ( _spinX != 0 || _spinY != 0 || _advance != 0 || _redraw );
332 }
333 
335 {
336  switch( event->data.type )
337  {
338  case eq::Event::KEY_PRESS:
339  {
340  if( _handleKeyEvent( event->data.keyPress ))
341  {
342  _redraw = true;
343  return true;
344  }
345  break;
346  }
347 
348  case eq::Event::CHANNEL_POINTER_BUTTON_PRESS:
349  {
350  const eq::uint128_t& viewID = event->data.context.view.identifier;
351  _frameData.setCurrentViewID( viewID );
352  if( viewID == 0 )
353  {
354  _currentCanvas = 0;
355  return false;
356  }
357 
358  const View* view = _getCurrentView();
359  const eq::Layout* layout = view->getLayout();
360  const eq::Canvases& canvases = getCanvases();
361  for( eq::CanvasesCIter i = canvases.begin();
362  i != canvases.end(); ++i )
363  {
364  eq::Canvas* canvas = *i;
365  const eq::Layout* canvasLayout = canvas->getActiveLayout();
366 
367  if( canvasLayout == layout )
368  {
369  _currentCanvas = canvas;
370  return true;
371  }
372  }
373  return true;
374  }
375 
376  case eq::Event::CHANNEL_POINTER_BUTTON_RELEASE:
377  {
378  const eq::PointerEvent& releaseEvent =
379  event->data.pointerButtonRelease;
380  if( releaseEvent.buttons == eq::PTR_BUTTON_NONE)
381  {
382  if( releaseEvent.button == eq::PTR_BUTTON1 )
383  {
384  _spinX = releaseEvent.dy;
385  _spinY = releaseEvent.dx;
386  _redraw = true;
387  return true;
388  }
389  if( releaseEvent.button == eq::PTR_BUTTON2 )
390  {
391  _advance = -releaseEvent.dy;
392  _redraw = true;
393  return true;
394  }
395  }
396  break;
397  }
398  case eq::Event::CHANNEL_POINTER_MOTION:
399  {
400  switch( event->data.pointerMotion.buttons )
401  {
402  case eq::PTR_BUTTON1:
403  _spinX = 0;
404  _spinY = 0;
405 
406  if( _frameData.usePilotMode())
407  _frameData.spinCamera(
408  -0.005f * event->data.pointerMotion.dy,
409  -0.005f * event->data.pointerMotion.dx );
410  else
411  _frameData.spinModel(
412  -0.005f * event->data.pointerMotion.dy,
413  -0.005f * event->data.pointerMotion.dx, 0.f );
414  _redraw = true;
415  return true;
416 
417  case eq::PTR_BUTTON2:
418  _advance = -event->data.pointerMotion.dy;
419  _frameData.moveCamera( 0.f, 0.f, .005f * _advance );
420  _redraw = true;
421  return true;
422 
423  case eq::PTR_BUTTON3:
424  _frameData.moveCamera( .0005f * event->data.pointerMotion.dx,
425  -.0005f * event->data.pointerMotion.dy,
426  0.f );
427  _redraw = true;
428  return true;
429  }
430  break;
431  }
432 
433  case eq::Event::CHANNEL_POINTER_WHEEL:
434  {
435  _frameData.moveCamera( -0.05f * event->data.pointerWheel.xAxis,
436  0.f,
437  0.05f * event->data.pointerWheel.yAxis );
438  _redraw = true;
439  return true;
440  }
441 
442  case eq::Event::MAGELLAN_AXIS:
443  {
444  _spinX = 0;
445  _spinY = 0;
446  _advance = 0;
447  _frameData.spinModel( 0.0001f * event->data.magellan.xRotation,
448  0.0001f * event->data.magellan.yRotation,
449  0.0001f * event->data.magellan.zRotation );
450  _frameData.moveCamera( 0.0001f * event->data.magellan.xAxis,
451  0.0001f * event->data.magellan.yAxis,
452  0.0001f * event->data.magellan.zAxis );
453  _redraw = true;
454  return true;
455  }
456 
457  case eq::Event::MAGELLAN_BUTTON:
458  {
459  if( event->data.magellan.button == eq::PTR_BUTTON1 )
460  _frameData.toggleColorMode();
461 
462  _redraw = true;
463  return true;
464  }
465 
466  case eq::Event::WINDOW_EXPOSE:
467  case eq::Event::WINDOW_RESIZE:
468  case eq::Event::WINDOW_CLOSE:
469  case eq::Event::VIEW_RESIZE:
470  _redraw = true;
471  break;
472 
473  default:
474  break;
475  }
476 
477  _redraw |= eq::Config::handleEvent( event );
478  return _redraw;
479 }
480 
482 {
483  switch( command.getEventType( ))
484  {
485  case IDLE_AA_LEFT:
486  if( _useIdleAA )
487  {
488  const int32_t steps = command.read< int32_t >();
489  _numFramesAA = LB_MAX( _numFramesAA, steps );
490  }
491  else
492  _numFramesAA = 0;
493  return false;
494 
495  default:
496  break;
497  }
498 
499  _redraw |= eq::Config::handleEvent( command );
500  return _redraw;
501 }
502 
503 bool Config::_handleKeyEvent( const eq::KeyEvent& event )
504 {
505  switch( event.key )
506  {
507  case 'z':
508  _adjustEyeBase( -0.1f );
509  return true;
510  case 'Z':
511  _adjustEyeBase( 0.1f );
512  return true;
513  case 'y':
514  _adjustModelScale( 0.1f );
515  return true;
516  case 'Y':
517  _adjustModelScale( 10.0f );
518  return true;
519  case 't':
520  _adjustTileSize( -1 );
521  return true;
522  case 'T':
523  _adjustTileSize( 1 );
524  return true;
525  case 'u':
526  _frameData.toggleCompression();
527  return true;
528 
529  case 'n':
530  case 'N':
531  _frameData.togglePilotMode();
532  return true;
533  case ' ':
534  stopFrames();
535  _spinX = 0;
536  _spinY = 0;
537  _advance = 0;
538  _frameData.reset();
539  _setHeadMatrix( eq::Matrix4f::IDENTITY );
540  return true;
541 
542  case 'i':
543  _useIdleAA = !_useIdleAA;
544  return true;
545 
546  case 'k':
547  {
548  lunchbox::RNG rng;
549  if( rng.get< bool >( ))
550  _frameData.toggleOrtho();
551  if( rng.get< bool >( ))
552  _frameData.toggleStatistics();
553  if( rng.get< bool >( ))
554  _switchCanvas();
555  if( rng.get< bool >( ))
556  _switchView();
557  if( rng.get< bool >( ))
558  _switchLayout( 1 );
559  if( rng.get< bool >( ))
560  _switchModel();
561  if( rng.get< bool >( ))
562  eqAdmin::addWindow( _getAdminServer(), rng.get< bool >( ));
563  if( rng.get< bool >( ))
564  {
565  eqAdmin::removeWindow( _getAdminServer( ));
566  _currentCanvas = 0;
567  }
568  if( rng.get< bool >( ))
569  _switchViewMode();
570  return true;
571  }
572 
573  case 'o':
574  case 'O':
575  _frameData.toggleOrtho();
576  return true;
577 
578  case 's':
579  case 'S':
580  _frameData.toggleStatistics();
581  return true;
582 
583  case 'f':
584  _freezeLoadBalancing( true );
585  return true;
586 
587  case 'F':
588  _freezeLoadBalancing( false );
589  return true;
590 
591  case eq::KC_F1:
592  case 'h':
593  case 'H':
594  _frameData.toggleHelp();
595  return true;
596 
597  case 'd':
598  case 'D':
599  _frameData.toggleColorMode();
600  return true;
601 
602  case 'q':
603  _frameData.adjustQuality( -.1f );
604  return true;
605 
606  case 'Q':
607  _frameData.adjustQuality( .1f );
608  return true;
609 
610  case 'c':
611  case 'C':
612  _switchCanvas();
613  return true;
614 
615  case 'v':
616  case 'V':
617  _switchView();
618  return true;
619 
620  case 'm':
621  case 'M':
622  _switchModel();
623  return true;
624 
625  case 'l':
626  _switchLayout( 1 );
627  return true;
628  case 'L':
629  _switchLayout( -1 );
630  return true;
631 
632  case 'w':
633  case 'W':
634  _frameData.toggleWireframe();
635  return true;
636 
637  case 'r':
638  case 'R':
639  _frameData.toggleRenderMode();
640  return true;
641  case 'g':
642  case 'G':
643  _switchViewMode();
644  return true;
645  case 'a':
646  eqAdmin::addWindow( _getAdminServer(), false /* active stereo */ );
647  return true;
648  case 'p':
649  eqAdmin::addWindow( _getAdminServer(), true /* passive stereo */ );
650  return true;
651  case 'x':
652  eqAdmin::removeWindow( _getAdminServer( ));
653  _currentCanvas = 0;
654  LBASSERT( update() );
655  return false;
656 
657  // Head Tracking Emulation
658  case eq::KC_UP:
659  {
660  eq::Matrix4f headMatrix = _getHeadMatrix();
661  headMatrix.y() += 0.1f;
662  _setHeadMatrix( headMatrix );
663  return true;
664  }
665  case eq::KC_DOWN:
666  {
667  eq::Matrix4f headMatrix = _getHeadMatrix();
668  headMatrix.y() -= 0.1f;
669  _setHeadMatrix( headMatrix );
670  return true;
671  }
672  case eq::KC_RIGHT:
673  {
674  eq::Matrix4f headMatrix = _getHeadMatrix();
675  headMatrix.x() += 0.1f;
676  _setHeadMatrix( headMatrix );
677  return true;
678  }
679  case eq::KC_LEFT:
680  {
681  eq::Matrix4f headMatrix = _getHeadMatrix();
682  headMatrix.x() -= 0.1f;
683  _setHeadMatrix( headMatrix );
684  return true;
685  }
686  case eq::KC_PAGE_DOWN:
687  {
688  eq::Matrix4f headMatrix = _getHeadMatrix();
689  headMatrix.z() += 0.1f;
690  _setHeadMatrix( headMatrix );
691  return true;
692  }
693  case eq::KC_PAGE_UP:
694  {
695  eq::Matrix4f headMatrix = _getHeadMatrix();
696  headMatrix.z() -= 0.1f;
697  _setHeadMatrix( headMatrix );
698  return true;
699  }
700  case '.':
701  {
702  eq::Matrix4f headMatrix = _getHeadMatrix();
703  headMatrix.pre_rotate_x( .1f );
704  _setHeadMatrix( headMatrix );
705  return true;
706  }
707  case ',':
708  {
709  eq::Matrix4f headMatrix = _getHeadMatrix();
710  headMatrix.pre_rotate_x( -.1f );
711  _setHeadMatrix( headMatrix );
712  return true;
713  }
714  case ';':
715  {
716  eq::Matrix4f headMatrix = _getHeadMatrix();
717  headMatrix.pre_rotate_y( .1f );
718  _setHeadMatrix( headMatrix );
719  return true;
720  }
721  case '\'':
722  {
723  eq::Matrix4f headMatrix = _getHeadMatrix();
724  headMatrix.pre_rotate_y( -.1f );
725  _setHeadMatrix( headMatrix );
726  return true;
727  }
728  case '[':
729  {
730  eq::Matrix4f headMatrix = _getHeadMatrix();
731  headMatrix.pre_rotate_z( -.1f );
732  _setHeadMatrix( headMatrix );
733  return true;
734  }
735  case ']':
736  {
737  eq::Matrix4f headMatrix = _getHeadMatrix();
738  headMatrix.pre_rotate_z( .1f );
739  _setHeadMatrix( headMatrix );
740  return true;
741  }
742 
743  case '+':
744  _changeFocusDistance( .1f );
745  return true;
746 
747  case '-':
748  _changeFocusDistance( -.1f );
749  return true;
750 
751  case '1':
752  _setFocusMode( eq::FOCUSMODE_FIXED );
753  return true;
754 
755  case '2':
756  _setFocusMode( eq::FOCUSMODE_RELATIVE_TO_ORIGIN );
757  return true;
758 
759  case '3':
760  _setFocusMode( eq::FOCUSMODE_RELATIVE_TO_OBSERVER );
761  return true;
762 
763  case '4':
764  _adjustResistance( 1 );
765  return true;
766 
767  case '5':
768  _adjustResistance( -1 );
769  return true;
770 
771  case 'j':
772  stopFrames();
773  return true;
774 
775  case 'e':
776  _toggleEqualizer();
777  return true;
778 
779  default:
780  return false;
781  }
782 }
783 
784 co::uint128_t Config::sync( const co::uint128_t& version )
785 {
786  if( _admin.isValid() && _admin->isConnected( ))
787  _admin->syncConfig( getID(), version );
788 
789  return eq::Config::sync( version );
790 }
791 
792 void Config::_switchCanvas()
793 {
794  const eq::Canvases& canvases = getCanvases();
795  if( canvases.empty( ))
796  return;
797 
798  _frameData.setCurrentViewID( eq::uint128_t( ));
799 
800  if( !_currentCanvas )
801  {
802  _currentCanvas = canvases.front();
803  return;
804  }
805 
806  eq::CanvasesCIter i = lunchbox::find( canvases, _currentCanvas );
807  LBASSERT( i != canvases.end( ));
808 
809  ++i;
810  if( i == canvases.end( ))
811  _currentCanvas = canvases.front();
812  else
813  _currentCanvas = *i;
814  _switchView(); // activate first view on canvas
815 }
816 
817 void Config::_switchView()
818 {
819  const eq::Canvases& canvases = getCanvases();
820  if( !_currentCanvas && !canvases.empty( ))
821  _currentCanvas = canvases.front();
822 
823  if( !_currentCanvas )
824  return;
825 
826  const eq::Layout* layout = _currentCanvas->getActiveLayout();
827  if( !layout )
828  return;
829 
830  const View* view = _getCurrentView();
831  const eq::Views& views = layout->getViews();
832  LBASSERT( !views.empty( ));
833 
834  if( !view )
835  {
836  _frameData.setCurrentViewID( views.front()->getID( ));
837  return;
838  }
839 
840  eq::ViewsCIter i = std::find( views.begin(), views.end(), view );
841  if( i != views.end( ))
842  ++i;
843  if( i == views.end( ))
844  _frameData.setCurrentViewID( eq::uint128_t( ));
845  else
846  _frameData.setCurrentViewID( (*i)->getID( ));
847 }
848 
849 void Config::_switchModel()
850 {
851  if( _modelDist.empty( )) // no models
852  return;
853 
854  // current model of current view
855  View* view = _getCurrentView();
856  const eq::uint128_t& currentID = view ? view->getModelID() :
857  _frameData.getModelID();
858  // next model
859  ModelDistsCIter i;
860  for( i = _modelDist.begin(); i != _modelDist.end(); ++i )
861  {
862  if( (*i)->getID() != currentID )
863  continue;
864 
865  ++i;
866  break;
867  }
868  if( i == _modelDist.end( ))
869  i = _modelDist.begin(); // wrap around
870 
871  // set identifier on view or frame data (default model)
872  const eq::uint128_t& modelID = (*i)->getID();
873  if( view )
874  view->setModelID( modelID );
875  else
876  _frameData.setModelID( modelID );
877 
878  if( view )
879  {
880  const Model* model = getModel( modelID );
881  _setMessage( "Using " + lunchbox::getFilename( model->getName( )));
882  }
883 }
884 
885 void Config::_switchViewMode()
886 {
887  View* view = _getCurrentView();
888  if( !view )
889  return;
890 
891  const eq::View::Mode mode = view->getMode();
892  if( mode == eq::View::MODE_MONO )
893  {
894  view->changeMode( eq::View::MODE_STEREO );
895  _setMessage( "Switched to stereoscopic rendering" );
896  }
897  else
898  {
899  view->changeMode( eq::View::MODE_MONO );
900  _setMessage( "Switched to monoscopic rendering" );
901  }
902 }
903 
904 void Config::_freezeLoadBalancing( const bool onOff )
905 {
906  View* view = _getCurrentView();
907  if ( view )
908  view->getEqualizer().setFrozen( onOff );
909 }
910 
911 void Config::_adjustEyeBase( const float delta )
912 {
913  const eq::Observers& observers = getObservers();
914  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
915  {
916  eq::Observer* observer = *i;
917  observer->setEyePosition( eq::EYE_LEFT,
918  observer->getEyePosition( eq::EYE_LEFT ) +
919  eq::Vector3f( -delta, 0.f, 0.f ));
920  observer->setEyePosition( eq::EYE_RIGHT,
921  observer->getEyePosition( eq::EYE_RIGHT ) +
922  eq::Vector3f( delta, 0.f, 0.f ));
923  std::ostringstream stream;
924  stream << "Set eyes to " << observer->getEyePosition( eq::EYE_LEFT )
925  << ", " << observer->getEyePosition( eq::EYE_RIGHT );
926  _setMessage( stream.str( ));
927  }
928 }
929 
930 void Config::_adjustTileSize( const int delta )
931 {
932  View* view = _getCurrentView();
933  if( !view )
934  return;
935 
936  eq::Vector2i tileSize = view->getEqualizer().getTileSize();
937  if( tileSize == eq::Vector2i( -1, -1 ) )
938  tileSize = eq::Vector2i( 64, 64 );
939  tileSize += delta;
940  view->getEqualizer().setTileSize( tileSize );
941 }
942 
943 void Config::_adjustResistance( const int delta )
944 {
945  View* view = _getCurrentView();
946  if( !view )
947  return;
948 
949  eq::Vector2i size = view->getEqualizer().getResistance2i();
950  size += delta;
951  size.x() = LB_MAX( size.x(), 0 );
952  size.y() = LB_MAX( size.y(), 0 );
953  std::ostringstream stream;
954  stream << "Set load equalizer resistance to " << size;
955  _setMessage( stream.str( ));
956  view->getEqualizer().setResistance( size );
957 }
958 
959 void Config::_adjustModelScale( const float factor )
960 {
961  View* view = _getCurrentView();
962  if( !view )
963  return;
964 
965  const float current = view->getModelUnit() * factor;
966  if( current > std::numeric_limits<float>::epsilon( ))
967  view->setModelUnit( current );
968 
969  std::ostringstream stream;
970  stream << "Set model unit to " << view->getModelUnit();
971  _setMessage( stream.str( ));
972 }
973 
974 void Config::_switchLayout( int32_t increment )
975 {
976  if( !_currentCanvas )
977  return;
978 
979  _frameData.setCurrentViewID( eq::uint128_t( ));
980 
981  int64_t index = _currentCanvas->getActiveLayoutIndex() + increment;
982  const eq::Layouts& layouts = _currentCanvas->getLayouts();
983  LBASSERT( !layouts.empty( ));
984 
985  index = ( index % layouts.size( ));
986  _currentCanvas->useLayout( uint32_t( index ));
987 
988  const eq::Layout* layout = layouts[index];
989  std::ostringstream stream;
990  stream << "Layout ";
991  if( layout )
992  {
993  const std::string& name = layout->getName();
994  if( name.empty( ))
995  stream << index;
996  else
997  stream << name;
998  }
999  else
1000  stream << "NONE";
1001 
1002  stream << " active";
1003  _setMessage( stream.str( ));
1004 }
1005 
1006 void Config::_toggleEqualizer()
1007 {
1008  View* view = _getCurrentView();
1009  if ( view )
1010  view->toggleEqualizer();
1011 }
1012 
1013 // Note: real applications would use one tracking device per observer
1014 void Config::_setHeadMatrix( const eq::Matrix4f& matrix )
1015 {
1016  const eq::Observers& observers = getObservers();
1017  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1018  {
1019  (*i)->setHeadMatrix( matrix );
1020  }
1021 
1022  eq::Vector3f trans;
1023  matrix.get_translation( trans );
1024  std::ostringstream stream;
1025  stream << "Observer at " << trans;
1026  _setMessage( stream.str( ));
1027 }
1028 
1029 const eq::Matrix4f& Config::_getHeadMatrix() const
1030 {
1031  const eq::Observers& observers = getObservers();
1032  if( observers.empty( ))
1033  return eq::Matrix4f::IDENTITY;
1034 
1035  return observers[0]->getHeadMatrix();
1036 }
1037 
1038 void Config::_changeFocusDistance( const float delta )
1039 {
1040  const eq::Observers& observers = getObservers();
1041  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1042  {
1043  eq::Observer* observer = *i;
1044  observer->setFocusDistance( observer->getFocusDistance() + delta );
1045  std::ostringstream stream;
1046  stream << "Set focus distance to " << observer->getFocusDistance();
1047  _setMessage( stream.str( ));
1048  }
1049 }
1050 
1051 void Config::_setFocusMode( const eq::FocusMode mode )
1052 {
1053  const eq::Observers& observers = getObservers();
1054  for( eq::ObserversCIter i = observers.begin(); i != observers.end(); ++i )
1055  (*i)->setFocusMode( mode );
1056 
1057  std::ostringstream stream;
1058  stream << "Set focus mode to " << mode;
1059  _setMessage( stream.str( ));
1060 }
1061 
1062 void Config::_setMessage( const std::string& message )
1063 {
1064  _frameData.setMessage( message );
1065  _messageTime = getTime();
1066 }
1067 
1068 eq::admin::ServerPtr Config::_getAdminServer()
1069 {
1070  // Debug: _closeAdminServer();
1071  if( _admin.isValid() && _admin->isConnected( ))
1072  return _admin;
1073 
1074  eq::admin::init( 0, 0 );
1075  eq::admin::ClientPtr client = new eq::admin::Client;
1076  if( !client->initLocal( 0, 0 ))
1077  {
1078  _setMessage( "Can't init admin client" );
1079  eq::admin::exit();
1080  }
1081 
1082  _admin = new eq::admin::Server;
1083  if( !client->connectServer( _admin ))
1084  {
1085  _setMessage( "Can't open connection to administrate server" );
1086  client->exitLocal();
1087  _admin = 0;
1088  eq::admin::exit();
1089  }
1090  return _admin;
1091 }
1092 
1093 void Config::_closeAdminServer()
1094 {
1095  if( !_admin )
1096  return;
1097 
1098  eq::admin::ClientPtr client = _admin->getClient();
1099  client->disconnectServer( _admin );
1100  client->exitLocal();
1101  LBASSERT( client->getRefCount() == 1 );
1102  LBASSERT( _admin->getRefCount() == 1 );
1103 
1104  _admin = 0;
1105  eq::admin::exit();
1106 }
1107 
1108 View* Config::_getCurrentView()
1109 {
1110  const eq::uint128_t& viewID = _frameData.getCurrentViewID();
1111  eq::View* view = find< eq::View >( viewID );
1112  return static_cast< View* >( view );
1113 }
1114 
1115 const View* Config::_getCurrentView() const
1116 {
1117  const eq::uint128_t& viewID = _frameData.getCurrentViewID();
1118  const eq::View* view = find< eq::View >( viewID );
1119  return static_cast< const View* >( view );
1120 }
1121 
1122 }
virtual EQ_API bool init(const uint128_t &initID)
Initialize this configuration.
EQFABRIC_INL void setFocusDistance(const float focusDistance)
Set the focal distance.
A canvas represents a logical 2D projection surface.
Definition: client/canvas.h:50
const Pipes & getPipes() const
EQFABRIC_INL VisitorResult accept(ConfigVisitor &visitor)
Perform a depth-first traversal of this config.
Canvases::const_iterator CanvasesCIter
A const_iterator over a eq::Canvas vector.
virtual EQ_API bool exit()
Exit this configuration.
EQ_API bool update()
Update the configuration.
A Node represents a single computer in the cluster.
virtual bool handleEvent(eq::EventICommand command)
EQ_API void stopFrames()
Asynchronously signal all channels to interrupt their rendering.
EQFABRIC_INL void setEyePosition(const Eye eye, const Vector3f &pos)
Set the position of the given eye relative to the observer.
virtual EQ_API uint32_t startFrame(const uint128_t &frameID)
Request a new frame of rendering.
EQ_API int64_t getTime() const
Get the current time in milliseconds.
std::vector< Layout * > Layouts
A vector of pointers to eq::Layout.
lunchbox::RefPtr< Server > ServerPtr
A reference-counted pointer to an eq::Server.
EQFABRIC_INL const Vector3f & getEyePosition(const Eye eye) const
A command specialization for config events.
Definition: eventICommand.h:38
EQFABRIC_API const std::string & getName() const
EQFABRIC_INL const L * getActiveLayout() const
std::vector< View * > Views
A vector of pointers to eq::View.
float getFocusDistance() const
std::vector< Observer * > Observers
A vector of pointers to eq::Observer.
std::vector< Canvas * > Canvases
A vector of pointers to eq::Canvas.
EQFABRIC_API bool exit()
De-initialize the Equalizer fabric namespace.
A layout groups one or more View, logically belonging together.
Definition: client/layout.h:46
A View is a 2D area of a Layout.
EQ_API ClientPtr getClient()
EQFABRIC_API bool init(const int argc, char **argv)
Initialize the Equalizer fabric namespace.
virtual ~Config()
Destruct a config.
Views::const_iterator ViewsCIter
A const_iterator over a eq::View vector.
virtual EQ_API bool registerObject(co::Object *object)
Register a distributed object.
EQ_API co::NodePtr getApplicationNode()
An Observer looks at one or more views from a certain position (head matrix) with a given eye separat...
virtual EQ_API bool handleEvent(const ConfigEvent *event)
Handle one (old) config event.
virtual EQ_API void deregisterObject(co::Object *object)
Deregister a distributed object.
Observers::const_iterator ObserversCIter
A const_iterator over a eq::Observer vector.
virtual uint32_t startFrame(const eq::uint128_t &frameID)
const Views & getViews() const
Get the list of views.
Definition: fabric/layout.h:47
EQ_API uint32_t getEventType() const
Returns the event type.