osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2011 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #include "LODFactorCallback" 00020 00021 #include <osg/Math> 00022 #include <osg/PagedLOD> 00023 #include <osg/StateSet> 00024 #include <osg/Uniform> 00025 #include <osgUtil/CullVisitor> 00026 00027 namespace osgEarth 00028 { 00029 namespace Drivers 00030 { 00031 // This callback sets a uniform, osgearth_LODRangeFactor, based on the 00032 // distance from the camera and its relation to the minimum and 00033 // maximum distance for a tile. The maximum distance isn't actually 00034 // available, so 2 * min distance is used as an estimate. The range 00035 // factor's value goes from 0 - at the maximum range - to 1 for the 00036 // minimum range. 00037 00038 void LODFactorCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) 00039 { 00040 // test the type since this is not always a PagedLOD. 00041 osg::PagedLOD* lod = static_cast<osg::PagedLOD*>(node); 00042 osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv); 00043 osg::LOD::RangeMode rangeMode = lod->getRangeMode(); 00044 float requiredRange = 0.0f; 00045 float rangeFactor = 1.0f; 00046 const osg::LOD::RangeList& rangeList = lod->getRangeList(); 00047 if (rangeMode == osg::LOD::DISTANCE_FROM_EYE_POINT) 00048 { 00049 requiredRange = cv->getDistanceToViewPoint(lod->getCenter(), true); 00050 } 00051 else if (cv->getLODScale() > 0.0f) 00052 { 00053 requiredRange = cv->clampedPixelSize(lod->getBound()) / cv->getLODScale(); 00054 } 00055 else 00056 { 00057 // The comment in osg/PagedLOD.cpp says that this algorithm 00058 // finds the highest res tile, but it actually finds the 00059 // lowest res tile! 00060 for (osg::LOD::RangeList::const_iterator itr = rangeList.begin(), end = rangeList.end(); 00061 itr != end; 00062 ++itr) 00063 { 00064 requiredRange = osg::maximum(requiredRange, itr->first); 00065 } 00066 } 00067 // We're counting on only finding one valid LOD, unlike the 00068 // general OSG behavior. 00069 if (!rangeList.empty() && rangeList[0].first <= requiredRange 00070 && requiredRange < rangeList[0].second) 00071 { 00072 rangeFactor = 1.0f - (requiredRange - rangeList[0].first) / rangeList[0].first; 00073 rangeFactor = osg::clampTo(rangeFactor, 0.0f, 1.0f); 00074 } 00075 osg::ref_ptr<osg::Uniform> ufact 00076 = new osg::Uniform("osgearth_LODRangeFactor", rangeFactor); 00077 osg::ref_ptr<osg::StateSet> ss = new osg::StateSet; 00078 ss->addUniform(ufact.get()); 00079 00080 cv->pushStateSet(ss.get()); 00081 traverse(node, nv); 00082 cv->popStateSet(); 00083 } 00084 } 00085 }