osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/Utils.cpp

Go to the documentation of this file.
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 <osgEarth/Utils>
00020 #include <osg/Version>
00021 #include <osg/CoordinateSystemNode>
00022 
00023 using namespace osgEarth;
00024 
00025 //------------------------------------------------------------------------
00026 
00027 void osgEarth::removeEventHandler(osgViewer::View* view, osgGA::GUIEventHandler* handler)
00028 {
00029     osgViewer::View::EventHandlers::iterator itr = std::find(view->getEventHandlers().begin(), view->getEventHandlers().end(), handler);
00030     if (itr != view->getEventHandlers().end())
00031     {
00032         view->getEventHandlers().erase(itr);
00033     }
00034 }
00035 
00036 //------------------------------------------------------------------------
00037 
00038 CullNodeByHorizon::CullNodeByHorizon( const osg::Vec3d& world, const osg::EllipsoidModel* model ) :
00039 _world(world),
00040 _r2(model->getRadiusPolar() * model->getRadiusPolar())
00041 {
00042     //nop
00043 }
00044 
00045 void
00046 CullNodeByHorizon::operator()(osg::Node* node, osg::NodeVisitor* nv)
00047 {
00048     if ( nv )
00049     {
00050         osg::Vec3d eye, center, up;
00051         osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
00052         cv->getCurrentCamera()->getViewMatrixAsLookAt(eye,center,up);
00053 
00054         double d2 = eye.length2();
00055         double horiz2 = d2 - _r2;
00056 
00057         double dist2 = (_world-eye).length2();
00058 
00059         if ( dist2 < horiz2 )
00060         {
00061             traverse(node, nv);
00062         }
00063     }
00064 }
00065 
00066 //------------------------------------------------------------------------
00067 
00068 CullNodeByNormal::CullNodeByNormal( const osg::Vec3d& normal )
00069 {
00070     _normal = normal;
00071     //_normal.normalize();
00072 }
00073 
00074 void
00075 CullNodeByNormal::operator()(osg::Node* node, osg::NodeVisitor* nv)
00076 {
00077     osg::Vec3d eye, center, up;
00078     osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
00079 
00080     cv->getCurrentCamera()->getViewMatrixAsLookAt(eye,center,up);
00081 
00082     eye.normalize();
00083     osg::Vec3d normal = _normal;
00084     normal.normalize();
00085 
00086     double dotProduct = eye * normal;
00087     if ( dotProduct > 0.0 )
00088     {
00089         traverse(node, nv);
00090     }
00091 }
00092 
00093 //------------------------------------------------------------------------
00094 
00095 #undef LC
00096 #define LC "[PixelAutoTransform] "
00097 
00098 PixelAutoTransform::PixelAutoTransform() :
00099 osg::AutoTransform()
00100 {
00101     // deactivate culling for the first traversal. We will reactivate it later.
00102     setCullingActive( false );
00103 }
00104 
00105 void
00106 PixelAutoTransform::accept( osg::NodeVisitor& nv )
00107 {
00108     if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
00109     {
00110         // re-activate culling now that the first cull traversal has taken place.
00111         this->setCullingActive( true );
00112         osg::CullStack* cs = dynamic_cast<osg::CullStack*>(&nv);
00113         if ( cs )
00114         {
00115             osg::Viewport::value_type width  = _previousWidth;
00116             osg::Viewport::value_type height = _previousHeight;
00117 
00118             osg::Viewport* viewport = cs->getViewport();
00119             if (viewport)
00120             {
00121                 width = viewport->width();
00122                 height = viewport->height();
00123             }
00124 
00125             osg::Vec3d eyePoint = cs->getEyeLocal(); 
00126             osg::Vec3d localUp = cs->getUpLocal(); 
00127             osg::Vec3d position = getPosition();
00128 
00129             const osg::Matrix& projection = *(cs->getProjectionMatrix());
00130 
00131             bool doUpdate = _firstTimeToInitEyePoint || _dirty;
00132             if ( !_firstTimeToInitEyePoint )
00133             {
00134                 osg::Vec3d dv = _previousEyePoint - eyePoint;
00135 
00136                 if (dv.length2() > getAutoUpdateEyeMovementTolerance() * (eyePoint-getPosition()).length2())
00137                 {
00138                     doUpdate = true;
00139                 }
00140                 else
00141                 {
00142                     osg::Vec3d dupv = _previousLocalUp - localUp;
00143 
00144                     // rotating the camera only affects ROTATE_TO_*
00145                     if ((_autoRotateMode && dupv.length2() > getAutoUpdateEyeMovementTolerance()) ||
00146                         (width != _previousWidth || height != _previousHeight) ||
00147                         (projection != _previousProjection) ||
00148                         (position != _previousPosition) )
00149                     {
00150                         doUpdate = true;
00151                     }
00152                 }
00153             }
00154             _firstTimeToInitEyePoint = false;
00155 
00156             if ( doUpdate )
00157             {            
00158                 if ( getAutoScaleToScreen() )
00159                 {
00160                     double radius =
00161                         _sizingNode.valid() ? _sizingNode->getBound().radius() :
00162                         getNumChildren() > 0 ? getChild(0)->getBound().radius() : 
00163                         0.48;
00164 
00165                     double pixels = cs->pixelSize( getPosition(), radius );
00166 
00167                     double scaledMinPixels = _minPixels * _minimumScale;
00168                     double scale = pixels < scaledMinPixels ? scaledMinPixels / pixels : 1.0;
00169 
00170                     OE_DEBUG << LC
00171                         << "Pixels = " << pixels << ", minPix = " << _minPixels << ", scale = " << scale
00172                         << std::endl;
00173 
00174                     setScale( scale );
00175                 }
00176 
00177                 _previousEyePoint = eyePoint;
00178                 _previousLocalUp = localUp;
00179                 _previousWidth = width;
00180                 _previousHeight = height;
00181                 _previousProjection = projection;
00182                 _previousPosition = position;
00183 
00184                 _matrixDirty = true;
00185             }
00186 
00187             if (_autoRotateMode==ROTATE_TO_SCREEN)
00188             {
00189                 osg::Vec3d translation;
00190                 osg::Quat rotation;
00191                 osg::Vec3d scale;
00192                 osg::Quat so;
00193 
00194                 cs->getModelViewMatrix()->decompose( translation, rotation, scale, so );
00195 
00196                 setRotation(rotation.inverse());
00197             }
00198             else if (_autoRotateMode==ROTATE_TO_CAMERA)
00199             {
00200                 osg::Vec3d PosToEye = _position - eyePoint;
00201                 osg::Matrix lookto = osg::Matrix::lookAt(
00202                     osg::Vec3d(0,0,0), PosToEye, localUp);
00203                 osg::Quat q;
00204                 q.set(osg::Matrix::inverse(lookto));
00205                 setRotation(q);
00206             }
00207 
00208 #if OSG_MIN_VERSION_REQUIRED(3,0,0)
00209             else if (_autoRotateMode==ROTATE_TO_AXIS)
00210             {
00211                 osg::Matrix matrix;
00212                 osg::Vec3 ev(eyePoint - _position);
00213 
00214                 switch(_cachedMode)
00215                 {
00216                 case(AXIAL_ROT_Z_AXIS):
00217                     {
00218                         ev.z() = 0.0f;
00219                         float ev_length = ev.length();
00220                         if (ev_length>0.0f)
00221                         {
00222                             //float rotation_zrotation_z = atan2f(ev.x(),ev.y());
00223                             //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f);
00224                             float inv = 1.0f/ev_length;
00225                             float s = ev.x()*inv;
00226                             float c = -ev.y()*inv;
00227                             matrix(0,0) = c;
00228                             matrix(1,0) = -s;
00229                             matrix(0,1) = s;
00230                             matrix(1,1) = c;
00231                         }
00232                         break;
00233                     }
00234                 case(AXIAL_ROT_Y_AXIS):
00235                     {
00236                         ev.y() = 0.0f;
00237                         float ev_length = ev.length();
00238                         if (ev_length>0.0f)
00239                         {
00240                             //float rotation_zrotation_z = atan2f(ev.x(),ev.y());
00241                             //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f);
00242                             float inv = 1.0f/ev_length;
00243                             float s = -ev.z()*inv;
00244                             float c = ev.x()*inv;
00245                             matrix(0,0) = c;
00246                             matrix(2,0) = s;
00247                             matrix(0,2) = -s;
00248                             matrix(2,2) = c;
00249                         }
00250                         break;
00251                     }
00252                 case(AXIAL_ROT_X_AXIS):
00253                     {
00254                         ev.x() = 0.0f;
00255                         float ev_length = ev.length();
00256                         if (ev_length>0.0f)
00257                         {
00258                             //float rotation_zrotation_z = atan2f(ev.x(),ev.y());
00259                             //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f);
00260                             float inv = 1.0f/ev_length;
00261                             float s = -ev.z()*inv;
00262                             float c = -ev.y()*inv;
00263                             matrix(1,1) = c;
00264                             matrix(2,1) = -s;
00265                             matrix(1,2) = s;
00266                             matrix(2,2) = c;
00267                         }
00268                         break;
00269                     }
00270                 case(ROTATE_TO_AXIS): // need to implement 
00271                     {
00272                         float ev_side = ev*_side;
00273                         float ev_normal = ev*_normal;
00274                         float rotation = atan2f(ev_side,ev_normal);
00275                         matrix.makeRotate(rotation,_axis);
00276                         break;
00277                     }
00278                 }
00279                 osg::Quat q;
00280                 q.set(matrix);
00281                 setRotation(q);
00282             }
00283 #endif
00284 
00285             _dirty = false;
00286         }
00287     }
00288 
00289     // finally, skip AT's accept and do Transform.
00290     Transform::accept(nv);
00291 
00292 }
00293 
00294 void
00295 PixelAutoTransform::dirty()
00296 {
00297     _dirty = true;
00298     setCullingActive( false );
00299 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines