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

Revision 13191, 11.8 kB (checked in by robert, 14 hours ago)

From Jason Beverage, "It looks like the Callback header got accidentally removed from the CMakeLists.txt in the submission yesterday for the geometry instancing example."

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