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

Revision 13041, 10.0 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
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
25ImageSequence::ImageSequence()
26{
27    _referenceTime = DBL_MAX;
28    _timeMultiplier = 1.0;
29
30    _mode = PRE_LOAD_ALL_IMAGES;
31    _length = 1.0;
32    _timePerImage = 1.0;
33
34    _seekTime = 0.0;
35    _seekTimeSet = false;
36
37    _previousAppliedImageIndex = -1;
38}
39
40ImageSequence::ImageSequence(const ImageSequence& is,const CopyOp& copyop):
41    osg::ImageStream(is,copyop),
42    _referenceTime(is._referenceTime),
43    _timeMultiplier(is._timeMultiplier),
44    _mode(is._mode),
45    _length(is._length),
46    _timePerImage(is._timePerImage)
47{
48    _seekTime = is._seekTime;
49    _seekTimeSet = is._seekTimeSet;
50
51    _previousAppliedImageIndex = -1;
52}
53
54int ImageSequence::compare(const Image& rhs) const
55{
56    return ImageStream::compare(rhs);
57}
58
59void ImageSequence::seek(double time)
60{
61    _seekTime = time;
62    _seekTimeSet = true;
63}
64
65void ImageSequence::play()
66{
67    _status=PLAYING;
68}
69
70void ImageSequence::pause()
71{
72    _status=PAUSED;
73}
74
75void ImageSequence::rewind()
76{
77    seek(0.0f);
78}
79
80void ImageSequence::setMode(Mode mode)
81{
82    _mode = mode;
83}
84
85void ImageSequence::setLength(double length)
86{
87    if (length<=0.0)
88    {
89        OSG_NOTICE<<"ImageSequence::setLength("<<length<<") invalid length value, must be greater than 0."<<std::endl;
90        return;
91    }
92
93    _length = length;
94    computeTimePerImage();
95}
96
97void ImageSequence::computeTimePerImage()
98{
99    if (!_fileNames.empty()) _timePerImage = _length / double(_fileNames.size());
100    else if (!_images.empty()) _timePerImage = _length / double(_images.size());
101    else _timePerImage = _length;
102}
103
104void ImageSequence::setImageFile(unsigned int pos, const std::string& fileName)
105{
106    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
107
108    if (pos>=_fileNames.size()) _fileNames.resize(pos);
109    _fileNames[pos] = fileName;
110}
111
112std::string ImageSequence::getImageFile(unsigned int pos) const
113{
114    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
115    return pos<_fileNames.size() ? _fileNames[pos] : std::string();
116}
117
118void ImageSequence::addImageFile(const std::string& fileName)
119{
120    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
121    _fileNames.push_back(fileName);
122    computeTimePerImage();
123}
124
125void ImageSequence::setImage(unsigned int pos, osg::Image* image)
126{
127    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
128
129    OSG_INFO<<"ImageSequence::setImage("<<pos<<","<<image->getFileName()<<")"<<std::endl;
130
131    if (pos>=_images.size()) _images.resize(pos+1);
132
133    _images[pos] = image;
134
135    // prune from file requested list.
136    FilesRequested::iterator itr = _filesRequested.find(image->getFileName());
137    if (itr!=_filesRequested.end()) _filesRequested.erase(itr);
138}
139
140Image* ImageSequence::getImage(unsigned int pos)
141{
142    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
143    return pos<_images.size() ? _images[pos].get() : 0;
144}
145
146const Image* ImageSequence::getImage(unsigned int pos) const
147{
148    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
149    return pos<_images.size() ? _images[pos].get() : 0;
150}
151
152void ImageSequence::addImage(osg::Image* image)
153{
154    if (image==0) return;
155
156    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
157
158    // OSG_NOTICE<<"merging image in order expected : "<<image->getFileName()<<std::endl;
159    _images.push_back(image);
160
161    computeTimePerImage();
162
163    if (data()==0)
164    {
165        setImageToChild(_images.front().get());
166    }
167}
168
169void ImageSequence::setImageToChild(const osg::Image* image)
170{
171    // OSG_NOTICE<<"setImageToChild("<<image<<")"<<std::endl;
172
173    if (image==0) return;
174
175    // check to see if data is changing, if not don't apply
176    if (image->data() == data()) return;
177
178    setImage(image->s(),image->t(),image->r(),
179             image->getInternalTextureFormat(),
180             image->getPixelFormat(),image->getDataType(),
181             const_cast<unsigned char*>(image->data()),
182             osg::Image::NO_DELETE,
183             image->getPacking());
184}
185
186void ImageSequence::applyLoopingMode()
187{
188}
189
190int ImageSequence::imageIndex(double time)
191{
192    if (getLoopingMode()==LOOPING)
193    {
194        double positionRatio = time/_length;
195        time = (positionRatio - floor(positionRatio))*_length;
196    }
197
198    if (time<0.0) return 0;
199    int index = int(time/_timePerImage);
200    if (index>=int(_images.size())) return int(_images.size())-1;
201    return index;
202}
203
204void ImageSequence::update(osg::NodeVisitor* nv)
205{
206    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
207
208    osg::NodeVisitor::ImageRequestHandler* irh = nv->getImageRequestHandler();
209    const osg::FrameStamp* fs = nv->getFrameStamp();
210
211    // OSG_NOTICE<<"ImageSequence::update("<<fs<<", "<<irh<<")"<<std::endl;
212
213    if (_referenceTime == DBL_MAX)
214    {
215        _referenceTime = fs->getSimulationTime();
216    }
217
218    bool looping = getLoopingMode()==LOOPING;
219    double time = (fs->getSimulationTime() - _referenceTime)*_timeMultiplier;
220
221    if (_seekTimeSet || _status==PAUSED || _status==INVALID)
222    {
223        time = _seekTime;
224        _referenceTime =  fs->getSimulationTime() - time/_timeMultiplier;
225    }
226    else
227    {
228        if (looping)
229        {
230            while (time>_length)
231            {
232                _referenceTime += _length/_timeMultiplier;
233                time -= _length;
234            }
235        }
236        else
237        {
238            if (time>_length)
239            {
240                _referenceTime = fs->getSimulationTime() - _length/_timeMultiplier;
241                time = _length;
242            }
243        }
244    }
245
246    _seekTime = time;
247    _seekTimeSet = false;
248
249    bool pruneOldImages = false;
250
251
252    switch(_mode)
253    {
254        case(PRE_LOAD_ALL_IMAGES):
255        {
256            if (_fileNames.size()>_images.size())
257            {
258                FileNames::iterator itr = _fileNames.begin();
259                for(unsigned int i=0;i<_images.size();++i) ++itr;
260
261                for(; itr!=_fileNames.end(); ++itr)
262                {
263                    osg::Image* image = irh->readImageFile(*itr);
264                    _images.push_back(image);
265                }
266            }
267
268            irh = 0;
269            break;
270        }
271        case(PAGE_AND_RETAIN_IMAGES):
272        {
273            break;
274        }
275        case(PAGE_AND_DISCARD_USED_IMAGES):
276        {
277            pruneOldImages = true;
278            break;
279        }
280    }
281
282    int index = int(time/_timePerImage);
283    // OSG_NOTICE<<"time= "<<time<<" _timePerImage="<<_timePerImage<<" index="<<index<<" _length="<<_length<<std::endl;
284
285    if (index>=int(_images.size())) index = int(_images.size())-1;
286
287    if (index>=0 && index<int(_images.size()))
288    {
289
290        if (pruneOldImages)
291        {
292            while (index>=0 && !_images[index].valid())
293            {
294                --index;
295            }
296        }
297
298        if (index>=0)
299        {
300            // OSG_NOTICE<<"at time "<<time<<" setting child = "<<index<<std::endl;
301
302            if (_previousAppliedImageIndex!=index)
303            {
304                if (_previousAppliedImageIndex >= 0 &&
305                    _previousAppliedImageIndex<int(_images.size()) &&
306                    pruneOldImages)
307                {
308                    _images[_previousAppliedImageIndex] = 0;
309                }
310
311                setImageToChild(_images[index].get());
312
313                _previousAppliedImageIndex = index;
314            }
315        }
316    }
317
318    // OSG_NOTICE<<"time = "<<time<<std::endl;
319
320    if (irh)
321    {
322        double preLoadTime = time + osg::minimum(irh->getPreLoadTime()*_timeMultiplier, _length);
323
324        int startLoadIndex = int(time/_timePerImage);
325        if (startLoadIndex>=int(_images.size())) startLoadIndex = int(_images.size())-1;
326        if (startLoadIndex<0) startLoadIndex = 0;
327
328        int endLoadIndex = int(preLoadTime/_timePerImage);
329        if (endLoadIndex>=int(_fileNames.size()))
330        {
331            if (looping)
332            {
333                endLoadIndex -= int(_fileNames.size());
334            }
335            else
336            {
337                endLoadIndex = int(_fileNames.size())-1;
338            }
339        }
340        if (endLoadIndex<0) endLoadIndex = 0;
341
342        double requestTime = time;
343
344        if (endLoadIndex<startLoadIndex)
345        {
346            for(int i=startLoadIndex; i<int(_fileNames.size()); ++i)
347            {
348                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
349                {
350                    _filesRequested.insert(_fileNames[i]);
351                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
352                }
353                requestTime += _timePerImage;
354            }
355
356            for(int i=0; i<=endLoadIndex; ++i)
357            {
358                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
359                {
360                    _filesRequested.insert(_fileNames[i]);
361                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
362                }
363                requestTime += _timePerImage;
364            }
365        }
366        else
367        {
368            for(int i=startLoadIndex; i<=endLoadIndex; ++i)
369            {
370                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
371                {
372                    _filesRequested.insert(_fileNames[i]);
373                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
374                }
375                requestTime += _timePerImage;
376            }
377        }
378
379
380    }
381
382}
Note: See TracBrowser for help on using the browser.