Show
Ignore:
Timestamp:
03/03/08 19:12:21 (7 years ago)
Author:
robert
Message:

Implemented fade between layers using MultiTextureControl? node

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgmultitexturecontrol/osgmultitexturecontrol.cpp

    r7902 r7903  
    2222 
    2323#include <osg/Texture2D> 
    24 #include <osg/TexEnv> 
    25 #include <osg/TexGen> 
     24#include <osg/io_utils> 
    2625 
    2726#include <osgDB/Registry> 
     
    7271} 
    7372 
     73/** Callback used to track the elevation of the camera and update the texture weights in an MultiTextureControl node.*/ 
     74class ElevationLayerBlendingCallback : public osg::NodeCallback 
     75{ 
     76    public: 
     77     
     78        typedef std::vector<double> Elevations; 
     79 
     80        ElevationLayerBlendingCallback(osgFX::MultiTextureControl* mtc, const Elevations& elevations, float animationTime=4.0f): 
     81            _previousFrame(-1), 
     82            _previousTime(0.0), 
     83            _mtc(mtc), 
     84            _elevations(elevations), 
     85            _animationTime(animationTime) {} 
     86     
     87        /** Callback method called by the NodeVisitor when visiting a node.*/ 
     88        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 
     89        {  
     90            if (!nv->getFrameStamp() || _previousFrame==nv->getFrameStamp()->getFrameNumber()) 
     91            { 
     92                // we've already updated for this frame so no need to do it again, just traverse children. 
     93                traverse(node,nv); 
     94                return; 
     95            } 
     96             
     97            float deltaTime = 0.01f; 
     98            if (_previousFrame!=-1) 
     99            { 
     100                deltaTime = float(nv->getFrameStamp()->getReferenceTime() - _previousTime); 
     101            } 
     102             
     103            _previousTime = nv->getFrameStamp()->getReferenceTime(); 
     104            _previousFrame = nv->getFrameStamp()->getFrameNumber(); 
     105 
     106            double elevation = nv->getViewPoint().z(); 
     107         
     108            osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(node); 
     109            if (csn)  
     110            { 
     111                osg::EllipsoidModel* em = csn->getEllipsoidModel(); 
     112                if (em) 
     113                { 
     114                    double X = nv->getViewPoint().x(); 
     115                    double Y = nv->getViewPoint().y(); 
     116                    double Z = nv->getViewPoint().z(); 
     117                    double latitude, longitude; 
     118                    em->convertXYZToLatLongHeight(X,Y,Z,latitude, longitude, elevation); 
     119                } 
     120            } 
     121         
     122            if (_mtc.valid() && !_elevations.empty()) 
     123            { 
     124                unsigned int index = _mtc->getNumTextureWeights()-1; 
     125                for(unsigned int i=0; i<_elevations.size(); ++i) 
     126                { 
     127                    if (elevation>_elevations[i])  
     128                    { 
     129                        index = i; 
     130                        break; 
     131                    } 
     132                } 
     133                 
     134                float delta = std::min(deltaTime/_animationTime, 1.0f); 
     135                 
     136                for(unsigned int i=0; i<_mtc->getNumTextureWeights(); ++i) 
     137                { 
     138                    float currentValue = _mtc->getTextureWeight(i); 
     139                    float desiredValue = (i==index) ? 1.0f : 0.0f; 
     140                    if (desiredValue != currentValue) 
     141                    { 
     142                        if (currentValue<desiredValue) 
     143                        { 
     144                            desiredValue = std::min(currentValue + delta, desiredValue); 
     145                        } 
     146                        else 
     147                        { 
     148                            desiredValue = std::max(currentValue - delta, desiredValue); 
     149                        } 
     150                     
     151                        _mtc->setTextureWeight(i, desiredValue); 
     152                    } 
     153                } 
     154                 
     155            } 
     156         
     157            traverse(node,nv); 
     158        } 
     159 
     160        int                                             _previousFrame; 
     161        double                                          _previousTime; 
     162        float                                           _animationTime; 
     163        osg::observer_ptr<osgFX::MultiTextureControl>   _mtc; 
     164        Elevations                                      _elevations; 
     165}; 
     166 
     167 
    74168int main( int argc, char **argv ) 
    75169{ 
     
    78172    
    79173    // construct the viewer. 
    80     osgViewer::Viewer viewer; 
     174    osgViewer::Viewer viewer(arguments); 
     175 
     176    // quick hack to work around threading issue with osgFX::MultiTextureControl node's updating of 
     177    // its StateAttributes. 
     178    viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); 
    81179 
    82180    // load the nodes from the commandline arguments. 
     
    90188     
    91189    osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(rootnode); 
    92     if (csn) 
    93     { 
    94         osg::notify(osg::NOTICE)<<"Found CSN"<<csn<<std::endl; 
    95     } 
    96  
     190 
     191    unsigned int numLayers = 1; 
    97192    osgFX::MultiTextureControl* mtc = findTopMostNodeOfType<osgFX::MultiTextureControl>(rootnode); 
    98193    if (mtc) 
    99194    { 
    100         osg::notify(osg::NOTICE)<<"Found MTC "<<mtc<<std::endl; 
    101     } 
     195        numLayers = mtc->getNumTextureWeights(); 
     196    } 
     197     
     198    if (numLayers<2) 
     199    { 
     200        osg::notify(osg::NOTICE)<<"Warning: scene must have MultiTextureControl node with at least 2 texture units defined."<<std::endl; 
     201        return 1; 
     202    } 
     203     
     204    double maxElevationTransition = 1e6; 
     205    ElevationLayerBlendingCallback::Elevations elevations; 
     206    for(unsigned int i=0; i<numLayers; ++i) 
     207    { 
     208        elevations.push_back(maxElevationTransition); 
     209        maxElevationTransition /= 2.0; 
     210    } 
     211     
     212    ElevationLayerBlendingCallback* elbc = new ElevationLayerBlendingCallback(mtc, elevations); 
     213 
     214    // assign to the most appropriate node (the CoordinateSystemNode is best as it provides the elevation on the globe.) 
     215    if (csn) csn->setCullCallback(elbc);     
     216    else if (mtc) mtc->setCullCallback(elbc); 
     217    else rootnode->setCullCallback(elbc); 
    102218 
    103219    // add terrain manipulator