osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/ShaderComposition.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 #include <osgEarth/ShaderComposition>
00020 
00021 #include <osgEarth/Registry>
00022 #include <osg/Shader>
00023 #include <osg/Program>
00024 #include <osg/State>
00025 #include <osg/Notify>
00026 #include <sstream>
00027 
00028 #define LC "[VirtualProgram] "
00029 
00030 using namespace osgEarth;
00031 using namespace osgEarth::ShaderComp;
00032 
00033 //------------------------------------------------------------------------
00034 
00035 namespace
00036 {
00038     class StateHack : public osg::State 
00039     {
00040     public:        
00041         typedef std::pair<const osg::StateAttribute*,osg::StateAttribute::OverrideValue> AttributePair;
00042         typedef std::vector<AttributePair> AttributeVec;
00043 
00044         const AttributeVec* getAttributeVec( const osg::StateAttribute* attribute ) const
00045         {
00046             osg::State::AttributeMap::const_iterator i = _attributeMap.find( attribute->getTypeMemberPair() );
00047             return i != _attributeMap.end() ? &(i->second.attributeVec) : 0L;
00048         }
00049 
00050         static const AttributeVec* GetAttributeVec( const osg::State& state, const osg::StateAttribute* attribute ) 
00051         {
00052             const StateHack* sh = reinterpret_cast< const StateHack* >( &state );
00053             return sh->getAttributeVec( attribute );
00054         }
00055     };
00056 }
00057 
00058 //------------------------------------------------------------------------
00059 
00060 // If graphics board has program linking problems set MERGE_SHADERS to 1
00061 // Merge shaders can be used to merge shaders strings into one shader. 
00062 #define MERGE_SHADERS 0
00063 #define NOTIFICATION_MESSAGES 0
00064 
00065 VirtualProgram::VirtualProgram( unsigned int mask ) : 
00066 _mask( mask ) 
00067 {
00068     // because we sometimes update/change the attribute's members from within the apply() method
00069     this->setDataVariance( osg::Object::DYNAMIC );
00070 }
00071 
00072 VirtualProgram::VirtualProgram(const VirtualProgram& rhs, const osg::CopyOp& copyop ) :
00073 osg::Program( rhs, copyop ),
00074 _shaderMap( rhs._shaderMap ),
00075 _mask( rhs._mask ),
00076 _functions( rhs._functions )
00077 {
00078     //nop
00079 }
00080 
00081 osg::Shader*
00082 VirtualProgram::getShader( const std::string& shaderSemantic, osg::Shader::Type type )
00083 {
00084     ShaderMap::key_type key( shaderSemantic, type );
00085     return _shaderMap[ key ].get();
00086 }
00087 
00088 osg::Shader*
00089 VirtualProgram::setShader( const std::string& shaderSemantic, osg::Shader * shader )
00090 {
00091     if( shader->getType() == osg::Shader::UNDEFINED ) 
00092         return NULL;
00093 
00094     ShaderMap::key_type key( shaderSemantic, shader->getType() );
00095 
00096     osg::ref_ptr< osg::Shader >  shaderNew     = shader;
00097     osg::ref_ptr< osg::Shader >& shaderCurrent = _shaderMap[ key ];
00098 
00099     shaderNew->setName( shaderSemantic );
00100 
00101     if( shaderCurrent != shaderNew )
00102     {
00103        shaderCurrent = shaderNew;
00104     }
00105 
00106     //OE_NOTICE << shader->getShaderSource() << std::endl;
00107 
00108     return shaderCurrent.get();
00109 }
00110 
00111 void
00112 VirtualProgram::setFunction(const std::string& functionName,
00113                             const std::string& shaderSource,
00114                             FunctionLocation location,
00115                             float priority)
00116 {
00117     Threading::ScopedMutexLock lock( _functionsMutex );
00118 
00119     OrderedFunctionMap& ofm = _functions[location];
00120     ofm.insert( std::pair<float,std::string>( priority, functionName ) );
00121     osg::Shader::Type type = (int)location <= (int)LOCATION_VERTEX_POST_LIGHTING ?
00122         osg::Shader::VERTEX : osg::Shader::FRAGMENT;
00123     setShader( functionName, new osg::Shader( type, shaderSource ) );
00124 }
00125 
00126 void
00127 VirtualProgram::removeShader( const std::string& shaderSemantic, osg::Shader::Type type )
00128 {
00129     _shaderMap.erase( ShaderMap::key_type( shaderSemantic, type ) );
00130 }
00131 
00132 static unsigned s_applies = 0;
00133 static int      s_framenum = 0;
00134 
00135 void
00136 VirtualProgram::apply( osg::State & state ) const
00137 {
00138     if( _shaderMap.empty() ) // Virtual Program works as normal Program
00139         return Program::apply( state );
00140 
00141     // first, find and collect all the VirtualProgram attributes:
00142     ShaderMap shaderMap;
00143     const StateHack::AttributeVec* av = StateHack::GetAttributeVec( state, this );
00144     if ( av )
00145     {
00146         for( StateHack::AttributeVec::const_iterator i = av->begin(); i != av->end(); ++i )
00147         {
00148             const osg::StateAttribute* sa = i->first;
00149             const VirtualProgram* vp = dynamic_cast< const VirtualProgram* >( sa );
00150             if( vp && ( vp->_mask & _mask ) )
00151             {
00152                 for( ShaderMap::const_iterator i = vp->_shaderMap.begin(); i != vp->_shaderMap.end(); ++i )
00153                 {
00154                     shaderMap[ i->first ] = i->second;
00155                 }
00156             }
00157         }
00158     }
00159 
00160     // next add the local shader components to the map:
00161     for( ShaderMap::const_iterator i = _shaderMap.begin(); i != _shaderMap.end(); ++i )
00162         shaderMap[ i->first ] = i->second;
00163 
00164     if( shaderMap.size() )
00165     {
00166         // next, assemble a list of the shaders in the map so we can compare it:
00167         ShaderList sl;
00168         for( ShaderMap::iterator i = shaderMap.begin(); i != shaderMap.end(); ++i )
00169             sl.push_back( i->second );
00170 
00171         // see if there's already a program associated with this list:
00172         osg::Program* program = 0L;
00173         ProgramMap::iterator p = _programMap.find( sl );
00174         if ( p != _programMap.end() )
00175         {
00176             program = p->second.get();
00177         }
00178         else
00179         {
00180             ShaderFactory* sf = osgEarth::Registry::instance()->getShaderFactory();
00181 
00182             // build a new set of accumulated functions, to support the creation of main()
00183             const_cast<VirtualProgram*>(this)->refreshAccumulatedFunctions( state );
00184                 
00185             osg::Shader* vert_main = sf->createVertexShaderMain( _accumulatedFunctions );
00186             const_cast<VirtualProgram*>(this)->setShader( "osgearth_vert_main", vert_main );
00187             shaderMap[ ShaderSemantic("osgearth_vert_main", osg::Shader::VERTEX) ] = vert_main;
00188 
00189             osg::Shader* frag_main = sf->createFragmentShaderMain( _accumulatedFunctions );
00190             const_cast<VirtualProgram*>(this)->setShader( "osgearth_frag_main", frag_main );
00191             shaderMap[ ShaderSemantic("osgearth_frag_main", osg::Shader::FRAGMENT) ] = frag_main;
00192             
00193             // rebuild the shader list now that we've changed the shader map.
00194             sl.clear();
00195             for( ShaderMap::iterator i = shaderMap.begin(); i != shaderMap.end(); ++i )
00196                 sl.push_back( i->second );
00197 
00198             // Create a new program and add all our shaders.
00199             program = new osg::Program();
00200 
00201 #if !MERGE_SHADERS
00202             for( ShaderList::iterator i = sl.begin(); i != sl.end(); ++i )
00203             {
00204                 program->addShader( i->get() );
00205             }
00206 #else
00207             std::string strFragment;
00208             std::string strVertex;
00209             std::string strGeometry;
00210             
00211             for( ShaderList::iterator i = sl.begin(); i != sl.end(); ++i )
00212             {
00213                 if( i->get()->getType() == osg::Shader::FRAGMENT )
00214                     strFragment += i->get()->getShaderSource();
00215                 else if ( i->get()->getType() == osg::Shader::VERTEX )
00216                     strVertex += i->get()->getShaderSource();
00217                 else if ( i->get()->getType() == osg::Shader::GEOMETRY )
00218                     strGeometry += i->get()->getShaderSource();
00219             }
00220 
00221             if( strFragment.length() > 0 )
00222             {
00223                 program->addShader( new osg::Shader( osg::Shader::FRAGMENT, strFragment ) );
00224             }
00225 
00226             if( strVertex.length() > 0  )
00227             {
00228                 program->addShader( new osg::Shader( osg::Shader::VERTEX, strVertex ) );
00229             }
00230 
00231             if( strGeometry.length() > 0  )
00232             {
00233                 program->addShader( new osg::Shader( osg::Shader::GEOMETRY, strGeometry ) );
00234             }
00235 #endif
00236             // finally, cache the program so we only regenerate it when it changes.
00237             _programMap[ sl ] = program;
00238         }
00239 
00240         // finally, apply the program attribute.
00241         program->apply( state );
00242     }
00243     else
00244     {
00245         Program::apply( state );
00246     }
00247 }
00248 
00249 void
00250 VirtualProgram::getFunctions( FunctionLocationMap& out ) const
00251 {
00252     Threading::ScopedMutexLock lock( const_cast<VirtualProgram*>(this)->_functionsMutex );
00253     out = _functions;
00254 }
00255 
00256 void
00257 VirtualProgram::refreshAccumulatedFunctions( const osg::State& state )
00258 {
00259     // This method searches the state's attribute stack and accumulates all 
00260     // the user functions (including those in this program).
00261 
00262     Threading::ScopedMutexLock lock( _functionsMutex );
00263 
00264     _accumulatedFunctions.clear();
00265 
00266     const StateHack::AttributeVec* av = StateHack::GetAttributeVec( state, this );
00267     for( StateHack::AttributeVec::const_iterator i = av->begin(); i != av->end(); ++i )
00268     {
00269         const osg::StateAttribute* sa = i->first;
00270         const VirtualProgram* vp = dynamic_cast< const VirtualProgram* >( sa );
00271         if( vp && vp != this && ( vp->_mask & _mask ) )
00272         {
00273             FunctionLocationMap rhs;
00274             vp->getFunctions( rhs );
00275 
00276             for( FunctionLocationMap::const_iterator j = rhs.begin(); j != rhs.end(); ++j )
00277             {
00278                 const OrderedFunctionMap& ofm = j->second;
00279                 for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
00280                 {
00281                     _accumulatedFunctions[j->first].insert( *k );
00282                 }
00283             }
00284         }
00285     }
00286 
00287     // add the local ones too:
00288     for( FunctionLocationMap::const_iterator j = _functions.begin(); j != _functions.end(); ++j )
00289     {
00290         const OrderedFunctionMap& ofm = j->second;
00291         for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
00292         {
00293             _accumulatedFunctions[j->first].insert( *k );
00294         }
00295     } 
00296 }
00297 
00298 //----------------------------------------------------------------------------
00299 
00300 osg::Shader*
00301 ShaderFactory::createVertexShaderMain( const FunctionLocationMap& functions ) const
00302 {
00303     FunctionLocationMap::const_iterator i = functions.find( LOCATION_VERTEX_PRE_TEXTURING );
00304     const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
00305 
00306     FunctionLocationMap::const_iterator j = functions.find( LOCATION_VERTEX_PRE_LIGHTING );
00307     const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
00308 
00309     FunctionLocationMap::const_iterator k = functions.find( LOCATION_VERTEX_POST_LIGHTING );
00310     const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
00311 
00312     std::stringstream buf;
00313     buf << "void osgearth_vert_setupTexturing(); \n"
00314         << "void osgearth_vert_setupLighting(); \n"
00315         << "uniform bool osgearth_LightingEnabled; \n"
00316         << "uniform float osgearth_CameraElevation; \n"
00317         << "varying float osgearth_CameraRange; \n";
00318 
00319     if ( preTexture )
00320         for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
00321             buf << "void " << i->second << "(); \n";
00322 
00323     if ( preLighting )
00324         for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
00325             buf << "void " << i->second << "(); \n";
00326 
00327     if ( postLighting )
00328         for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
00329             buf << "void " << i->second << "(); \n";
00330 
00331     buf << "void main(void) \n"
00332         << "{ \n"
00333         << "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
00334 
00335         << "    vec4 position4 = gl_ModelViewMatrix * gl_Vertex; \n"
00336         << "    osgearth_CameraRange = length( position4.xyz ); \n"
00337 
00338 //        << "    vec3 cameraPos = normalize(vec3( osg_ViewMatrixInverse[3][0], osg_ViewMatrixInverse[3][1], osg_ViewMatrixInverse[3][2] ));
00339 
00340         << "    vec3 position = position4.xyz / position4.w; \n"
00341         << "    vec3 normal = normalize( gl_NormalMatrix * gl_Normal ); \n";
00342 
00343     if ( preTexture )
00344         for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
00345             buf << "    " << i->second << "(); \n";
00346 
00347     buf << "    osgearth_vert_setupTexturing(); \n";
00348     
00349     if ( preLighting )
00350         for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
00351             buf << "    " << i->second << "(); \n";
00352 
00353     buf << "    if ( osgearth_LightingEnabled ) \n"
00354         << "        osgearth_vert_setupLighting(); \n";
00355     
00356     if ( postLighting )
00357         for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
00358             buf << "    " << i->second << "(); \n";
00359 
00360     buf << "} \n";
00361 
00362     std::string str = buf.str();
00363     //OE_INFO << str << std::endl;
00364     return new osg::Shader( osg::Shader::VERTEX, str );
00365 }
00366 
00367 
00368 osg::Shader*
00369 ShaderFactory::createFragmentShaderMain( const FunctionLocationMap& functions ) const
00370 {
00371     FunctionLocationMap::const_iterator i = functions.find( LOCATION_FRAGMENT_PRE_TEXTURING );
00372     const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
00373 
00374     FunctionLocationMap::const_iterator j = functions.find( LOCATION_FRAGMENT_PRE_LIGHTING );
00375     const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
00376 
00377     FunctionLocationMap::const_iterator k = functions.find( LOCATION_FRAGMENT_POST_LIGHTING );
00378     const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
00379 
00380     std::stringstream buf;
00381     buf << "void osgearth_frag_applyTexturing( inout vec4 color ); \n"
00382         << "void osgearth_frag_applyLighting( inout vec4 color ); \n";
00383 
00384     if ( preTexture )
00385         for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
00386             buf << "void " << i->second << "( inout vec4 color ); \n";
00387 
00388     if ( preLighting )
00389         for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
00390             buf << "void " << i->second << "( inout vec4 color ); \n";
00391 
00392     if ( postLighting )
00393         for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
00394             buf << "void " << i->second << "( inout vec4 color ); \n";
00395 
00396     buf << "uniform bool osgearth_LightingEnabled; \n"
00397         << "void main(void) \n"
00398         << "{ \n"
00399         << "    vec4 color = vec4(1,1,1,1); \n";
00400 
00401     if ( preTexture )
00402         for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
00403             buf << "    " << i->second << "( color ); \n";
00404 
00405     buf << "    osgearth_frag_applyTexturing( color ); \n";
00406 
00407     if ( preLighting )
00408         for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
00409             buf << "    " << i->second << "( color ); \n";
00410     
00411     buf << "    if (osgearth_LightingEnabled) \n"
00412         << "        osgearth_frag_applyLighting( color ); \n";
00413 
00414     if ( postLighting )
00415         for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
00416             buf << "    " << i->second << "( color ); \n";
00417 
00418     buf << "    gl_FragColor = color; \n"
00419         << "} \n";  
00420 
00421     std::string str = buf.str();
00422     //OE_INFO << str;
00423     return new osg::Shader( osg::Shader::FRAGMENT, str );
00424 }
00425 
00426 
00427 osg::Shader*
00428 ShaderFactory::createDefaultTextureVertexShader( int numTexCoordSets ) const
00429 {
00430     std::stringstream buf;
00431 
00432     buf << "void osgearth_vert_setupTexturing() \n"
00433         << "{ \n";
00434 
00435     //TODO: gl_TexCoord et.al. are depcrecated so we should replace them ...
00436     for(int i=0; i<numTexCoordSets; ++i )
00437     {
00438         buf << "    gl_TexCoord["<< i <<"] = gl_MultiTexCoord"<< i << "; \n";
00439     }
00440         
00441     buf << "} \n";
00442 
00443     std::string str = buf.str();
00444     return new osg::Shader( osg::Shader::VERTEX, str );
00445 }
00446 
00447 
00448 osg::Shader*
00449 ShaderFactory::createDefaultTextureFragmentShader( int numTexImageUnits ) const
00450 {
00451     std::stringstream buf;
00452 
00453     buf << "#version 120 \n";
00454 
00455     if ( numTexImageUnits > 0 )
00456     {
00457         buf << "uniform sampler2D ";
00458         for( int i=0; i<numTexImageUnits; ++i )
00459             buf << "tex" << i << (i+1 < numTexImageUnits? "," : "; \n");
00460     }
00461 
00462     buf << "void osgearth_frag_applyTexturing( inout vec4 color ) \n"
00463         << "{ \n"
00464         << "    vec3 color3 = color.rgb; \n"
00465         << "    vec4 texel; \n";
00466 
00467     for(int i=0; i<numTexImageUnits; ++i )
00468     {
00469         buf << "    texel = texture2D(tex" << i << ", gl_TexCoord["<< i <<"].st); \n"
00470             << "    color3 = mix( color3, texel.rgb, texel.a ); \n";
00471     }
00472         
00473     buf << "    color = vec4(color3,color.a); \n"
00474         << "} \n";
00475 
00476     std::string str = buf.str();
00477     return new osg::Shader( osg::Shader::FRAGMENT, str );
00478 }
00479 
00480 
00481 osg::Shader*
00482 ShaderFactory::createDefaultLightingVertexShader() const
00483 {
00484     static char s_PerVertexLighting_VertexShaderSource[] = 
00485         "void osgearth_vert_setupLighting()                                         \n"
00486         "{                                                                          \n"
00487         "    vec3 normal = normalize( gl_NormalMatrix * gl_Normal );                \n"
00488         "    float NdotL = dot( normal, normalize(gl_LightSource[0].position.xyz) );\n"
00489         "    NdotL = max( 0.0, NdotL );                                             \n"
00490         "    float NdotHV = dot( normal, gl_LightSource[0].halfVector.xyz );        \n"
00491         "    NdotHV = max( 0.0, NdotHV );                                           \n"
00492         "                                                                           \n"
00493         "    gl_FrontColor = gl_FrontLightModelProduct.sceneColor +                 \n"
00494         "                    gl_FrontLightProduct[0].ambient +                      \n"
00495         "                    gl_FrontLightProduct[0].diffuse * NdotL;               \n"
00496         "                                                                           \n"
00497         "    gl_FrontSecondaryColor = vec4(0.0);                                    \n"
00498         "                                                                           \n"
00499         "    if ( NdotL * NdotHV > 0.0 )                                            \n"
00500         "        gl_FrontSecondaryColor = gl_FrontLightProduct[0].specular *        \n"
00501         "                                 pow( NdotHV, gl_FrontMaterial.shininess );\n"
00502         "                                                                           \n"
00503         "    gl_BackColor = gl_FrontColor;                                          \n"
00504         "    gl_BackSecondaryColor = gl_FrontSecondaryColor;                        \n"
00505         "}                                                                          \n";
00506 
00507     return new osg::Shader( osg::Shader::VERTEX, s_PerVertexLighting_VertexShaderSource );
00508 }
00509 
00510 
00511 osg::Shader*
00512 ShaderFactory::createDefaultLightingFragmentShader() const
00513 {
00514     static char s_PerVertexLighting_FragmentShaderSource[] =
00515         "void osgearth_frag_applyLighting( inout vec4 color )                       \n"
00516         "{                                                                          \n"
00517         "    float alpha = color.a;                                                 \n"
00518         "    color = color * gl_Color + gl_SecondaryColor;                          \n"
00519         "    color.a = alpha;                                                       \n"
00520         "}                                                                          \n";
00521 
00522     return new osg::Shader( osg::Shader::FRAGMENT, s_PerVertexLighting_FragmentShaderSource );
00523 }
00524 
00525 //--------------------------------------------------------------------------
00526 
00527 #if 0
00528 // This is just a holding pen for various stuff
00529 
00530 static char s_PerFragmentLighting_VertexShaderSource[] =
00531     "varying vec3 Normal; \n"
00532     "varying vec3 Position; \n"
00533     "void osgearth_vert_setupLighting() \n"
00534     "{ \n"
00535     "    Normal = normal; \n"
00536     "    Position = position; \n"
00537     "} \n";
00538 
00539 static char s_PerFragmentDirectionalLighting_FragmentShaderSource[] =
00540     "varying vec3 Normal; \n"
00541     "varying vec3 Position; \n"
00542     "void osgearth_frag_applyLighting( inout vec4 color ) \n"
00543     "{ \n"
00544     "    vec3 n = normalize( Normal ); \n"
00545     "    float NdotL = dot( n, normalize(gl_LightSource[0].position.xyz) ); \n"
00546     "    NdotL = max( 0.0, NdotL ); \n"
00547     "    float NdotHV = dot( n, gl_LightSource[0].halfVector.xyz ); \n"
00548     "    NdotHV = max( 0.0, NdotHV ); \n"
00549     "    color *= gl_FrontLightModelProduct.sceneColor + \n"
00550     "             gl_FrontLightProduct[0].ambient + \n"
00551     "             gl_FrontLightProduct[0].diffuse * NdotL; \n"
00552     "    if ( NdotL * NdotHV > 0.0 ) \n"
00553     "        color += gl_FrontLightProduct[0].specular * \n"
00554     "                 pow( NdotHV, gl_FrontMaterial.shininess ); \n"
00555     "} \n";
00556 
00557 #endif
00558 
00559 //------------------------------------------------------------------------
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines