Equalizer  1.6.1
eqPly/channel.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  * 2007, Tobias Wolf <twolf@access.unizh.ch>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  * - Neither the name of Eyescale Software GmbH nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "channel.h"
33 
34 #include "initData.h"
35 #include "config.h"
36 #include "configEvent.h"
37 #include "pipe.h"
38 #include "view.h"
39 #include "window.h"
40 #include "vertexBufferState.h"
41 
42 // light parameters
43 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
44 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
45 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
46 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
47 
48 // material properties
49 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
50 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
51 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
52 static GLint materialShininess = 64;
53 
54 #ifndef M_SQRT3_2
55 # define M_SQRT3_2 0.86603f /* sqrt(3)/2 */
56 #endif
57 
58 namespace eqPly
59 {
60 
61 Channel::Channel( eq::Window* parent )
62  : eq::Channel( parent )
63  , _model(0)
64  , _frameRestart( 0 )
65 {
66 }
67 
68 bool Channel::configInit( const eq::uint128_t& initID )
69 {
70  if( !eq::Channel::configInit( initID ))
71  return false;
72 
73  setNearFar( 0.1f, 10.0f );
74  _model = 0;
75  _modelID = 0;
76  return true;
77 }
78 
80 {
81  for( size_t i = 0; i < eq::NUM_EYES; ++i )
82  {
83  delete _accum[ i ].buffer;
84  _accum[ i ].buffer = 0;
85  }
86 
87  return eq::Channel::configExit();
88 }
89 
90 void Channel::frameClear( const eq::uint128_t& frameID )
91 {
92  if( stopRendering( ))
93  return;
94 
95  _initJitter();
96  resetRegions();
97 
98  const FrameData& frameData = _getFrameData();
99  const int32_t eyeIndex = lunchbox::getIndexOfLastBit( getEye() );
100  if( _isDone() && !_accum[ eyeIndex ].transfer )
101  return;
102 
103  applyBuffer();
104  applyViewport();
105 
106  const eq::View* view = getView();
107  if( view && frameData.getCurrentViewID() == view->getID( ))
108  glClearColor( 1.f, 1.f, 1.f, 0.f );
109 #ifndef NDEBUG
110  else if( getenv( "EQ_TAINT_CHANNELS" ))
111  {
112  const eq::Vector3ub color = getUniqueColor();
113  glClearColor( color.r()/255.f, color.g()/255.f, color.b()/255.f, 0.f );
114  }
115 #endif // NDEBUG
116  else
117  glClearColor( 0.f, 0.f, 0.f, 0.0f );
118 
119  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
120 }
121 
122 void Channel::frameDraw( const eq::uint128_t& frameID )
123 {
124  if( stopRendering( ))
125  return;
126 
127  _initJitter();
128  if( _isDone( ))
129  return;
130 
131  Window* window = static_cast< Window* >( getWindow( ));
132  VertexBufferState& state = window->getState();
133  const Model* oldModel = _model;
134  const Model* model = _getModel();
135 
136  if( oldModel != model )
137  state.setFrustumCulling( false ); // create all display lists/VBOs
138 
139  if( model )
140  _updateNearFar( model->getBoundingSphere( ));
141 
142  eq::Channel::frameDraw( frameID ); // Setup OpenGL state
143 
144  glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
145  glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
146  glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse );
147  glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
148 
149  glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
150  glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
151  glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
152  glMateriali( GL_FRONT, GL_SHININESS, materialShininess );
153 
154  const FrameData& frameData = _getFrameData();
155  glPolygonMode( GL_FRONT_AND_BACK,
156  frameData.useWireframe() ? GL_LINE : GL_FILL );
157 
158  const eq::Vector3f& position = frameData.getCameraPosition();
159 
160  glMultMatrixf( frameData.getCameraRotation().array );
161  glTranslatef( position.x(), position.y(), position.z() );
162  glMultMatrixf( frameData.getModelRotation().array );
163 
164  if( frameData.getColorMode() == COLOR_DEMO )
165  {
166  const eq::Vector3ub color = getUniqueColor();
167  glColor3ub( color.r(), color.g(), color.b() );
168  }
169  else
170  glColor3f( .75f, .75f, .75f );
171 
172  if( model )
173  _drawModel( model );
174  else
175  {
176  glNormal3f( 0.f, -1.f, 0.f );
177  glBegin( GL_TRIANGLE_STRIP );
178  glVertex3f( .25f, 0.f, .25f );
179  glVertex3f( -.25f, 0.f, .25f );
180  glVertex3f( .25f, 0.f, -.25f );
181  glVertex3f( -.25f, 0.f, -.25f );
182  glEnd();
183  }
184 
185  state.setFrustumCulling( true );
186  Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
187  accum.stepsDone = LB_MAX( accum.stepsDone,
188  getSubPixel().size * getPeriod( ));
189  accum.transfer = true;
190 }
191 
192 void Channel::frameAssemble( const eq::uint128_t& frameID )
193 {
194  if( stopRendering( ))
195  return;
196 
197  if( _isDone( ))
198  return;
199 
200  Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
201 
202  if( getPixelViewport() != _currentPVP )
203  {
204  accum.transfer = true;
205 
206  if( accum.buffer && !accum.buffer->usesFBO( ))
207  {
208  LBWARN << "Current viewport different from view viewport, "
209  << "idle anti-aliasing not implemented." << std::endl;
210  accum.step = 0;
211  }
212 
213  eq::Channel::frameAssemble( frameID );
214  return;
215  }
216  // else
217 
218  accum.transfer = true;
219  const eq::Frames& frames = getInputFrames();
220 
221  for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i )
222  {
223  eq::Frame* frame = *i;
224  const eq::SubPixel& curSubPixel = frame->getSubPixel();
225 
226  if( curSubPixel != eq::SubPixel::ALL )
227  accum.transfer = false;
228 
229  accum.stepsDone = LB_MAX( accum.stepsDone, frame->getSubPixel().size *
230  frame->getPeriod( ));
231  }
232 
233  applyBuffer();
234  applyViewport();
236 
237  try
238  {
239  eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer );
240  }
241  catch( const co::Exception& e )
242  {
243  LBWARN << e.what() << std::endl;
244  }
245 
247 }
248 
249 void Channel::frameReadback( const eq::uint128_t& frameID )
250 {
251  if( stopRendering() || _isDone( ))
252  return;
253 
254  const FrameData& frameData = _getFrameData();
255  const eq::Frames& frames = getOutputFrames();
256  for( eq::FramesCIter i = frames.begin(); i != frames.end(); ++i )
257  {
258  eq::Frame* frame = *i;
259  // OPT: Drop alpha channel from all frames during network transport
260  frame->setAlphaUsage( false );
261 
262  if( frameData.isIdle( ))
263  frame->setQuality( eq::Frame::BUFFER_COLOR, 1.f );
264  else
265  frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality());
266 
267  if( frameData.useCompression( ))
268  frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_AUTO );
269  else
270  frame->useCompressor( eq::Frame::BUFFER_COLOR, EQ_COMPRESSOR_NONE );
271  }
272 
273  eq::Channel::frameReadback( frameID );
274 }
275 
276 void Channel::frameStart( const eq::uint128_t& frameID,
277  const uint32_t frameNumber )
278 {
279  if( stopRendering( ))
280  return;
281 
282  for( size_t i = 0; i < eq::NUM_EYES; ++i )
283  _accum[ i ].stepsDone = 0;
284 
285  eq::Channel::frameStart( frameID, frameNumber );
286 }
287 
288 void Channel::frameViewStart( const eq::uint128_t& frameID )
289 {
290  if( stopRendering( ))
291  return;
292 
293  _currentPVP = getPixelViewport();
294  _initJitter();
295  eq::Channel::frameViewStart( frameID );
296 }
297 
298 void Channel::frameFinish( const eq::uint128_t& frameID,
299  const uint32_t frameNumber )
300 {
301  if( stopRendering( ))
302  return;
303 
304  for( size_t i = 0; i < eq::NUM_EYES; ++i )
305  {
306  Accum& accum = _accum[ i ];
307  if( accum.step > 0 )
308  {
309  if( int32_t( accum.stepsDone ) > accum.step )
310  accum.step = 0;
311  else
312  accum.step -= accum.stepsDone;
313  }
314  }
315 
316  eq::Channel::frameFinish( frameID, frameNumber );
317 }
318 
319 void Channel::frameViewFinish( const eq::uint128_t& frameID )
320 {
321  if( stopRendering( ))
322  return;
323 
324  applyBuffer();
325 
326  const FrameData& frameData = _getFrameData();
327  Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
328 
329  if( accum.buffer )
330  {
331  const eq::PixelViewport& pvp = getPixelViewport();
332  const bool isResized = accum.buffer->resize( pvp );
333 
334  if( isResized )
335  {
336  const View* view = static_cast< const View* >( getView( ));
337  accum.buffer->clear();
338  accum.step = view->getIdleSteps();
339  accum.stepsDone = 0;
340  }
341  else if( frameData.isIdle( ))
342  {
344 
345  if( !_isDone() && accum.transfer )
346  accum.buffer->accum();
347  accum.buffer->display();
348 
350  }
351  }
352 
353  applyViewport();
354  _drawOverlay();
355  _drawHelp();
356 
357  if( frameData.useStatistics())
358  drawStatistics();
359 
360  int32_t steps = 0;
361  if( frameData.isIdle( ))
362  {
363  for( size_t i = 0; i < eq::NUM_EYES; ++i )
364  steps = LB_MAX( steps, _accum[i].step );
365  }
366  else
367  {
368  const View* view = static_cast< const View* >( getView( ));
369  steps = view ? view->getIdleSteps() : 0;
370  }
371 
372  // if _jitterStep == 0 and no user redraw event happened, the app will exit
373  // FSAA idle mode and block on the next redraw event.
374  eq::Config* config = getConfig();
375  config->sendEvent( IDLE_AA_LEFT ) << steps;
376 
377  eq::Channel::frameViewFinish( frameID );
378 }
379 
380 bool Channel::useOrtho() const
381 {
382  const FrameData& frameData = _getFrameData();
383  return frameData.useOrtho();
384 }
385 
386 const FrameData& Channel::_getFrameData() const
387 {
388  const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
389  return pipe->getFrameData();
390 }
391 
392 bool Channel::_isDone() const
393 {
394  const FrameData& frameData = _getFrameData();
395  if( !frameData.isIdle( ))
396  return false;
397 
398  const eq::SubPixel& subpixel = getSubPixel();
399  const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
400  return int32_t( subpixel.index ) >= accum.step;
401 }
402 
403 void Channel::_initJitter()
404 {
405  if( !_initAccum( ))
406  return;
407 
408  const FrameData& frameData = _getFrameData();
409  if( frameData.isIdle( ))
410  return;
411 
412  const View* view = static_cast< const View* >( getView( ));
413  if( !view )
414  return;
415 
416  const int32_t idleSteps = view->getIdleSteps();
417  if( idleSteps == 0 )
418  return;
419 
420  // ready for the next FSAA
421  Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
422  if( accum.buffer )
423  accum.buffer->clear();
424  accum.step = idleSteps;
425 }
426 
427 bool Channel::_initAccum()
428 {
429  View* view = static_cast< View* >( getNativeView( ));
430  if( !view ) // Only alloc accum for dest
431  return true;
432 
433  const eq::Eye eye = getEye();
434  Accum& accum = _accum[ lunchbox::getIndexOfLastBit( eye ) ];
435 
436  if( accum.buffer ) // already done
437  return true;
438 
439  if( accum.step == -1 ) // accum init failed last time
440  return false;
441 
442  // Check unsupported cases
444  {
445  for( size_t i = 0; i < eq::NUM_EYES; ++i )
446  {
447  if( _accum[ i ].buffer )
448  {
449  LBWARN << "glAccum-based accumulation does not support "
450  << "stereo, disabling idle anti-aliasing."
451  << std::endl;
452  for( size_t j = 0; j < eq::NUM_EYES; ++j )
453  {
454  delete _accum[ j ].buffer;
455  _accum[ j ].buffer = 0;
456  _accum[ j ].step = -1;
457  }
458 
459  view->setIdleSteps( 0 );
460  return false;
461  }
462  }
463  }
464 
465  // set up accumulation buffer
466  accum.buffer = new eq::util::Accum( glewGetContext( ));
467  const eq::PixelViewport& pvp = getPixelViewport();
468  LBASSERT( pvp.isValid( ));
469 
470  if( !accum.buffer->init( pvp, getWindow()->getColorFormat( )) ||
471  accum.buffer->getMaxSteps() < 256 )
472  {
473  LBWARN <<"Accumulation buffer initialization failed, "
474  << "idle AA not available." << std::endl;
475  delete accum.buffer;
476  accum.buffer = 0;
477  accum.step = -1;
478  return false;
479  }
480 
481  // else
482  LBVERB << "Initialized "
483  << (accum.buffer->usesFBO() ? "FBO accum" : "glAccum")
484  << " buffer for " << getName() << " " << getEye()
485  << std::endl;
486 
487  view->setIdleSteps( accum.buffer ? 256 : 0 );
488  return true;
489 }
490 
491 bool Channel::stopRendering() const
492 {
493  return getPipe()->getCurrentFrame() < _frameRestart;
494 }
495 
496 eq::Vector2f Channel::getJitter() const
497 {
498  const FrameData& frameData = _getFrameData();
499  const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
500 
501  if( !frameData.isIdle() || accum.step <= 0 )
502  return eq::Channel::getJitter();
503 
504  const View* view = static_cast< const View* >( getView( ));
505  if( !view || view->getIdleSteps() != 256 )
506  return eq::Vector2f::ZERO;
507 
508  const eq::Vector2i jitterStep = _getJitterStep();
509  if( jitterStep == eq::Vector2i::ZERO )
510  return eq::Vector2f::ZERO;
511 
512  const eq::PixelViewport& pvp = getPixelViewport();
513  const float pvp_w = float( pvp.w );
514  const float pvp_h = float( pvp.h );
515  const float frustum_w = float(( getFrustum().get_width( )));
516  const float frustum_h = float(( getFrustum().get_height( )));
517 
518  const float pixel_w = frustum_w / pvp_w;
519  const float pixel_h = frustum_h / pvp_h;
520 
521  const float sampleSize = 16.f; // sqrt( 256 )
522  const float subpixel_w = pixel_w / sampleSize;
523  const float subpixel_h = pixel_h / sampleSize;
524 
525  // Sample value randomly computed within the subpixel
526  lunchbox::RNG rng;
527  const eq::Pixel& pixel = getPixel();
528 
529  const float i = ( rng.get< float >() * subpixel_w +
530  float( jitterStep.x( )) * subpixel_w ) / float( pixel.w );
531  const float j = ( rng.get< float >() * subpixel_h +
532  float( jitterStep.y( )) * subpixel_h ) / float( pixel.h );
533 
534  return eq::Vector2f( i, j );
535 }
536 
537 static const uint32_t _primes[100] = {
538  739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
539  839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
540  947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
541  1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109,
542  1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
543  1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
544  1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
545  1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 };
546 
547 eq::Vector2i Channel::_getJitterStep() const
548 {
549  const eq::SubPixel& subPixel = getSubPixel();
550  const uint32_t channelID = subPixel.index;
551  const View* view = static_cast< const View* >( getView( ));
552  if( !view )
553  return eq::Vector2i::ZERO;
554 
555  const uint32_t totalSteps = uint32_t( view->getIdleSteps( ));
556  if( totalSteps != 256 )
557  return eq::Vector2i::ZERO;
558 
559  const Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
560  const uint32_t subset = totalSteps / getSubPixel().size;
561  const uint32_t index = ( accum.step * _primes[ channelID % 100 ] )%subset +
562  ( channelID * subset );
563  const uint32_t sampleSize = 16;
564  const int dx = index % sampleSize;
565  const int dy = index / sampleSize;
566 
567  return eq::Vector2i( dx, dy );
568 }
569 
570 const Model* Channel::_getModel()
571 {
572  Config* config = static_cast< Config* >( getConfig( ));
573  const View* view = static_cast< const View* >( getView( ));
574  const FrameData& frameData = _getFrameData();
575  LBASSERT( !view || dynamic_cast< const View* >( getView( )));
576 
577  eq::uint128_t id = view ? view->getModelID() : frameData.getModelID();
578  if( id == 0 )
579  id = frameData.getModelID();
580  if( id != _modelID )
581  {
582  _model = config->getModel( id );
583  _modelID = id;
584  }
585 
586  return _model;
587 }
588 
589 void Channel::_drawModel( const Model* scene )
590 {
591  Window* window = static_cast< Window* >( getWindow( ));
592  VertexBufferState& state = window->getState();
593  const FrameData& frameData = _getFrameData();
594 
595  if( frameData.getColorMode() == COLOR_MODEL && scene->hasColors( ))
596  state.setColors( true );
597  else
598  state.setColors( false );
599  state.setChannel( this );
600 
601  // Compute cull matrix
602  const eq::Matrix4f& rotation = frameData.getCameraRotation();
603  const eq::Matrix4f& modelRotation = frameData.getModelRotation();
604  eq::Matrix4f position = eq::Matrix4f::IDENTITY;
605  position.set_translation( frameData.getCameraPosition());
606 
607  const eq::Frustumf& frustum = getFrustum();
608  const eq::Matrix4f projection = useOrtho() ? frustum.compute_ortho_matrix():
609  frustum.compute_matrix();
610  const eq::Matrix4f& view = getHeadTransform();
611  const eq::Matrix4f model = rotation * position * modelRotation;
612 
613  state.setProjectionModelViewMatrix( projection * view * model );
614  state.setRange( &getRange().start);
615 
616  const eq::Pipe* pipe = getPipe();
617  const GLuint program = state.getProgram( pipe );
618  if( program != VertexBufferState::INVALID )
619  glUseProgram( program );
620 
621  scene->cullDraw( state );
622 
623  state.setChannel( 0 );
624  if( program != VertexBufferState::INVALID )
625  glUseProgram( 0 );
626 
627  const InitData& initData =
628  static_cast<Config*>( getConfig( ))->getInitData();
629  if( initData.useROI( ))
630  // declare empty region in case nothing is in frustum
631  declareRegion( eq::PixelViewport( ));
632  else
634 
635 #ifndef NDEBUG // region border
636  const eq::PixelViewport& pvp = getPixelViewport();
637  const eq::PixelViewport& region = getRegion();
638 
639  glMatrixMode( GL_PROJECTION );
640  glLoadIdentity();
641  glOrtho( 0.f, pvp.w, 0.f, pvp.h, -1.f, 1.f );
642  glMatrixMode( GL_MODELVIEW );
643  glLoadIdentity();
644 
645  const eq::View* currentView = getView();
646  if( frameData.getColorMode() == COLOR_DEMO )
647  {
648  const eq::Vector3ub color = getUniqueColor();
649  glColor3ub( color.r(), color.g(), color.b() );
650  }
651  else if( currentView &&
652  frameData.getCurrentViewID() == currentView->getID( ))
653  {
654  glColor3f( 0.f, 0.f, 0.f );
655  }
656  else
657  glColor3f( 1.f, 1.f, 1.f );
658  glNormal3f( 0.f, 0.f, 1.f );
659 
660  const eq::Vector4f rect( float( region.x ) + .5f, float( region.y ) + .5f,
661  float( region.getXEnd( )) - .5f,
662  float( region.getYEnd( )) - .5f );
663  glBegin( GL_LINE_LOOP ); {
664  glVertex3f( rect[0], rect[1], -.99f );
665  glVertex3f( rect[2], rect[1], -.99f );
666  glVertex3f( rect[2], rect[3], -.99f );
667  glVertex3f( rect[0], rect[3], -.99f );
668  } glEnd();
669 #endif
670 }
671 
672 void Channel::_drawOverlay()
673 {
674  // Draw the overlay logo
675  const Window* window = static_cast<Window*>( getWindow( ));
676  const eq::util::Texture* texture = window->getLogoTexture();
677  if( !texture )
678  return;
679 
680  glMatrixMode( GL_PROJECTION );
681  glLoadIdentity();
683  glMatrixMode( GL_MODELVIEW );
684  glLoadIdentity();
685 
686  glDisable( GL_DEPTH_TEST );
687  glDisable( GL_LIGHTING );
688  glColor3f( 1.0f, 1.0f, 1.0f );
689  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
690 
691  // logo
692  glEnable( GL_BLEND );
693  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
694  const GLenum target = texture->getTarget();
695  glEnable( target );
696  texture->bind();
697  glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
698  glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
699 
700  const float tWidth = float( texture->getWidth( ) );
701  const float tHeight = float( texture->getHeight( ) );
702 
703  const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
704  const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
705 
706  glBegin( GL_QUADS ); {
707  glTexCoord2f( 0, 0 );
708  glVertex3f( 5.0f, 5.0f, 0.0f );
709 
710  glTexCoord2f( width, 0 );
711  glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
712 
713  glTexCoord2f( width, height );
714  glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
715 
716  glTexCoord2f( 0, height );
717  glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
718 
719  } glEnd();
720 
721  glDisable( target );
722  glDisable( GL_BLEND );
723  glEnable( GL_LIGHTING );
724  glEnable( GL_DEPTH_TEST );
725 }
726 
727 void Channel::_drawHelp()
728 {
729  const FrameData& frameData = _getFrameData();
730  std::string message = frameData.getMessage();
731 
732  if( !frameData.showHelp() && message.empty( ))
733  return;
734 
735  applyBuffer();
736  applyViewport();
738 
739  glLogicOp( GL_XOR );
740  glEnable( GL_COLOR_LOGIC_OP );
741  glDisable( GL_LIGHTING );
742  glDisable( GL_DEPTH_TEST );
743 
744  glColor3f( 1.f, 1.f, 1.f );
745 
746  const eq::PixelViewport& pvp = getPixelViewport();
747  const eq::Viewport& vp = getViewport();
748  const float height = pvp.h / vp.h;
749 
750  if( !message.empty( ))
751  {
752  const eq::Window::Font* font = getWindow()->getMediumFont();
753 
754  const float width = pvp.w / vp.w;
755  const float xOffset = vp.x * width;
756 
757  const float yOffset = vp.y * height;
758  const float yPos = 0.618f * height;
759  float y = yPos - yOffset;
760 
761  for( size_t pos = message.find( '\n' ); pos != std::string::npos;
762  pos = message.find( '\n' ))
763  {
764  glRasterPos3f( 10.f - xOffset, y, 0.99f );
765  font->draw( message.substr( 0, pos ));
766  message = message.substr( pos + 1 );
767  y -= 22.f;
768  }
769  // last line
770  glRasterPos3f( 10.f - xOffset, y, 0.99f );
771  font->draw( message );
772  }
773 
774  glMatrixMode( GL_PROJECTION );
775  glLoadIdentity();
777  glMatrixMode( GL_MODELVIEW );
778 
779  if( frameData.showHelp( ))
780  {
781  const eq::Window::Font* font = getWindow()->getSmallFont();
782  std::string help = EqPly::getHelp();
783  float y = height - 16.f;
784 
785  for( size_t pos = help.find( '\n' ); pos != std::string::npos;
786  pos = help.find( '\n' ))
787  {
788  glRasterPos3f( 10.f, y, 0.99f );
789 
790  font->draw( help.substr( 0, pos ));
791  help = help.substr( pos + 1 );
792  y -= 16.f;
793  }
794  // last line
795  glRasterPos3f( 10.f, y, 0.99f );
796  font->draw( help );
797  }
798 
800 }
801 
802 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
803 {
804  // compute dynamic near/far plane of whole model
805  const FrameData& frameData = _getFrameData();
806 
807  const eq::Matrix4f& rotation = frameData.getCameraRotation();
808  const eq::Matrix4f headTransform = getHeadTransform() * rotation;
809 
810  eq::Matrix4f modelInv;
811  compute_inverse( headTransform, modelInv );
812 
813  const eq::Vector3f zero = modelInv * eq::Vector3f::ZERO;
814  eq::Vector3f front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
815 
816  front -= zero;
817  front.normalize();
818  front *= boundingSphere.w();
819 
820  const eq::Vector3f center =
821  frameData.getCameraPosition().get_sub_vector< 3 >() -
822  boundingSphere.get_sub_vector< 3 >();
823  const eq::Vector3f nearPoint = headTransform * ( center - front );
824  const eq::Vector3f farPoint = headTransform * ( center + front );
825 
826  if( useOrtho( ))
827  {
828  LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) >
829  std::numeric_limits< float >::epsilon(),
830  nearPoint << " == " << farPoint );
831  setNearFar( -nearPoint.z(), -farPoint.z() );
832  }
833  else
834  {
835  // estimate minimal value of near plane based on frustum size
836  const eq::Frustumf& frustum = getFrustum();
837  const float width = fabs( frustum.right() - frustum.left() );
838  const float height = fabs( frustum.top() - frustum.bottom() );
839  const float size = LB_MIN( width, height );
840  const float minNear = frustum.near_plane() / size * .001f;
841 
842  const float zNear = LB_MAX( minNear, -nearPoint.z() );
843  const float zFar = LB_MAX( zNear * 2.f, -farPoint.z() );
844 
845  setNearFar( zNear, zFar );
846  }
847 }
848 
849 }
A configuration is a visualization session driven by an application.
virtual void setupAssemblyState()
Setup the OpenGL state for a readback or assemble operation.
virtual void frameClear(const uint128_t &frameID)
Clear the frame buffer.
virtual void applyViewport() const
Apply the OpenGL viewport for the current rendering task.
virtual void frameStart(const uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
virtual void drawStatistics()
Draw a statistics overlay.
A View is a 2D area of a Layout.
virtual void frameAssemble(const uint128_t &frameID)
Assemble all input frames.
A Window represents an on-screen or off-screen drawable.
virtual Vector2f getJitter() const
const GLEWContext * glewGetContext() const
Get the GLEW context for this channel.
const Frames & getInputFrames()
void applyScreenFrustum() const
Apply an orthographic frustum for pixel-based 2D operations.
virtual void resetRegions()
Reset the declared regions of interest.
A wrapper around AGL, WGL and GLX bitmap fonts.
virtual void frameFinish(const uint128_t &frameID, const uint32_t frameNumber)
Finish rendering a frame.
const Frames & getOutputFrames()
virtual void applyBuffer()
Apply the current rendering buffer, including the color mask.
void draw(const std::string &text) const
Draw text on the current raster position.
const SubPixel & getSubPixel() const
int32_t getHeight() const
uint32_t size
Total number of contributors.
Definition: subPixel.h:102
virtual bool configExit()
Exit this channel.
A Pipe represents a graphics card (GPU) on a Node.
uint32_t getPeriod() const
PixelViewport getRegion() const
View * getView()
Get the channel&#39;s current View.
A window represent an OpenGL drawable and context.
bool usesFBO() const
Test if the accumulation uses the FBO implementation.
Pipe * getPipe()
Render using the colors defined in the ply file.
Definition: eqPly.h:78
void sendEvent(ConfigEvent &event)
Send an (old) event to the application node.
void bind() const
Bind the texture.
virtual bool configExit()
Exit this channel.
static uint32_t assembleFrames(const Frames &frames, Channel *channel, util::Accum *accum)
Assemble all frames in an arbitrary order using the fastest implemented algorithm on the given channe...
const Matrix4f & getHeadTransform() const
Return the view matrix.
virtual bool useOrtho() const
Select perspective or orthographic rendering.
The representation of one GPU.
const Vector3ub & getUniqueColor() const
void useCompressor(const Frame::Buffer buffer, const uint32_t name)
Sets a compressor for compression for following transmissions.
View * getNativeView()
Get the channel&#39;s native view.
A holder for a frame data and related parameters.
Definition: client/frame.h:42
std::vector< Frame * > Frames
A vector of pointers to eq::Frame.
virtual bool configInit(const uint128_t &initID)
Initialize this channel.
virtual void declareRegion(const eq::PixelViewport &region)
Declare a region covered by the current draw or assemble operation.
EQFABRIC_INL void setNearFar(const float nearPlane, const float farPlane)
Set the near and far planes for this channel.
A C++ class to abstract an accumulation buffer.
Definition: accum.h:39
Frames::const_iterator FramesCIter
A const_iterator over a eq::Frame vector.
virtual void frameDraw(const uint128_t &frameID)
Draw the scene.
A wrapper around OpenGL textures.
Definition: texture.h:38
virtual void frameViewFinish(const uint128_t &frameID)
Finish updating a destination channel.
const PixelViewport & getPixelViewport() const
void setAlphaUsage(const bool useAlpha)
Set alpha usage for newly allocated images.
virtual void frameStart(const eq::uint128_t &frameID, const uint32_t frameNumber)
Start rendering a frame.
int32_t getWidth() const
const std::string & getName() const
Config * getConfig()
virtual void frameViewStart(const uint128_t &frameID)
Start updating a destination channel.
uint32_t getCurrentFrame() const
Return the current frame number.
virtual void frameReadback(const uint128_t &frameID)
Read back the rendered frame buffer into the output frames.
virtual void frameDraw(const eq::uint128_t &frameID)
Draw the scene.
Use a unique color to demonstrate decomposition.
Definition: eqPly.h:79
unsigned getTarget() const
void setQuality(const Frame::Buffer buffer, const float quality)
Set the minimum quality after compression.
virtual void resetAssemblyState()
Reset the OpenGL state after an assembly operation.