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

Revision 13186, 11.5 kB (checked in by robert, 5 weeks ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

  • 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    bool useDirectTimeRequest = _seekTimeSet;
221   
222    if (_seekTimeSet || _status==PAUSED || _status==INVALID)
223    {
224        time = _seekTime;
225        _referenceTime =  fs->getSimulationTime() - time/_timeMultiplier;
226    }
227    else
228    {
229        if (looping)
230        {
231            while (time>_length)
232            {
233                _referenceTime += _length/_timeMultiplier;
234                time -= _length;
235            }
236        }
237        else
238        {
239            if (time>_length)
240            {
241                _referenceTime = fs->getSimulationTime() - _length/_timeMultiplier;
242                time = _length;
243            }
244        }
245    }
246
247    _seekTime = time;
248    _seekTimeSet = false;
249
250    bool pruneOldImages = false;
251
252    switch(_mode)
253    {
254        case(PRE_LOAD_ALL_IMAGES):
255        {
256            if (irh && _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        if (pruneOldImages)
290        {
291            if (_previousAppliedImageIndex<index)
292            {
293                OSG_DEBUG<<"ImageSequence::update(..) Moving forward by "<<index-_previousAppliedImageIndex<<std::endl;
294                while (index>=0 && !_images[index].valid())
295                {
296                    --index;
297                }
298            }
299            else if (_previousAppliedImageIndex>index)
300            {
301                OSG_DEBUG<<"ImageSequence::update(..) Moving back by "<<_previousAppliedImageIndex-index<<std::endl;
302                while (index<static_cast<int>(_images.size()) && !_images[index].valid())
303                {
304                    ++index;
305                }
306            }
307            else
308            {
309                // OSG_NOTICE<<"ImageSequence::update(..) Same index."<<std::endl;
310            }
311        }
312
313        if (index>=0)
314        {
315            // OSG_NOTICE<<"at time "<<time<<" setting child = "<<index<<std::endl;
316
317            if (_previousAppliedImageIndex!=index)
318            {
319                if (_previousAppliedImageIndex >= 0 &&
320                    _previousAppliedImageIndex<int(_images.size()) &&
321                    pruneOldImages)
322                {
323                    _images[_previousAppliedImageIndex] = 0;
324                }
325
326                setImageToChild(_images[index].get());
327
328                _previousAppliedImageIndex = index;
329            }
330        }
331    }
332
333    // OSG_NOTICE<<"time = "<<time<<std::endl;
334
335    if (!irh) return;
336
337    if (useDirectTimeRequest)
338    {
339        int i = int(time/_timePerImage);
340        if ((i>=int(_images.size()) || !_images[i]))
341        {
342             i = osg::clampTo<int>(i, 0, _fileNames.size()-1);
343             if (_filesRequested.count(_fileNames[i])==0)
344             {
345                 OSG_INFO<<"Requesting file, entry="<<i<<" : _fileNames[i]="<<_fileNames[i]<<std::endl;
346                //_filesRequested.insert(_fileNames[i]);
347                irh->requestImageFile(_fileNames[i], this, i, time, fs);
348             }
349             else
350             {
351                 OSG_DEBUG<<"File already requested, entry="<<i<<" : _fileNames[i]="<<_fileNames[i]<<std::endl;
352             }
353        }
354    }
355    else
356    {
357        double preLoadTime = time + osg::minimum(irh->getPreLoadTime()*_timeMultiplier, _length);
358
359        int startLoadIndex = int(time/_timePerImage);
360        if (startLoadIndex>=int(_images.size())) startLoadIndex = int(_images.size())-1;
361        if (startLoadIndex<0) startLoadIndex = 0;
362
363        int endLoadIndex = int(preLoadTime/_timePerImage);
364        if (endLoadIndex>=int(_fileNames.size()))
365        {
366            if (looping)
367            {
368                endLoadIndex -= int(_fileNames.size());
369            }
370            else
371            {
372                endLoadIndex = int(_fileNames.size())-1;
373            }
374        }
375        if (endLoadIndex<0) endLoadIndex = 0;
376
377        double requestTime = time;
378
379        if (endLoadIndex<startLoadIndex)
380        {
381            for(int i=startLoadIndex; i<int(_fileNames.size()); ++i)
382            {
383                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
384                {
385                    //_filesRequested.insert(_fileNames[i]);
386                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
387                }
388                requestTime += _timePerImage;
389            }
390
391            for(int i=0; i<=endLoadIndex; ++i)
392            {
393                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
394                {
395                    //_filesRequested.insert(_fileNames[i]);
396                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
397                }
398                requestTime += _timePerImage;
399            }
400        }
401        else
402        {
403            for(int i=startLoadIndex; i<=endLoadIndex; ++i)
404            {
405                if ((i>=int(_images.size()) || !_images[i]) && _filesRequested.count(_fileNames[i])==0)
406                {
407                    //_filesRequested.insert(_fileNames[i]);
408                    irh->requestImageFile(_fileNames[i], this, i, requestTime, fs);
409                }
410                requestTime += _timePerImage;
411            }
412        }
413
414
415    }
416
417}
Note: See TracBrowser for help on using the browser.