00001
00002
00003
00004
00005
00006 #include "channel.h"
00007
00008 #include "frameData.h"
00009 #include "initData.h"
00010 #include "config.h"
00011 #include "pipe.h"
00012 #include "window.h"
00013 #include "vertexBufferState.h"
00014
00015 using namespace eq::base;
00016 using namespace std;
00017 using namespace mesh;
00018
00019
00020 static GLfloat lightPosition[] = {0.0f, 0.0f, 1.0f, 0.0f};
00021 static GLfloat lightAmbient[] = {0.1f, 0.1f, 0.1f, 1.0f};
00022 static GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00023 static GLfloat lightSpecular[] = {0.8f, 0.8f, 0.8f, 1.0f};
00024
00025
00026 static GLfloat materialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
00027 static GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
00028 static GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f};
00029 static GLint materialShininess = 64;
00030
00031 #ifndef M_SQRT3_2
00032 # define M_SQRT3_2 0.86603f
00033 #endif
00034
00035 namespace eqPly
00036 {
00037 bool Channel::configInit( const uint32_t initID )
00038 {
00039 if( !eq::Channel::configInit( initID ))
00040 return false;
00041
00042 setNearFar( 0.1f, 10.0f );
00043 return true;
00044 }
00045
00046 void Channel::frameDraw( const uint32_t frameID )
00047 {
00048
00049 eq::Channel::frameDraw( frameID );
00050
00051 glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00052 glLightfv( GL_LIGHT0, GL_AMBIENT, lightAmbient );
00053 glLightfv( GL_LIGHT0, GL_DIFFUSE, lightDiffuse );
00054 glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00055
00056 glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
00057 glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
00058 glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
00059 glMateriali( GL_FRONT, GL_SHININESS, materialShininess );
00060
00061 const FrameData::Data& frameData = _getFrameData();
00062 glTranslatef( frameData.translation.x, frameData.translation.y,
00063 frameData.translation.z );
00064 glMultMatrixf( frameData.rotation.ml );
00065
00066 const Config* config = static_cast< Config* >( getConfig( ));
00067 const Model* model = config->getModel();
00068 const eq::Range& range = getRange();
00069
00070 if( !frameData.color )
00071 {
00072 glColor3f( .75f, .75f, .75f );
00073 }
00074 else if( range != eq::Range::ALL )
00075 {
00076 const vmml::Vector3ub color = getUniqueColor();
00077 glColor3ub( color.r, color.g, color.b );
00078 }
00079 else if( model && !model->hasColors( ))
00080 {
00081 glColor3f( .75f, .75f, .75f );
00082 }
00083
00084 if( model )
00085 {
00086 _drawModel( model );
00087 }
00088 else
00089 {
00090 glColor3f( 1.f, 1.f, 0.f );
00091 glNormal3f( 0.f, -1.f, 0.f );
00092 glBegin( GL_TRIANGLE_STRIP );
00093 glVertex3f( .25f, 0.f, .25f );
00094 glVertex3f( -.25f, 0.f, .25f );
00095 glVertex3f( .25f, 0.f, -.25f );
00096 glVertex3f( -.25f, 0.f, -.25f );
00097 glEnd();
00098 }
00099
00100 if( range == eq::Range::ALL )
00101 _drawLogo();
00102
00103 #ifndef NDEBUG
00104 outlineViewport();
00105 #endif
00106 }
00107
00108 void Channel::frameAssemble( const uint32_t frameID )
00109 {
00110 eq::Channel::frameAssemble( frameID );
00111 _drawLogo();
00112 }
00113
00114 const FrameData::Data& Channel::_getFrameData() const
00115 {
00116 const Pipe* pipe = static_cast<Pipe*>( getPipe( ));
00117 return pipe->getFrameData();
00118 }
00119
00120 void Channel::applyFrustum() const
00121 {
00122 const FrameData::Data& frameData = _getFrameData();
00123
00124 if( frameData.ortho )
00125 eq::Channel::applyOrtho();
00126 else
00127 eq::Channel::applyFrustum();
00128 }
00129
00130 void Channel::_drawModel( const Model* model )
00131 {
00132 Window* window = static_cast<Window*>( getWindow() );
00133 VertexBufferState& state = window->getState();
00134 const FrameData::Data& frameData = _getFrameData();
00135 const eq::Range& range = getRange();
00136 vmml::FrustumCullerf culler;
00137
00138 state.setColors( frameData.color && range == eq::Range::ALL &&
00139 model->hasColors() );
00140 _initFrustum( culler, model->getBoundingSphere( ));
00141
00142 const eq::Pipe* pipe = getPipe();
00143 const GLuint program = state.getProgram( pipe );
00144 if( program != VertexBufferState::FAILED )
00145 glUseProgram( program );
00146
00147 model->beginRendering( state );
00148
00149
00150 vector< const VertexBufferBase* > candidates;
00151 candidates.push_back( model );
00152
00153 #ifndef NDEBUG
00154 size_t verticesRendered = 0;
00155 size_t verticesOverlap = 0;
00156 #endif
00157
00158 while( !candidates.empty() )
00159 {
00160 const VertexBufferBase* treeNode = candidates.back();
00161 candidates.pop_back();
00162
00163
00164 if( treeNode->getRange()[0] >= range.end ||
00165 treeNode->getRange()[1] < range.start )
00166 continue;
00167
00168
00169 const vmml::Visibility visibility =
00170 culler.testSphere( treeNode->getBoundingSphere( ));
00171
00172 switch( visibility )
00173 {
00174 case vmml::VISIBILITY_FULL:
00175
00176 if( range == eq::Range::ALL ||
00177 ( treeNode->getRange()[0] >= range.start &&
00178 treeNode->getRange()[1] < range.end ))
00179 {
00180 treeNode->render( state );
00181
00182 #ifndef NDEBUG
00183 verticesRendered += treeNode->getNumberOfVertices();
00184 #endif
00185 break;
00186 }
00187
00188
00189 case vmml::VISIBILITY_PARTIAL:
00190 {
00191 const VertexBufferBase* left = treeNode->getLeft();
00192 const VertexBufferBase* right = treeNode->getRight();
00193
00194 if( !left && !right )
00195 {
00196 if( treeNode->getRange()[0] >= range.start )
00197 {
00198 treeNode->render( state );
00199
00200 #ifndef NDEBUG
00201 verticesRendered += treeNode->getNumberOfVertices();
00202 if( visibility == vmml::VISIBILITY_PARTIAL )
00203 verticesOverlap += treeNode->getNumberOfVertices();
00204 #endif
00205 }
00206
00207 }
00208 else
00209 {
00210 if( left )
00211 candidates.push_back( left );
00212 if( right )
00213 candidates.push_back( right );
00214 }
00215 break;
00216 }
00217 case vmml::VISIBILITY_NONE:
00218
00219 break;
00220 }
00221 }
00222
00223 model->endRendering( state );
00224
00225 if( program != VertexBufferState::FAILED )
00226 glUseProgram( 0 );
00227
00228 #ifndef NDEBUG
00229 const size_t verticesTotal = model->getNumberOfVertices();
00230 EQLOG( LOG_CULL )
00231 << getName() << " rendered " << verticesRendered * 100 / verticesTotal
00232 << "% of model, overlap <= " << verticesOverlap * 100 / verticesTotal
00233 << "%" << endl;
00234 #endif
00235 }
00236
00237 void Channel::_drawLogo()
00238 {
00239 const Window* window = static_cast<Window*>( getWindow( ));
00240 GLuint texture;
00241 vmml::Vector2i size;
00242
00243 window->getLogoTexture( texture, size );
00244 if( !texture )
00245 return;
00246
00247 glMatrixMode( GL_PROJECTION );
00248 glLoadIdentity();
00249 applyScreenFrustum();
00250 glMatrixMode( GL_MODELVIEW );
00251 glLoadIdentity();
00252
00253 glDisable( GL_DEPTH_TEST );
00254 glDisable( GL_LIGHTING );
00255 glEnable( GL_BLEND );
00256 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00257
00258 glEnable( GL_TEXTURE_RECTANGLE_ARB );
00259 glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
00260 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
00261 GL_LINEAR );
00262 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
00263 GL_LINEAR );
00264
00265 glColor3f( 1.0f, 1.0f, 1.0f );
00266 glBegin( GL_TRIANGLE_STRIP ); {
00267 glTexCoord2f( 0.0f, 0.0f );
00268 glVertex3f( 5.0f, 5.0f, 0.0f );
00269
00270 glTexCoord2f( size.x, 0.0f );
00271 glVertex3f( size.x + 5.0f, 5.0f, 0.0f );
00272
00273 glTexCoord2f( 0.0f, size.y );
00274 glVertex3f( 5.0f, size.y + 5.0f, 0.0f );
00275
00276 glTexCoord2f( size.x, size.y );
00277 glVertex3f( size.x + 5.0f, size.y + 5.0f, 0.0f );
00278 } glEnd();
00279
00280 glDisable( GL_TEXTURE_RECTANGLE_ARB );
00281 glDisable( GL_BLEND );
00282 glEnable( GL_LIGHTING );
00283 glEnable( GL_DEPTH_TEST );
00284 }
00285
00286 void Channel::_initFrustum( vmml::FrustumCullerf& culler,
00287 const vmml::Vector4f& boundingSphere )
00288 {
00289
00290 const FrameData::Data& frameData = _getFrameData();
00291
00292 vmml::Matrix4f view( frameData.rotation );
00293 view.setTranslation( frameData.translation );
00294
00295 const vmml::Frustumf& frustum = getFrustum();
00296 const vmml::Matrix4f& headTransform = getHeadTransform();
00297 const vmml::Matrix4f modelView = headTransform * view;
00298 const vmml::Matrix4f projection = frameData.ortho ?
00299 frustum.computeOrthoMatrix() :
00300 frustum.computeMatrix();
00301
00302 culler.setup( projection * modelView );
00303
00304
00305 vmml::Matrix4f modelInv;
00306 headTransform.getInverse( modelInv );
00307
00308 const vmml::Vector3f zero = modelInv * vmml::Vector3f::ZERO;
00309 vmml::Vector3f front = modelInv * vmml::Vector3f( 0.0f, 0.0f, -1.0f );
00310
00311 front -= zero;
00312 front.normalize();
00313 front.scale( boundingSphere.radius );
00314
00315 const vmml::Vector3f center = vmml::Vector3f( boundingSphere.xyzw ) +
00316 vmml::Vector3f( frameData.translation );
00317 const vmml::Vector3f nearPoint = headTransform * ( center - front );
00318 const vmml::Vector3f farPoint = headTransform * ( center + front );
00319
00320 if( frameData.ortho )
00321 {
00322 EQASSERT( fabs( farPoint.z - nearPoint.z ) >
00323 numeric_limits< float >::epsilon( ));
00324 setNearFar( -nearPoint.z, -farPoint.z );
00325 }
00326 else
00327 {
00328 const float zNear = EQ_MAX( 0.0001f, -nearPoint.z );
00329 const float zFar = EQ_MAX( 0.0002f, -farPoint.z );
00330
00331 setNearFar( zNear, zFar );
00332 }
00333 }
00334 }