osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 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 <osgEarthUtil/AutoClipPlaneHandler> 00020 #include <osgEarth/FindNode> 00021 00022 using namespace osgEarth::Util; 00023 using namespace osgEarth; 00024 00025 AutoClipPlaneHandler::AutoClipPlaneHandler( const Map* map ) : 00026 _geocentric(false), 00027 _frame(0), 00028 _nfrAtRadius( 0.00001 ), 00029 _nfrAtDoubleRadius( 0.0049 ), 00030 _rp( -1 ), 00031 _autoFarPlaneClipping(true) 00032 { 00033 //NOP 00034 if ( map ) 00035 { 00036 _geocentric = map->isGeocentric(); 00037 if ( _geocentric ) 00038 _rp = map->getProfile()->getSRS()->getEllipsoid()->getRadiusPolar(); 00039 } 00040 } 00041 00042 bool 00043 AutoClipPlaneHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) 00044 { 00045 if ( ea.getEventType() == osgGA::GUIEventAdapter::FRAME && _frame++ > 1 ) 00046 { 00047 frame( aa ); 00048 } 00049 return false; 00050 } 00051 00052 void 00053 AutoClipPlaneHandler::frame( osgGA::GUIActionAdapter& aa ) 00054 { 00055 osg::Camera* cam = aa.asView()->getCamera(); 00056 00057 if ( _rp < 0 ) 00058 { 00059 osg::ref_ptr<MapNode> tempNode = osgEarth::findTopMostNodeOfType<MapNode>( cam ); 00060 if ( tempNode.valid() && tempNode->getMap()->getProfile() ) 00061 { 00062 _geocentric = tempNode->getMap()->isGeocentric(); 00063 if ( _geocentric ) 00064 _rp = tempNode->getMap()->getProfile()->getSRS()->getEllipsoid()->getRadiusPolar(); 00065 else 00066 OE_INFO << "[AutoClipPlaneHandler] disabled for non-geocentric map" << std::endl; 00067 00068 //_mapNode = tempNode.get(); 00069 } 00070 } 00071 00072 if ( _rp > 0 && _geocentric ) // _mapNode.valid() && _geocentric ) 00073 { 00074 cam->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); 00075 00076 osg::Vec3d eye, center, up; 00077 cam->getViewMatrixAsLookAt( eye, center, up ); 00078 00079 double d = eye.length(); 00080 00081 if ( d < _rp ) 00082 d = _rp; 00083 00084 if ( d > _rp ) 00085 { 00086 double fovy, ar, znear, zfar, finalZfar; 00087 cam->getProjectionMatrixAsPerspective( fovy, ar, znear, finalZfar ); 00088 00089 // far clip at the horizon: 00090 zfar = sqrt( d*d - _rp*_rp ); 00091 00092 if (_autoFarPlaneClipping) 00093 { 00094 finalZfar = zfar; 00095 } 00096 00097 double nfr = _nfrAtRadius + _nfrAtDoubleRadius * ((d-_rp)/d); 00098 znear = osg::clampAbove( zfar * nfr, 1.0 ); 00099 00100 cam->setProjectionMatrixAsPerspective( fovy, ar, znear, finalZfar ); 00101 00102 //OE_NOTICE << fixed 00103 // << "near=" << znear << ", far=" << zfar << std::endl; 00104 } 00105 } 00106 } 00107