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

Revision 13041, 10.4 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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 <osg/PagedLOD>
15#include <osg/CullStack>
16#include <osg/Notify>
17
18#include <algorithm>
19
20using namespace osg;
21
22PagedLOD::PerRangeData::PerRangeData():
23    _priorityOffset(0.0f),
24    _priorityScale(1.0f),
25    _minExpiryTime(0.0),
26    _minExpiryFrames(0),
27    _timeStamp(0.0f),
28    _frameNumber(0),
29    _frameNumberOfLastReleaseGLObjects(0) {}
30
31PagedLOD::PerRangeData::PerRangeData(const PerRangeData& prd):
32    _filename(prd._filename),
33    _priorityOffset(prd._priorityOffset),
34    _priorityScale(prd._priorityScale),
35    _minExpiryTime(prd._minExpiryTime),
36    _minExpiryFrames(prd._minExpiryFrames),
37    _timeStamp(prd._timeStamp),
38    _frameNumber(prd._frameNumber),
39    _frameNumberOfLastReleaseGLObjects(prd._frameNumberOfLastReleaseGLObjects),
40    _databaseRequest(prd._databaseRequest) {}
41
42PagedLOD::PerRangeData& PagedLOD::PerRangeData::operator = (const PerRangeData& prd)
43{
44    if (this==&prd) return *this;
45    _filename = prd._filename;
46    _priorityOffset = prd._priorityOffset;
47    _priorityScale = prd._priorityScale;
48    _timeStamp = prd._timeStamp;
49    _frameNumber = prd._frameNumber;
50    _frameNumberOfLastReleaseGLObjects = prd._frameNumberOfLastReleaseGLObjects;
51    _databaseRequest = prd._databaseRequest;
52    _minExpiryTime = prd._minExpiryTime;
53    _minExpiryFrames = prd._minExpiryFrames;
54    return *this;
55}
56
57PagedLOD::PagedLOD()
58{
59    _frameNumberOfLastTraversal = 0;
60    _centerMode = USER_DEFINED_CENTER;
61    _radius = -1;
62    _numChildrenThatCannotBeExpired = 0;
63    _disableExternalChildrenPaging = false;
64}
65
66PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop):
67    LOD(plod,copyop),
68    _databaseOptions(plod._databaseOptions),
69    _databasePath(plod._databasePath),
70    _frameNumberOfLastTraversal(plod._frameNumberOfLastTraversal),
71    _numChildrenThatCannotBeExpired(plod._numChildrenThatCannotBeExpired),
72    _disableExternalChildrenPaging(plod._disableExternalChildrenPaging),
73    _perRangeDataList(plod._perRangeDataList)
74{
75}
76
77PagedLOD::~PagedLOD()
78{
79}
80
81void PagedLOD::setDatabasePath(const std::string& path)
82{
83    _databasePath = path;
84    if (!_databasePath.empty())
85    {
86        char& lastCharacter = _databasePath[_databasePath.size()-1];
87        const char unixSlash = '/';
88        const char winSlash = '\\';
89
90        if (lastCharacter==winSlash)
91        {
92            lastCharacter = unixSlash;
93        }
94        else if (lastCharacter!=unixSlash)
95        {
96            _databasePath += unixSlash;
97        }
98
99/*
100        // make sure the last character is the appropriate slash
101#ifdef WIN32
102        if (lastCharacter==unixSlash)
103        {
104            lastCharacter = winSlash;
105        }
106        else if (lastCharacter!=winSlash)
107        {
108            _databasePath += winSlash;
109        }
110#else
111        if (lastCharacter==winSlash)
112        {
113            lastCharacter = unixSlash;
114        }
115        else if (lastCharacter!=unixSlash)
116        {
117            _databasePath += unixSlash;
118        }
119#endif
120*/
121    }
122}
123
124
125void PagedLOD::traverse(NodeVisitor& nv)
126{
127    // set the frame number of the traversal so that external nodes can find out how active this
128    // node is.
129    if (nv.getFrameStamp() &&
130        nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
131    {
132        setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
133    }
134
135    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
136    unsigned int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0;
137    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
138
139    switch(nv.getTraversalMode())
140    {
141        case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
142            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
143            break;
144        case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
145        {
146            float required_range = 0;
147            if (_rangeMode==DISTANCE_FROM_EYE_POINT)
148            {
149                required_range = nv.getDistanceToViewPoint(getCenter(),true);
150            }
151            else
152            {
153                osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv);
154                if (cullStack && cullStack->getLODScale()>0.0f)
155                {
156                    required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();
157                }
158                else
159                {
160                    // fallback to selecting the highest res tile by
161                    // finding out the max range
162                    for(unsigned int i=0;i<_rangeList.size();++i)
163                    {
164                        required_range = osg::maximum(required_range,_rangeList[i].first);
165                    }
166                }
167            }
168
169            int lastChildTraversed = -1;
170            bool needToLoadChild = false;
171            for(unsigned int i=0;i<_rangeList.size();++i)
172            {
173                if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
174                {
175                    if (i<_children.size())
176                    {
177                        if (updateTimeStamp)
178                        {
179                            _perRangeDataList[i]._timeStamp=timeStamp;
180                            _perRangeDataList[i]._frameNumber=frameNumber;
181                        }
182
183                        _children[i]->accept(nv);
184                        lastChildTraversed = (int)i;
185                    }
186                    else
187                    {
188                        needToLoadChild = true;
189                    }
190                }
191            }
192
193            if (needToLoadChild)
194            {
195                unsigned int numChildren = _children.size();
196
197                // select the last valid child.
198                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
199                {
200                    if (updateTimeStamp)
201                    {
202                        _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
203                        _perRangeDataList[numChildren-1]._frameNumber=frameNumber;
204                    }
205                    _children[numChildren-1]->accept(nv);
206                }
207
208                // now request the loading of the next unloaded child.
209                if (!_disableExternalChildrenPaging &&
210                    nv.getDatabaseRequestHandler() &&
211                    numChildren<_perRangeDataList.size())
212                {
213                    // compute priority from where abouts in the required range the distance falls.
214                    float priority = (_rangeList[numChildren].second-required_range)/(_rangeList[numChildren].second-_rangeList[numChildren].first);
215
216                    // invert priority for PIXEL_SIZE_ON_SCREEN mode
217                    if(_rangeMode==PIXEL_SIZE_ON_SCREEN)
218                    {
219                        priority = -priority;
220                    }
221
222                    // modify the priority according to the child's priority offset and scale.
223                    priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;
224
225                    if (_databasePath.empty())
226                    {
227                        nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
228                    }
229                    else
230                    {
231                        // prepend the databasePath to the child's filename.
232                        nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
233                    }
234                }
235
236            }
237
238
239           break;
240        }
241        default:
242            break;
243    }
244}
245
246
247void PagedLOD::expandPerRangeDataTo(unsigned int pos)
248{
249    if (pos>=_perRangeDataList.size()) _perRangeDataList.resize(pos+1);
250}
251
252bool PagedLOD::addChild( Node *child )
253{
254    if (LOD::addChild(child))
255    {
256        expandPerRangeDataTo(_children.size()-1);
257        return true;
258    }
259    return false;
260}
261
262bool PagedLOD::addChild(Node *child, float min, float max)
263{
264    if (LOD::addChild(child,min,max))
265    {
266        expandPerRangeDataTo(_children.size()-1);
267        return true;
268    }
269    return false;
270}
271
272
273bool PagedLOD::addChild(Node *child, float min, float max,const std::string& filename, float priorityOffset, float priorityScale)
274{
275    if (LOD::addChild(child,min,max))
276    {
277        setFileName(_children.size()-1,filename);
278        setPriorityOffset(_children.size()-1,priorityOffset);
279        setPriorityScale(_children.size()-1,priorityScale);
280        return true;
281    }
282    return false;
283}
284
285bool PagedLOD::removeChildren( unsigned int pos,unsigned int numChildrenToRemove)
286{
287    if (pos<_rangeList.size()) _rangeList.erase(_rangeList.begin()+pos, osg::minimum(_rangeList.begin()+(pos+numChildrenToRemove), _rangeList.end()) );
288    if (pos<_perRangeDataList.size()) _perRangeDataList.erase(_perRangeDataList.begin()+pos, osg::minimum(_perRangeDataList.begin()+ (pos+numChildrenToRemove), _perRangeDataList.end()) );
289
290    return Group::removeChildren(pos,numChildrenToRemove);
291}
292
293bool PagedLOD::removeExpiredChildren(double expiryTime, unsigned int expiryFrame, NodeList& removedChildren)
294{
295    if (_children.size()>_numChildrenThatCannotBeExpired)
296    {
297        unsigned cindex = _children.size() - 1;
298        if (!_perRangeDataList[cindex]._filename.empty() &&
299            _perRangeDataList[cindex]._timeStamp + _perRangeDataList[cindex]._minExpiryTime < expiryTime &&
300            _perRangeDataList[cindex]._frameNumber + _perRangeDataList[cindex]._minExpiryFrames < expiryFrame)
301        {
302            osg::Node* nodeToRemove = _children[cindex].get();
303            removedChildren.push_back(nodeToRemove);
304            return Group::removeChildren(cindex,1);
305        }
306    }
307    return false;
308}
Note: See TracBrowser for help on using the browser.