00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "channel.h"
00020
00021 #include "initData.h"
00022 #include "config.h"
00023 #include "pipe.h"
00024 #include "view.h"
00025 #include "window.h"
00026 #include "vertexBufferState.h"
00027
00028
00029 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
00030 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
00031 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00032 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
00033
00034
00035 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
00036 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00037 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
00038 static GLint materialShininess = 64;
00039
00040 #ifndef M_SQRT3_2
00041 # define M_SQRT3_2 0.86603f
00042 #endif
00043
00044 namespace eqPly
00045 {
00046 bool Channel::configInit( const uint32_t initID )
00047 {
00048 if( !eq::Channel::configInit( initID ))
00049 return false;
00050
00051 setNearFar( 0.1f, 10.0f );
00052 return true;
00053 }
00054
00055 void Channel::frameClear( const uint32_t frameID )
00056 {
00057 EQ_GL_CALL( applyBuffer( ));
00058 EQ_GL_CALL( applyViewport( ));
00059
00060 const eq::View* view = getView();
00061 const FrameData& frameData = _getFrameData();
00062 if( view && frameData.getCurrentViewID() == view->getID( ))
00063 glClearColor( .4f, .4f, .4f, 1.0f );
00064 #ifndef NDEBUG
00065 else if( getenv( "EQ_TAINT_CHANNELS" ))
00066 {
00067 const eq::Vector3ub color = getUniqueColor();
00068 glClearColor( color.r()/255.0f, color.g()/255.0f, color.b()/255.0f, 1.0f );
00069 }
00070 #endif // NDEBUG
00071 else
00072 glClearColor( 0.f, 0.f, 0.f, 1.0f );
00073
00074 EQ_GL_CALL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ));
00075 }
00076
00077 void Channel::frameDraw( const uint32_t frameID )
00078 {
00079 const Model* model = _getModel();
00080 if( model )
00081 _updateNearFar( model->getBoundingSphere( ));
00082
00083
00084 eq::Channel::frameDraw( frameID );
00085
00086 glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00087 glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00088 glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse );
00089 glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00090
00091 glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
00092 glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
00093 glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
00094 glMateriali( GL_FRONT, GL_SHININESS, materialShininess );
00095
00096 const FrameData& frameData = _getFrameData();
00097 glPolygonMode( GL_FRONT_AND_BACK,
00098 frameData.useWireframe() ? GL_LINE : GL_FILL );
00099
00100 const eq::Vector3f& translation = frameData.getCameraTranslation();
00101
00102 glMultMatrixf( frameData.getCameraRotation().array );
00103 glTranslatef( translation.x(), translation.y(), translation.z() );
00104 glMultMatrixf( frameData.getModelRotation().array );
00105
00106 if( frameData.getColorMode() == COLOR_DEMO )
00107 {
00108 const eq::Vector3ub color = getUniqueColor();
00109 glColor3ub( color.r(), color.g(), color.b() );
00110 }
00111 else
00112 glColor3f( .75f, .75f, .75f );
00113
00114 if( model )
00115 {
00116 _drawModel( model );
00117 }
00118 else
00119 {
00120 glNormal3f( 0.f, -1.f, 0.f );
00121 glBegin( GL_TRIANGLE_STRIP );
00122 glVertex3f( .25f, 0.f, .25f );
00123 glVertex3f( -.25f, 0.f, .25f );
00124 glVertex3f( .25f, 0.f, -.25f );
00125 glVertex3f( -.25f, 0.f, -.25f );
00126 glEnd();
00127 }
00128 }
00129
00130 void Channel::frameReadback( const uint32_t frameID )
00131 {
00132
00133 const eq::FrameVector& frames = getOutputFrames();
00134 for( eq::FrameVector::const_iterator i = frames.begin();
00135 i != frames.end(); ++i )
00136 {
00137 (*i)->setAlphaUsage( false );
00138 }
00139
00140 eq::Channel::frameReadback( frameID );
00141 }
00142
00143 const FrameData& Channel::_getFrameData() const
00144 {
00145 const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
00146 return pipe->getFrameData();
00147 }
00148
00149 void Channel::applyFrustum() const
00150 {
00151 const FrameData& frameData = _getFrameData();
00152
00153 if( frameData.useOrtho( ))
00154 eq::Channel::applyOrtho();
00155 else
00156 eq::Channel::applyFrustum();
00157 }
00158
00159 const Model* Channel::_getModel()
00160 {
00161 Config* config = static_cast< Config* >( getConfig( ));
00162 const View* view = static_cast< const View* >( getView( ));
00163 EQASSERT( !view || dynamic_cast< const View* >( getView( )));
00164
00165 if( view )
00166 return config->getModel( view->getModelID( ));
00167
00168 const FrameData& frameData = _getFrameData();
00169 return config->getModel( frameData.getModelID( ));
00170 }
00171
00172 void Channel::_drawModel( const Model* model )
00173 {
00174 Window* window = static_cast<Window*>( getWindow() );
00175 VertexBufferState& state = window->getState();
00176 const FrameData& frameData = _getFrameData();
00177 const eq::Range& range = getRange();
00178 eq::FrustumCullerf culler;
00179
00180 if( frameData.getColorMode() == COLOR_MODEL && model->hasColors( ))
00181 state.setColors( true );
00182 else
00183 state.setColors( false );
00184
00185 _initFrustum( culler, model->getBoundingSphere( ));
00186
00187 const eq::Pipe* pipe = getPipe();
00188 const GLuint program = state.getProgram( pipe );
00189 if( program != VertexBufferState::INVALID )
00190 glUseProgram( program );
00191
00192 model->beginRendering( state );
00193
00194
00195 std::vector< const mesh::VertexBufferBase* > candidates;
00196 candidates.push_back( model );
00197
00198 #ifndef NDEBUG
00199 size_t verticesRendered = 0;
00200 size_t verticesOverlap = 0;
00201 #endif
00202
00203 while( !candidates.empty() )
00204 {
00205 const mesh::VertexBufferBase* treeNode = candidates.back();
00206 candidates.pop_back();
00207
00208
00209 if( treeNode->getRange()[0] >= range.end ||
00210 treeNode->getRange()[1] < range.start )
00211 continue;
00212
00213
00214 const vmml::Visibility visibility =
00215 culler.test_sphere( treeNode->getBoundingSphere( ));
00216
00217 switch( visibility )
00218 {
00219 case vmml::VISIBILITY_FULL:
00220
00221 if( range == eq::Range::ALL ||
00222 ( treeNode->getRange()[0] >= range.start &&
00223 treeNode->getRange()[1] < range.end ))
00224 {
00225 treeNode->render( state );
00226
00227 #ifndef NDEBUG
00228 verticesRendered += treeNode->getNumberOfVertices();
00229 #endif
00230 break;
00231 }
00232
00233
00234 case vmml::VISIBILITY_PARTIAL:
00235 {
00236 const mesh::VertexBufferBase* left = treeNode->getLeft();
00237 const mesh::VertexBufferBase* right = treeNode->getRight();
00238
00239 if( !left && !right )
00240 {
00241 if( treeNode->getRange()[0] >= range.start )
00242 {
00243 treeNode->render( state );
00244
00245 #ifndef NDEBUG
00246 verticesRendered += treeNode->getNumberOfVertices();
00247 if( visibility == vmml::VISIBILITY_PARTIAL )
00248 verticesOverlap += treeNode->getNumberOfVertices();
00249 #endif
00250 }
00251
00252 }
00253 else
00254 {
00255 if( left )
00256 candidates.push_back( left );
00257 if( right )
00258 candidates.push_back( right );
00259 }
00260 break;
00261 }
00262 case vmml::VISIBILITY_NONE:
00263
00264 break;
00265 }
00266 }
00267
00268 model->endRendering( state );
00269
00270 if( program != VertexBufferState::INVALID )
00271 glUseProgram( 0 );
00272
00273 #ifndef NDEBUG
00274 const size_t verticesTotal = model->getNumberOfVertices();
00275 EQLOG( LOG_CULL )
00276 << getName() << " rendered " << verticesRendered * 100 / verticesTotal
00277 << "% of model, overlap <= " << verticesOverlap * 100 / verticesTotal
00278 << "%" << std::endl;
00279 #endif
00280 }
00281
00282 void Channel::frameViewFinish( const uint32_t frameID )
00283 {
00284 _drawOverlay();
00285 _drawHelp();
00286 }
00287
00288 void Channel::_drawOverlay()
00289 {
00290
00291 const Window* window = static_cast<Window*>( getWindow( ));
00292 GLuint texture;
00293 eq::Vector2i size;
00294
00295 window->getLogoTexture( texture, size );
00296
00297 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
00298 glMatrixMode( GL_PROJECTION );
00299 glLoadIdentity();
00300 applyScreenFrustum();
00301 glMatrixMode( GL_MODELVIEW );
00302 glLoadIdentity();
00303
00304 glDisable( GL_DEPTH_TEST );
00305 glDisable( GL_LIGHTING );
00306 glColor3f( 1.0f, 1.0f, 1.0f );
00307
00308 #if 1
00309
00310 const eq::PixelViewport& pvp = getPixelViewport();
00311 const eq::Viewport& vp = getViewport();
00312 const float w = pvp.w / vp.w - .5f;
00313 const float h = pvp.h / vp.h - .5f;
00314
00315 glBegin( GL_LINE_LOOP );
00316 {
00317 glVertex3f( .5f, .5f, 0.f );
00318 glVertex3f( w, .5f, 0.f );
00319 glVertex3f( w, h, 0.f );
00320 glVertex3f( .5f, h, 0.f );
00321 }
00322 glEnd();
00323 #endif
00324
00325
00326 if( texture )
00327 {
00328 glEnable( GL_BLEND );
00329 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00330
00331 glEnable( GL_TEXTURE_RECTANGLE_ARB );
00332 glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
00333 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
00334 GL_LINEAR );
00335 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
00336 GL_LINEAR );
00337
00338 glBegin( GL_TRIANGLE_STRIP ); {
00339 glTexCoord2f( 0.0f, 0.0f );
00340 glVertex3f( 5.0f, 5.0f, 0.0f );
00341
00342 glTexCoord2f( size.x(), 0.0f );
00343 glVertex3f( size.x() + 5.0f, 5.0f, 0.0f );
00344
00345 glTexCoord2f( 0.0f, size.y() );
00346 glVertex3f( 5.0f, size.y() + 5.0f, 0.0f );
00347
00348 glTexCoord2f( size.x(), size.y() );
00349 glVertex3f( size.x() + 5.0f, size.y() + 5.0f, 0.0f );
00350 } glEnd();
00351
00352 glDisable( GL_TEXTURE_RECTANGLE_ARB );
00353 glDisable( GL_BLEND );
00354 }
00355 glEnable( GL_LIGHTING );
00356 glEnable( GL_DEPTH_TEST );
00357 }
00358
00359 void Channel::_drawHelp()
00360 {
00361 const FrameData& frameData = _getFrameData();
00362 std::string message = frameData.getMessage();
00363
00364 if( !frameData.showHelp() && message.empty( ))
00365 return;
00366
00367 EQ_GL_CALL( applyBuffer( ));
00368 EQ_GL_CALL( applyViewport( ));
00369 EQ_GL_CALL( setupAssemblyState( ));
00370
00371 glDisable( GL_LIGHTING );
00372 glDisable( GL_DEPTH_TEST );
00373
00374 glColor3f( 1.f, 1.f, 1.f );
00375
00376 if( frameData.showHelp( ))
00377 {
00378 const eq::util::BitmapFont& font = getObjectManager()->getDefaultFont();
00379 std::string help = EqPly::getHelp();
00380 float y = 340.f;
00381
00382 for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00383 pos = help.find( '\n' ))
00384 {
00385 glRasterPos3f( 10.f, y, 0.99f );
00386
00387 font.draw( help.substr( 0, pos ));
00388 help = help.substr( pos + 1 );
00389 y -= 16.f;
00390 }
00391
00392 glRasterPos3f( 10.f, y, 0.99f );
00393 font.draw( help );
00394 }
00395
00396 if( !message.empty( ))
00397 {
00398 const eq::util::BitmapFont& font = getObjectManager()->getMediumFont();
00399
00400 const eq::Viewport& vp = getViewport();
00401 const eq::PixelViewport& pvp = getPixelViewport();
00402
00403 const float width = pvp.w / vp.w;
00404 const float xOffset = vp.x * width;
00405
00406 const float height = pvp.h / vp.h;
00407 const float yOffset = vp.y * height;
00408 const float yMiddle = 0.5f * height;
00409 float y = yMiddle - yOffset;
00410
00411 for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00412 pos = message.find( '\n' ))
00413 {
00414 glRasterPos3f( 10.f - xOffset, y, 0.99f );
00415
00416 font.draw( message.substr( 0, pos ));
00417 message = message.substr( pos + 1 );
00418 y -= 22.f;
00419 }
00420
00421 glRasterPos3f( 10.f - xOffset, y, 0.99f );
00422 font.draw( message );
00423 }
00424
00425 EQ_GL_CALL( resetAssemblyState( ));
00426 }
00427
00428 void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
00429 {
00430
00431 const FrameData& frameData = _getFrameData();
00432 const bool ortho = frameData.useOrtho();
00433
00434 const eq::Matrix4f& rotation = frameData.getCameraRotation();
00435 const eq::Matrix4f headTransform = getHeadTransform() * rotation;
00436
00437 eq::Matrix4f modelInv;
00438 compute_inverse( headTransform, modelInv );
00439
00440 const eq::Vector3f zero = modelInv * eq::Vector3f::ZERO;
00441 eq::Vector3f front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );
00442
00443 front -= zero;
00444 front.normalize();
00445 front *= boundingSphere.w();
00446
00447 const eq::Vector3f center = boundingSphere.get_sub_vector< 3 >() +
00448 frameData.getCameraTranslation( ).get_sub_vector< 3 >();
00449 const eq::Vector3f nearPoint = headTransform * ( center - front );
00450 const eq::Vector3f farPoint = headTransform * ( center + front );
00451
00452 if( ortho )
00453 {
00454 EQASSERT( fabs( farPoint.z() - nearPoint.z() ) >
00455 std::numeric_limits< float >::epsilon( ));
00456 setNearFar( -nearPoint.z(), -farPoint.z() );
00457 }
00458 else
00459 {
00460
00461 const eq::Frustumf& frustum = getFrustum();
00462 const float width = fabs( frustum.right() - frustum.left() );
00463 const float height = fabs( frustum.top() - frustum.bottom() );
00464 const float size = EQ_MIN( width, height );
00465 const float minNear = frustum.near_plane() / size * .001f;
00466
00467 const float zNear = EQ_MAX( minNear, -nearPoint.z() );
00468 const float zFar = EQ_MAX( zNear * 2.f, -farPoint.z() );
00469
00470 setNearFar( zNear, zFar );
00471 }
00472 }
00473
00474 void Channel::_initFrustum( eq::FrustumCullerf& culler,
00475 const mesh::BoundingSphere& boundingSphere )
00476 {
00477
00478 const FrameData& frameData = _getFrameData();
00479 const eq::Matrix4f& rotation = frameData.getCameraRotation();
00480 const eq::Matrix4f& modelRotation = frameData.getModelRotation();
00481 eq::Matrix4f translation = eq::Matrix4f::IDENTITY;
00482 translation.set_translation( frameData.getCameraTranslation());
00483
00484 const eq::Matrix4f modelView =
00485 getHeadTransform() * rotation * translation * modelRotation;
00486
00487 const bool ortho = frameData.useOrtho();
00488 const eq::Frustumf& frustum = ortho ? getOrtho() : getFrustum();
00489 const eq::Matrix4f projection = ortho ? frustum.compute_ortho_matrix() :
00490 frustum.compute_matrix();
00491 culler.setup( projection * modelView );
00492 }
00493 }