Changeset 8990

Show
Ignore:
Timestamp:
10/06/08 19:02:20 (6 years ago)
Author:
robert
Message:

Refactored ImageSequence? to provided a cleaner and more robust implementation

Location:
OpenSceneGraph/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/include/osg/ImageSequence

    r8758 r8990  
    2020 
    2121#include <list> 
     22#include <set> 
    2223 
    2324namespace osg { 
     
    4950        virtual double getTimeMultiplier() const { return _timeMultiplier; } 
    5051 
    51         typedef std::list< osg::ref_ptr<osg::Image> >   Images; 
    52         typedef std::list< std::string >                FileNames; 
     52        typedef std::vector< osg::ref_ptr<osg::Image> >   Images; 
     53        typedef std::vector< std::string >                FileNames; 
    5354         
    5455        virtual void seek(double time); 
     
    7677        void addImageFile(const std::string& fileName); 
    7778         
     79        void setImageFile(unsigned int pos, const std::string& fileName); 
     80        std::string getImageFile(unsigned int pos) const; 
     81         
     82        unsigned int getNumImageFiles() const { return _fileNames.size(); } 
     83 
    7884        FileNames& getFileNames() { return _fileNames; } 
    7985        const FileNames& getFileNames() const { return _fileNames; } 
     
    8187        void addImage(osg::Image* image); 
    8288         
     89        void setImage(int s,int t,int r, 
     90                      GLint internalTextureformat, 
     91                      GLenum pixelFormat,GLenum type, 
     92                      unsigned char* data, 
     93                      AllocationMode mode, 
     94                      int packing=1) { Image::setImage(s,t,r,internalTextureformat, pixelFormat, type, data, mode, packing); } 
     95 
     96        void setImage(unsigned int pos, osg::Image* image); 
     97        Image* getImage(unsigned int pos); 
     98        const Image* getImage(unsigned int pos) const; 
     99         
     100        unsigned int getNumImages() const { return _images.size(); } 
     101 
    83102        Images& getImages() { return _images; } 
    84103        const Images& getImages() const { return _images; } 
     
    96115        virtual ~ImageSequence() {} 
    97116         
     117        virtual void applyLoopingMode(); 
     118 
    98119        void setImageToChild(const osg::Image* image); 
    99120         
    100121        void computeTimePerImage(); 
     122 
     123        int imageIndex(double time); 
     124 
    101125 
    102126        double                          _referenceTime; 
     
    108132        double                          _timePerImage; 
    109133 
    110         OpenThreads::Mutex              _mutex; 
     134        mutable OpenThreads::Mutex      _mutex; 
    111135        FileNames                       _fileNames; 
    112         FileNames::iterator             _fileNamesIterator; 
    113         double                          _fileNamesIteratorTime; 
    114136 
    115137        Images                          _images; 
    116138         
    117         typedef std::pair< std::string, osg::ref_ptr<osg::Image> >  FileNameImagePair; 
    118         typedef std::list< FileNameImagePair >  FileNameImageList; 
    119         FileNameImageList               _filesRequested; 
     139        typedef std::set< std::string > FilesRequested; 
     140        FilesRequested                  _filesRequested; 
     141         
     142        int                             _previousAppliedImageIndex; 
    120143                 
    121         Images::iterator                _imageIterator; 
    122         double                          _imageIteratorTime; 
    123144         
    124145        bool                            _seekTimeSet; 
    125146        double                          _seekTime; 
     147         
    126148         
    127149 
  • OpenSceneGraph/trunk/include/osg/ImageStream

    r8755 r8990  
    6666        }; 
    6767         
    68         void setLoopingMode(LoopingMode mode) { _loopingMode = mode; applyLoopingMode(); } 
     68        void setLoopingMode(LoopingMode mode) 
     69        { 
     70            if (_loopingMode == mode) return; 
     71             
     72            _loopingMode = mode; 
     73            applyLoopingMode(); 
     74        } 
     75         
    6976        LoopingMode getLoopingMode() const { return _loopingMode; } 
    7077 
  • OpenSceneGraph/trunk/include/osg/NodeVisitor

    r8685 r8990  
    297297            virtual osg::Image* readImageFile(const std::string& fileName) = 0; 
    298298         
    299             virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp) = 0; 
     299            virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const FrameStamp* framestamp) = 0; 
    300300             
    301301        protected: 
  • OpenSceneGraph/trunk/src/osg/ImageSequence.cpp

    r8917 r8990  
    4545    _length = 1.0; 
    4646    _timePerImage = 1.0; 
    47  
    48     _fileNamesIterator = _fileNames.end(); 
    49     _fileNamesIteratorTime = 0.0; 
    50  
    51     _imageIterator = _images.end(); 
    52     _imageIteratorTime = 0.0; 
    5347     
    5448    _seekTime = 0.0; 
    5549    _seekTimeSet = false; 
     50     
     51    _previousAppliedImageIndex = -1; 
    5652} 
    5753 
     
    6460    _timePerImage(is._timePerImage) 
    6561{ 
    66     _fileNamesIterator = _fileNames.end(); 
    67     _fileNamesIteratorTime = 0.0; 
    68  
    69     _imageIterator = _images.end(); 
    70     _imageIteratorTime = 0.0; 
    71  
    7262    _seekTime = is._seekTime; 
    7363    _seekTimeSet = is._seekTimeSet; 
     64 
     65    _previousAppliedImageIndex = -1; 
    7466} 
    7567 
     
    10799void ImageSequence::setLength(double length) 
    108100{ 
     101    if (length<=0.0) 
     102    { 
     103        osg::notify(osg::NOTICE)<<"ImageSequence::setLength("<<length<<") invalid length value, must be greater than 0."<<std::endl; 
     104        return; 
     105    } 
     106     
    109107    _length = length; 
    110108    computeTimePerImage(); 
     
    118116} 
    119117 
     118void ImageSequence::setImageFile(unsigned int pos, const std::string& fileName) 
     119{ 
     120    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     121 
     122    if (pos>=_fileNames.size()) _fileNames.resize(pos); 
     123    _fileNames[pos] = fileName; 
     124} 
     125 
     126std::string ImageSequence::getImageFile(unsigned int pos) const 
     127{ 
     128    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     129    return pos<_fileNames.size() ? _fileNames[pos] : std::string(); 
     130} 
     131         
    120132void ImageSequence::addImageFile(const std::string& fileName) 
    121133{ 
     
    123135    _fileNames.push_back(fileName); 
    124136    computeTimePerImage(); 
    125      
    126     if (_fileNamesIterator==_fileNames.end()) 
    127     { 
    128         _fileNamesIterator = _fileNames.begin(); 
    129         _fileNamesIteratorTime = _referenceTime; 
    130     } 
     137} 
     138 
     139void ImageSequence::setImage(unsigned int pos, osg::Image* image) 
     140{ 
     141    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     142 
     143    osg::notify(osg::INFO)<<"ImageSequence::setImage("<<pos<<","<<image->getFileName()<<")"<<std::endl; 
     144 
     145    if (pos>=_images.size()) _images.resize(pos+1); 
     146     
     147    _images[pos] = image; 
     148 
     149    // prune from file requested list. 
     150    FilesRequested::iterator itr = _filesRequested.find(image->getFileName()); 
     151    if (itr!=_filesRequested.end()) _filesRequested.erase(itr); 
     152} 
     153 
     154Image* ImageSequence::getImage(unsigned int pos) 
     155{ 
     156    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     157    return pos<_images.size() ? _images[pos].get() : 0; 
     158} 
     159 
     160const Image* ImageSequence::getImage(unsigned int pos) const 
     161{ 
     162    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     163    return pos<_images.size() ? _images[pos].get() : 0; 
    131164} 
    132165 
    133166void ImageSequence::addImage(osg::Image* image) 
    134167{ 
    135     OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
    136  
    137     if (!_filesRequested.empty()) 
    138     { 
    139         // follows is a mechanism that ensures that requested images 
    140         // get merged in the correct time order. 
    141         if (_filesRequested.front().first != image->getFileName()) 
    142         { 
    143             for(FileNameImageList::iterator itr = _filesRequested.begin(); 
    144                 itr != _filesRequested.end(); 
    145                 ++itr) 
    146             { 
    147                 if (itr->first == image->getFileName()) 
    148                 { 
    149                     osg::notify(osg::NOTICE)<<"inserting image into waiting queue : "<<image->getFileName()<<std::endl; 
    150                     itr->second = image; 
    151                     return; 
    152                 } 
    153             } 
    154             // osg::notify(osg::NOTICE)<<"image not expected : "<<image->getFileName()<<std::endl; 
    155             _images.push_back(image); 
    156         } 
    157         else 
    158         { 
    159             // osg::notify(osg::NOTICE)<<"merging image in order expected : "<<image->getFileName()<<std::endl; 
    160             _images.push_back(image); 
    161  
    162             _filesRequested.pop_front(); 
    163              
    164             FileNameImageList::iterator itr; 
    165             for(itr = _filesRequested.begin(); 
    166                 itr != _filesRequested.end() && itr->second.valid(); 
    167                 ++itr) 
    168             { 
    169                 // osg::notify(osg::NOTICE)<<"   merging previously loaded, but out of order file : "<<itr->first<<std::endl; 
    170                 _images.push_back(itr->second); 
    171             } 
    172              
    173             _filesRequested.erase(_filesRequested.begin(), itr); 
    174         } 
    175     } 
    176     else 
    177     { 
    178         _images.push_back(image); 
    179     } 
     168    if (image==0) return; 
     169 
     170    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); 
     171 
     172    // osg::notify(osg::NOTICE)<<"merging image in order expected : "<<image->getFileName()<<std::endl; 
     173    _images.push_back(image); 
    180174 
    181175    computeTimePerImage(); 
     
    183177    if (data()==0) 
    184178    { 
    185         _imageIterator = _images.begin(); 
    186         _imageIteratorTime = 0.0; 
    187         setImageToChild(_imageIterator->get()); 
     179        setImageToChild(_images.front().get()); 
    188180    } 
    189181} 
     
    194186 
    195187    if (image==0) return; 
     188 
     189    // check to see if data is changing, if not don't apply 
     190    if (image->data() == data()) return; 
    196191 
    197192    setImage(image->s(),image->t(),image->r(), 
     
    203198} 
    204199 
     200void ImageSequence::applyLoopingMode() 
     201{ 
     202} 
     203 
     204int ImageSequence::imageIndex(double time) 
     205{ 
     206    if (getLoopingMode()==LOOPING)  
     207    { 
     208        double positionRatio = time/_length; 
     209        time = (positionRatio - floor(positionRatio))*_length; 
     210    } 
     211 
     212    if (time<0.0) return 0; 
     213    int index = int(time/_timePerImage); 
     214    if (index>=_images.size()) return _images.size()-1; 
     215    return index; 
     216} 
     217 
    205218void ImageSequence::update(osg::NodeVisitor* nv) 
    206219{ 
     
    225238        _referenceTime =  fs->getSimulationTime() - time/_timeMultiplier; 
    226239    } 
    227      
    228     if (time>_length) 
    229     { 
    230         time -= floor(time/_length)*_length; 
    231     } 
    232              
     240    else 
     241    { 
     242        if (looping) 
     243        { 
     244            while (time>_length) 
     245            { 
     246                _referenceTime += _length/_timeMultiplier; 
     247                time -= _length; 
     248            } 
     249        } 
     250        else 
     251        { 
     252            if (time>_length) 
     253            { 
     254                _referenceTime = fs->getSimulationTime() - _length/_timeMultiplier; 
     255                time = _length; 
     256            } 
     257        } 
     258    } 
     259     
    233260    _seekTime = time; 
    234 //    _seekTimeSet = false; 
    235  
    236     FileNames::iterator previous_fileNamesIterator = _fileNamesIterator; 
    237     Images::iterator previous_imageIterator = _imageIterator; 
    238      
     261    _seekTimeSet = false; 
     262 
    239263    bool pruneOldImages = false; 
    240264     
     
    270294    } 
    271295 
     296    int index = int(time/_timePerImage); 
     297    // osg::notify(osg::NOTICE)<<"time= "<<time<<" _timePerImage="<<_timePerImage<<" index="<<index<<" _length="<<_length<<std::endl; 
     298 
     299    if (index>=_images.size()) index = _images.size()-1; 
     300 
     301    if (index>=0 && index<_images.size()) 
     302    { 
     303 
     304        if (pruneOldImages) 
     305        { 
     306            while (index>=0 && !_images[index].valid()) 
     307            { 
     308                --index; 
     309            } 
     310        } 
     311                 
     312        if (index>=0) 
     313        { 
     314            // osg::notify(osg::NOTICE)<<"at time "<<time<<" setting child = "<<index<<std::endl; 
     315 
     316            if (_previousAppliedImageIndex!=index) 
     317            { 
     318                if (_previousAppliedImageIndex >= 0 &&  
     319                    _previousAppliedImageIndex<_images.size() &&  
     320                    pruneOldImages) 
     321                { 
     322                    _images[_previousAppliedImageIndex] = 0; 
     323                } 
     324             
     325                setImageToChild(_images[index].get()); 
     326                 
     327                _previousAppliedImageIndex = index; 
     328            } 
     329        } 
     330    } 
     331 
    272332    // osg::notify(osg::NOTICE)<<"time = "<<time<<std::endl; 
    273333 
    274     if (irh && _images.size()<_fileNames.size()) 
     334    if (irh) 
    275335    { 
    276336        double preLoadTime = time + osg::minimum(irh->getPreLoadTime()*_timeMultiplier, _length); 
    277337         
    278         if (preLoadTime>=_length) 
    279         { 
    280             // 
    281             // Advance fileNameIterator to end and wrap around 
    282             // 
    283             for(;  
    284                 _fileNamesIterator != _fileNames.end(); 
    285                 ++_fileNamesIterator) 
    286             { 
    287                 _fileNamesIteratorTime += _timePerImage; 
    288                  
    289                 double effectTime = fs->getSimulationTime() + (preLoadTime - _fileNamesIteratorTime); 
    290                 _filesRequested.push_back(FileNameImagePair(*_fileNamesIterator,0)); 
    291                 irh->requestImageFile(*_fileNamesIterator, this, effectTime, fs); 
    292                  
    293             } 
    294              
    295             preLoadTime -= _length; 
    296  
     338        int startLoadIndex = int(time/_timePerImage); 
     339        if (startLoadIndex>=_images.size()) startLoadIndex = _images.size()-1; 
     340        if (startLoadIndex<0) startLoadIndex = 0; 
     341 
     342        int endLoadIndex = int(preLoadTime/_timePerImage); 
     343        if (endLoadIndex>=_fileNames.size())  
     344        { 
    297345            if (looping) 
    298346            { 
    299                 _fileNamesIterator = _fileNames.begin(); 
    300                 _fileNamesIteratorTime = 0.0; 
    301             } 
    302         } 
    303          
    304  
    305         if (_fileNamesIterator!=_fileNames.end()) 
    306         { 
    307             // 
    308             // Advance fileNameIterator to encmpass preLoadTime 
    309             // 
    310  
    311             //osg::notify(osg::NOTICE)<<"   _fileNamesIteratorTime = "<<_fileNamesIteratorTime<<" "<<_timePerImage<<std::endl; 
    312             while(preLoadTime > (_fileNamesIteratorTime + _timePerImage)) 
    313             { 
    314                 _fileNamesIteratorTime += _timePerImage; 
    315                 //osg::notify(osg::NOTICE)<<"   _fileNamesIteratorTime = "<<_fileNamesIteratorTime<<std::endl; 
    316                 //osg::notify(osg::NOTICE)<<"   need to preLoad = "<<*_fileNamesIterator<<std::endl; 
    317                 ++_fileNamesIterator; 
    318  
    319                 if (previous_fileNamesIterator==_fileNamesIterator) break; 
    320  
    321                 if (_fileNamesIterator ==_fileNames.end()) 
    322                 { 
    323                     // return iterator to begining of set.             
    324                     if (looping) _fileNamesIterator = _fileNames.begin(); 
    325                     else break;                     
    326                 } 
    327  
    328                 double effectTime = fs->getSimulationTime() + (preLoadTime - _fileNamesIteratorTime); 
    329                 _filesRequested.push_back(FileNameImagePair(*_fileNamesIterator,0)); 
    330                 irh->requestImageFile(*_fileNamesIterator, this, effectTime, fs); 
    331             } 
    332         } 
    333  
    334         if (looping && _fileNamesIterator==_fileNames.end()) 
    335         { 
    336             _fileNamesIterator = _fileNames.begin(); 
    337             _fileNamesIteratorTime = 0.0; 
    338         } 
    339     } 
    340          
    341  
    342  
    343     { 
    344         // 
    345         // Advance imageIterator 
    346         // 
    347  
    348         if ((looping || _seekTimeSet) && time<_imageIteratorTime) 
    349         { 
    350             _imageIterator = _images.begin(); 
    351             _imageIteratorTime = 0.0; 
    352         } 
    353  
    354         if (_imageIterator!=_images.end()) 
    355         { 
    356             // osg::notify(osg::NOTICE)<<"   _imageIteratorTime = "<<_imageIteratorTime<<std::endl; 
    357             while(time > (_imageIteratorTime + _timePerImage)) 
    358             { 
    359                 _imageIteratorTime += _timePerImage; 
    360                 // osg::notify(osg::NOTICE)<<"   _imageIteratorTime = "<<_imageIteratorTime<<std::endl; 
    361                 ++_imageIterator; 
    362  
    363                 if (_imageIterator ==_images.end()) 
    364                 { 
    365  
    366                     if (pruneOldImages) 
    367                     { 
    368                         _images.erase(previous_imageIterator, _imageIterator); 
    369                         previous_imageIterator = _images.begin(); 
    370                     } 
    371  
    372                     if (looping) 
    373                     { 
    374                         // return iterator to begining of set.             
    375                         _imageIterator = _images.begin(); 
    376                     } 
    377                     else 
    378                     { 
    379                         break; 
    380                     } 
    381                 } 
    382             } 
    383         } 
    384  
    385         if (looping && _imageIterator==_images.end()) 
    386         { 
    387             _imageIterator = _images.begin(); 
    388         } 
    389     } 
    390          
    391     if (_imageIterator!=_images.end() && previous_imageIterator != _imageIterator) 
    392     { 
    393         if (pruneOldImages) 
    394         { 
    395             _images.erase(previous_imageIterator, _imageIterator); 
    396         } 
    397      
    398         setImageToChild(_imageIterator->get()); 
    399     } 
    400     _seekTimeSet = false; 
    401 } 
     347                endLoadIndex -= _fileNames.size(); 
     348            } 
     349            else 
     350            { 
     351                endLoadIndex = _fileNames.size()-1; 
     352            } 
     353        } 
     354        if (endLoadIndex<0) endLoadIndex = 0; 
     355         
     356        double requestTime = time; 
     357         
     358        if (endLoadIndex<startLoadIndex) 
     359        { 
     360            for(int i=startLoadIndex; i<_fileNames.size(); ++i) 
     361            { 
     362                if ((i>=_images.size() || !_images[i]) && _filesRequested.count(_fileNames[i])==0) 
     363                { 
     364                    _filesRequested.insert(_fileNames[i]); 
     365                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs); 
     366                } 
     367                requestTime += _timePerImage; 
     368            } 
     369 
     370            for(int i=0; i<=endLoadIndex; ++i) 
     371            { 
     372                if ((i>=_images.size() || !_images[i]) && _filesRequested.count(_fileNames[i])==0) 
     373                { 
     374                    _filesRequested.insert(_fileNames[i]); 
     375                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs); 
     376                } 
     377                requestTime += _timePerImage; 
     378            } 
     379        } 
     380        else 
     381        { 
     382            for(int i=startLoadIndex; i<=endLoadIndex; ++i) 
     383            { 
     384                if ((i>=_images.size() || !_images[i]) && _filesRequested.count(_fileNames[i])==0) 
     385                { 
     386                    _filesRequested.insert(_fileNames[i]); 
     387                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs); 
     388                } 
     389                requestTime += _timePerImage; 
     390            } 
     391        } 
     392 
     393 
     394    } 
     395 
     396}