root/OpenSceneGraph/trunk/src/osg/ImageSequence.cpp @ 9062

Revision 9062, 10.7 kB (checked in by robert, 6 years ago)

Various warning fixes

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <OpenThreads/ScopedLock>
15#include <osg/ImageSequence>
16#include <osg/Notify>
17#include <osg/Camera>
18#include <osg/NodeVisitor>
19#include <osg/Texture2D>
20
21#include <math.h>
22
23using namespace osg;
24
25void ImageSequence::UpdateCallback::operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv)
26{
27    osg::Texture* texture = attr ? attr->asTexture() : 0;
28   
29    // osg::notify(osg::NOTICE)<<"ImageSequence::UpdateCallback::"<<texture<<std::endl;
30    if (texture)
31    {
32        for(unsigned int i=0; i<texture->getNumImages(); ++i)
33        {
34            texture->getImage(i)->update(nv);
35        }
36    }
37}
38
39ImageSequence::ImageSequence()
40{
41    _referenceTime = DBL_MAX;
42    _timeMultiplier = 1.0;
43
44    _mode = PRE_LOAD_ALL_IMAGES;
45    _length = 1.0;
46    _timePerImage = 1.0;
47   
48    _seekTime = 0.0;
49    _seekTimeSet = false;
50   
51    _previousAppliedImageIndex = -1;
52}
53
54ImageSequence::ImageSequence(const ImageSequence& is,const CopyOp& copyop):
55    osg::ImageStream(is,copyop),
56    _referenceTime(is._referenceTime),
57    _timeMultiplier(is._timeMultiplier),
58    _mode(is._mode),
59    _length(is._length),
60    _timePerImage(is._timePerImage)
61{
62    _seekTime = is._seekTime;
63    _seekTimeSet = is._seekTimeSet;
64
65    _previousAppliedImageIndex = -1;
66}
67
68int ImageSequence::compare(const Image& rhs) const
69{
70    return ImageStream::compare(rhs);
71}
72
73void ImageSequence::seek(double time)
74{
75    _seekTime = time;
76    _seekTimeSet = true;
77}
78
79void ImageSequence::play()
80{
81    _status=PLAYING;
82}
83
84void ImageSequence::pause()
85{
86    _status=PAUSED;
87}
88
89void ImageSequence::rewind()
90{
91    seek(0.0f);
92}
93
94void ImageSequence::setMode(Mode mode)
95{
96    _mode = mode;
97}
98
99void ImageSequence::setLength(double length)
100{
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   
107    _length = length;
108    computeTimePerImage();
109}
110
111void ImageSequence::computeTimePerImage()
112{
113    if (!_fileNames.empty()) _timePerImage = _length / double(_fileNames.size());
114    else if (!_images.empty()) _timePerImage = _length / double(_images.size());
115    else _timePerImage = _length;
116}
117
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       
132void ImageSequence::addImageFile(const std::string& fileName)
133{
134    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
135    _fileNames.push_back(fileName);
136    computeTimePerImage();
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;
164}
165
166void ImageSequence::addImage(osg::Image* image)
167{
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);
174
175    computeTimePerImage();
176   
177    if (data()==0)
178    {
179        setImageToChild(_images.front().get());
180    }
181}
182
183void ImageSequence::setImageToChild(const osg::Image* image)
184{
185    // osg::notify(osg::NOTICE)<<"setImageToChild("<<image<<")"<<std::endl;
186
187    if (image==0) return;
188
189    // check to see if data is changing, if not don't apply
190    if (image->data() == data()) return;
191
192    setImage(image->s(),image->t(),image->r(),
193             image->getInternalTextureFormat(),
194             image->getPixelFormat(),image->getDataType(),
195             const_cast<unsigned char*>(image->data()),
196             osg::Image::NO_DELETE,
197             image->getPacking());
198}
199
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>=int(_images.size())) return int(_images.size())-1;
215    return index;
216}
217
218void ImageSequence::update(osg::NodeVisitor* nv)
219{
220    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
221   
222    osg::NodeVisitor::ImageRequestHandler* irh = nv->getImageRequestHandler();
223    const osg::FrameStamp* fs = nv->getFrameStamp();
224
225    // osg::notify(osg::NOTICE)<<"ImageSequence::update("<<fs<<", "<<irh<<")"<<std::endl;
226
227    if (_referenceTime == DBL_MAX)
228    {
229        _referenceTime = fs->getSimulationTime();
230    }
231   
232    bool looping = getLoopingMode()==LOOPING;
233    double time = (fs->getSimulationTime() - _referenceTime)*_timeMultiplier;
234   
235    if (_seekTimeSet || _status==PAUSED || _status==INVALID)
236    {
237        time = _seekTime;       
238        _referenceTime =  fs->getSimulationTime() - time/_timeMultiplier;
239    }
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   
260    _seekTime = time;
261    _seekTimeSet = false;
262
263    bool pruneOldImages = false;
264   
265   
266    switch(_mode)
267    {
268        case(PRE_LOAD_ALL_IMAGES):
269        {
270            if (_fileNames.size()>_images.size())
271            {
272                FileNames::iterator itr = _fileNames.begin();
273                for(unsigned int i=0;i<_images.size();++i) ++itr;
274
275                for(; itr!=_fileNames.end(); ++itr)
276                {
277                    osg::Image* image = irh->readImageFile(*itr);
278                    _images.push_back(image);
279                }
280            }
281       
282            irh = 0;
283            break;
284        }
285        case(PAGE_AND_RETAIN_IMAGES):
286        {
287            break;
288        }
289        case(PAGE_AND_DISCARD_USED_IMAGES):
290        {
291            pruneOldImages = true;
292            break;
293        }
294    }
295
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>=int(_images.size())) index = int(_images.size())-1;
300
301    if (index>=0 && index<int(_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<int(_images.size()) &&
320                    pruneOldImages)
321                {
322                    _images[_previousAppliedImageIndex] = 0;
323                }
324           
325                setImageToChild(_images[index].get());
326               
327                _previousAppliedImageIndex = index;
328            }
329        }
330    }
331
332    // osg::notify(osg::NOTICE)<<"time = "<<time<<std::endl;
333
334    if (irh)
335    {
336        double preLoadTime = time + osg::minimum(irh->getPreLoadTime()*_timeMultiplier, _length);
337       
338        int startLoadIndex = int(time/_timePerImage);
339        if (startLoadIndex>=int(_images.size())) startLoadIndex = int(_images.size())-1;
340        if (startLoadIndex<0) startLoadIndex = 0;
341
342        int endLoadIndex = int(preLoadTime/_timePerImage);
343        if (endLoadIndex>=int(_fileNames.size()))
344        {
345            if (looping)
346            {
347                endLoadIndex -= int(_fileNames.size());
348            }
349            else
350            {
351                endLoadIndex = int(_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<int(_fileNames.size()); ++i)
361            {
362                if ((i>=int(_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>=int(_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>=int(_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}
Note: See TracBrowser for help on using the browser.