osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_seamless/PatchGroup.cpp

Go to the documentation of this file.
00001 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00002  * Copyright 2010 Pelican Ventures, Inc.
00003  * http://osgearth.org
00004  *
00005  * osgEarth is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00017  */
00018 
00019 #include "PatchGroup"
00020 
00021 #include <osg/Array>
00022 #include <osg/Geometry>
00023 #include <osg/Notify>
00024 #include <osg/Transform>
00025 #include <osgDB/FileNameUtils>
00026 #include <osgDB/Registry>
00027 
00028 #include "Patch"
00029 #include "PatchSet"
00030 
00031 namespace seamless
00032 {
00033 using namespace std;
00034 using namespace osg;
00035 
00036 PatchGroup::PatchGroup()
00037 {
00038     setRangeMode(LOD::PIXEL_SIZE_ON_SCREEN);
00039 }
00040 
00041 PatchGroup::PatchGroup(const PatchGroup& rhs, const CopyOp& copyop)
00042     : PagedLOD(rhs, copyop)
00043 {
00044     setRangeMode(LOD::PIXEL_SIZE_ON_SCREEN);
00045 }
00046 
00047 PatchGroup::~PatchGroup()
00048 {
00049 }
00050 
00051 // Work around for an interface change in osgDB::DatabasePager
00052 struct NodePathProxy
00053 {
00054     NodePathProxy(Group* group_, NodeVisitor& nv_)
00055         : group(group_), nv(nv_)
00056     {
00057     }
00058     operator Group* () { return group; }
00059     operator NodePath& () { return nv.getNodePath(); }
00060     Group* group;
00061     NodeVisitor& nv;
00062 };
00063 
00064 void PatchGroup::getPatchExtents(Vec2d& lowerLeft, Vec2d& upperRight) const
00065 {
00066     const PatchOptions* poptions = getOptions();
00067     if (!poptions)
00068     {
00069         lowerLeft = Vec2d(0.0, 0.0);
00070         upperRight = Vec2d(1.0, 1.0);
00071     }
00072     else
00073     {
00074         poptions->getPatchExtents(lowerLeft, upperRight);
00075     }
00076 }
00077 
00078 // Child 0 is the patch for this LOD. Child 1 is a group of the 4
00079 // patches for the next level.
00080 
00081 // Copied and edited from PagedLOD::traverse.
00082 void PatchGroup::traverse(NodeVisitor& nv)
00083 {
00084     // set the frame number of the traversal so that external nodes can find out how active this
00085     // node is.
00086     if (nv.getFrameStamp() &&
00087         nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
00088     {
00089         setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
00090     }
00091 
00092     double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
00093     int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0;
00094     bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
00095 
00096     switch(nv.getTraversalMode())
00097     {
00098     case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
00099         std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
00100         break;
00101     case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
00102     {
00103         Vec3 eye = nv.getViewPoint();
00104         if (_children.empty())
00105             return;
00106         Transform* tform = static_cast<Transform*>(_children[0].get());
00107         if (tform->getNumChildren() == 0)
00108             return;
00109         Matrix localMat;
00110         tform->computeWorldToLocalMatrix(localMat, &nv);
00111         eye = eye * localMat;
00112         Patch* patch = static_cast<Patch*>(tform->getChild(0));
00113         float epsilon = patch->getPatchError(eye);
00114 
00115         int lastChildTraversed = -1;
00116         bool needToLoadChild = false;
00117         // Range list is set up so that the error is [0,1] for the
00118         // patch  at this level and (1, 1e10) for the next level.
00119         for(unsigned int i=0;i<_rangeList.size();++i)
00120         {
00121             if (_rangeList[i].first <= epsilon
00122                 && epsilon < _rangeList[i].second)
00123             {
00124                 if (i<_children.size())
00125                 {
00126                     if (updateTimeStamp)
00127                     {
00128                         _perRangeDataList[i]._timeStamp=timeStamp;
00129                         _perRangeDataList[i]._frameNumber=frameNumber;
00130                     }
00131 
00132                     _children[i]->accept(nv);
00133                     lastChildTraversed = (int)i;
00134                 }
00135                 else
00136                 {
00137                     needToLoadChild = true;
00138                 }
00139             }
00140         }
00141 
00142         if (needToLoadChild)
00143         {
00144             unsigned int numChildren = _children.size();
00145 
00146             // select the last valid child.
00147             if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
00148             {
00149                 if (updateTimeStamp)
00150                 {
00151                     _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
00152                     _perRangeDataList[numChildren-1]._frameNumber=frameNumber;
00153                 }
00154                 _children[numChildren-1]->accept(nv);
00155             }
00156 
00157             // now request the loading of the next unloaded child.
00158             if (!_disableExternalChildrenPaging &&
00159                 nv.getDatabaseRequestHandler() &&
00160                 numChildren<_perRangeDataList.size())
00161             {
00162                 // compute priority from where abouts in the required range the distance falls.
00163                 float priority = (_rangeList[numChildren].second - epsilon)/(_rangeList[numChildren].second-_rangeList[numChildren].first);
00164 
00165                 // invert priority for PIXEL_SIZE_ON_SCREEN mode
00166                 priority = -priority;
00167 
00168                 // modify the priority according to the child's priority offset and scale.
00169                 priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;
00170 
00171                 if (_databasePath.empty())
00172                 {
00173                     nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,NodePathProxy(this, nv),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
00174                 }
00175                 else
00176                 {
00177                     // prepend the databasePath to the child's filename.
00178                     nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,NodePathProxy(this, nv),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get());
00179                 }
00180             }
00181 
00182         }
00183         break;
00184     }
00185     default:
00186         break;
00187     }
00188 }
00189 
00190 PatchOptions::PatchOptions()
00191    : _lowerLeft(0.0, 0.0), _upperRight(1.0, 1.0), _level(0),
00192     _tileKey(osgEarth::TileKey::INVALID)
00193 {
00194 }
00195 
00196 PatchOptions::PatchOptions(const std::string& str)
00197     : osgDB::Options(str), _lowerLeft(0.0, 0.0), _upperRight(1.0, 1.0),
00198       _level(0), _tileKey(osgEarth::TileKey::INVALID)
00199 {
00200 }
00201 
00202 PatchOptions::PatchOptions(const PatchOptions& rhs, const CopyOp& copyop)
00203     : osgDB::Options(rhs, copyop), _lowerLeft(rhs._lowerLeft),
00204       _upperRight(rhs._upperRight), _level(rhs._level), _tileKey(rhs._tileKey)
00205 {
00206     _patchSet = static_cast<PatchSet*>(copyop(rhs._patchSet.get()));
00207 }
00208 
00209 PatchOptions::~PatchOptions()
00210 {
00211 }
00212 
00213 void PatchOptions::setPatchSet(PatchSet* patchSet)
00214 {
00215     _patchSet = patchSet;
00216 }
00217 
00218 PatchSet* PatchOptions::getPatchSet() const
00219 {
00220     return _patchSet.get();
00221 }
00222 
00223 
00224 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines