osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthUtil/Draggers.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 
00020 #include <osg/AutoTransform>
00021 #include <osgViewer/View>
00022 #include <osgUtil/IntersectionVisitor>
00023 #include <osgUtil/LineSegmentIntersector>
00024 #include <osgEarthUtil/Draggers>
00025 #include <osg/io_utils>
00026 
00027 using namespace osgEarth;
00028 using namespace osgEarth::Util;
00029 
00030 /**********************************************************/
00031 TranslateCommand::TranslateCommand():
00032 osgManipulator::MotionCommand()
00033 {
00034 }
00035 
00036 osgManipulator::MotionCommand*
00037 TranslateCommand::createCommandInverse()
00038 {
00039     TranslateCommand *cmd = new TranslateCommand();
00040     cmd->setTranslation( -_translation );
00041     return cmd;
00042 }
00043 
00044 osg::Matrix
00045 TranslateCommand::getMotionMatrix() const 
00046 {
00047     return osg::Matrixd::translate(_translation);
00048 }
00049 
00050 
00051 TranslateCommand::~TranslateCommand()
00052 {
00053 }
00054 
00055 /**********************************************************/
00056     
00057 
00058 IntersectingDragger::IntersectingDragger():
00059 osgManipulator::Dragger(),
00060 _size(5.0f)
00061 {
00062     setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
00063     setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
00064 }
00065 
00066 IntersectingDragger::~IntersectingDragger()
00067 {
00068 }
00069 
00070 void
00071 IntersectingDragger::setupDefaultGeometry()
00072 {
00073     //Build the handle
00074     osg::Sphere* shape = new osg::Sphere(osg::Vec3(0,0,0), _size);   
00075     osg::Geode* geode = new osg::Geode();
00076     _shapeDrawable = new osg::ShapeDrawable( shape );    
00077     geode->addDrawable( _shapeDrawable.get() );
00078     setDrawableColor( _color );
00079 
00080     geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
00081     geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
00082     osg::AutoTransform* at = new osg::AutoTransform;
00083     at->setAutoScaleToScreen( true );
00084     at->addChild( geode );
00085     addChild( at );
00086 }
00087 
00088 bool
00089 IntersectingDragger::getHit(const osg::Vec3d& start, const osg::Vec3d &end, osg::Vec3d& intersection)
00090 {
00091     if (_node.valid())
00092     {
00093         osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(start,end);
00094 
00095         osgUtil::IntersectionVisitor iv(lsi.get());
00096 
00097         _node->accept(iv);
00098 
00099         if (lsi->containsIntersections())
00100         {
00101             OE_DEBUG << "Got get hit at " << start << " to " << end << std::endl;
00102             intersection = lsi->getIntersections().begin()->getWorldIntersectPoint();
00103             return true;
00104         }
00105     }
00106 
00107     OE_DEBUG << "Warning:  Couldn't get hit at " << start << " to " << end << std::endl;
00108     return false;
00109 }
00110 
00111 void
00112 IntersectingDragger::setDrawableColor(const osg::Vec4f& color)
00113 {
00114     if (_shapeDrawable.valid()) _shapeDrawable->setColor( color );
00115 };
00116 
00117 bool IntersectingDragger::handle(const osgManipulator::PointerInfo& pointer, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
00118 {
00119     // Check if the dragger node is in the nodepath.
00120     //if (!pointer.contains(this)) return false; 
00121 
00122 
00123     switch (ea.getEventType())
00124     {
00125         // Pick start.
00126         case (osgGA::GUIEventAdapter::PUSH):
00127             {
00128                 osg::NodePath nodePathToRoot;
00129                 computeNodePathToRoot(*this,nodePathToRoot);
00130                 _localToWorld = osg::computeLocalToWorld(nodePathToRoot);
00131                 _worldToLocal.invert( _localToWorld );
00132 
00133                 osg::Vec3d near, far, hit;
00134                 pointer.getNearFarPoints(near, far);
00135                 if (getHit(near, far, hit))
00136                 {
00137                     _startPoint = hit;
00138                    
00139                     // Generate the motion command.
00140                     osg::ref_ptr<TranslateCommand> cmd = new TranslateCommand();
00141                     cmd->setTranslation(osg::Vec3d(0,0,0));
00142                     cmd->setStage(osgManipulator::MotionCommand::START);
00143                     cmd->setLocalToWorldAndWorldToLocal(_localToWorld, _worldToLocal);
00144 
00145                     // Dispatch command.
00146                     dispatch(*cmd);
00147 
00148                     cmd = new TranslateCommand();
00149                     hit = hit * _worldToLocal;
00150                     osg::Vec3d start = getMatrix().getTrans() * _worldToLocal;                    
00151                     osg::Vec3d translation = hit - start;
00152                     cmd->setTranslation(translation);
00153                     cmd->setStage(osgManipulator::MotionCommand::MOVE);
00154                     cmd->setLocalToWorldAndWorldToLocal(_localToWorld, _worldToLocal);
00155 
00156                     // Dispatch command.
00157                     dispatch(*cmd);
00158 
00159                     setDrawableColor( _pickColor );
00160 
00161                     aa.requestRedraw();
00162                 }                 
00163                 return true; 
00164             }
00165             
00166         // Pick move.
00167         case (osgGA::GUIEventAdapter::DRAG):
00168             {                
00169                 osg::Vec3d near, far, hit;
00170                 pointer.getNearFarPoints(near, far);
00171                 if (getHit(near, far, hit))
00172                 {
00173                     // Generate the motion command.
00174                     osg::ref_ptr<TranslateCommand> cmd = new TranslateCommand();
00175                     hit = hit * _worldToLocal;
00176                     osg::Vec3d start = _startPoint * _worldToLocal;
00177                     osg::Vec3d translation = hit - start;
00178                     cmd->setTranslation(translation);
00179                     cmd->setStage(osgManipulator::MotionCommand::MOVE);
00180                     cmd->setLocalToWorldAndWorldToLocal(_localToWorld, _worldToLocal);
00181 
00182                     // Dispatch command.
00183                     dispatch(*cmd);
00184 
00185                     aa.requestRedraw();
00186                 }           
00187                 return true; 
00188             }
00189             
00190         // Pick finish.
00191         case (osgGA::GUIEventAdapter::RELEASE):
00192             {             
00193                 osg::ref_ptr<TranslateCommand> cmd = new TranslateCommand();
00194                 cmd->setStage(osgManipulator::MotionCommand::FINISH);
00195                 cmd->setLocalToWorldAndWorldToLocal(_localToWorld, _worldToLocal);
00196 
00197                 // Dispatch command.
00198                 dispatch(*cmd);
00199 
00200                 // Reset color.
00201                 setDrawableColor(_color);
00202 
00203                 aa.requestRedraw();
00204 
00205                 return true;
00206             }
00207         default:
00208             return false;
00209     }
00210 }
00211 
00212 bool IntersectingDragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
00213 {
00214     //This is essentialy the same as the original Dragger handle code except for it checks for "all" intersections and not just the first one.
00215     //This allows you to turn depth testing off and have control points that might be obstructed by a mountain still be clickable.
00216     if (ea.getHandled()) return false;
00217 
00218     osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
00219     if (!view) return false;
00220 
00221     bool handled = false;
00222 
00223     bool activationPermitted = true;
00224     if (_activationModKeyMask!=0 || _activationKeyEvent!=0)
00225     {
00226         _activationPermittedByModKeyMask = (_activationModKeyMask!=0) ?
00227             ((ea.getModKeyMask() & _activationModKeyMask)!=0) :
00228             false;
00229 
00230         if (_activationKeyEvent!=0)
00231         {
00232             switch (ea.getEventType())
00233             {
00234                 case osgGA::GUIEventAdapter::KEYDOWN:
00235                 {
00236                     if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = true;
00237                     break;
00238                 }
00239                 case osgGA::GUIEventAdapter::KEYUP:
00240                 {
00241                     if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = false;
00242                     break;
00243                 }
00244                 default:
00245                     break;
00246             }
00247         }
00248 
00249         activationPermitted =  _activationPermittedByModKeyMask || _activationPermittedByKeyEvent;
00250 
00251     }
00252 
00253     if (activationPermitted || _draggerActive)
00254     {
00255         switch (ea.getEventType())
00256         {
00257             case osgGA::GUIEventAdapter::PUSH:
00258             {
00259                 osgUtil::LineSegmentIntersector::Intersections intersections;
00260 
00261                 _pointer.reset();
00262 
00263                 if (view->computeIntersections(ea.getX(),ea.getY(),intersections))
00264                 {
00265                     for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
00266                         hitr != intersections.end();
00267                         ++hitr)
00268                     {
00269                         _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint());
00270                     }
00271                     
00272                     for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
00273                         hitr != intersections.end();
00274                         ++hitr)
00275                     {
00276                         for (osg::NodePath::const_iterator itr = hitr->nodePath.begin();
00277                             itr != hitr->nodePath.end();
00278                             ++itr)
00279                         {
00280                             osgManipulator::Dragger* dragger = dynamic_cast<osgManipulator::Dragger*>(*itr);
00281                             if (dragger)
00282                             {
00283                                 if (dragger==this)
00284                                 {
00285                                     osg::Camera *rootCamera = view->getCamera();
00286                                     osg::NodePath nodePath = _pointer._hitList.front().first;
00287                                     osg::NodePath::reverse_iterator ritr;
00288                                     for(ritr = nodePath.rbegin();
00289                                         ritr != nodePath.rend();
00290                                         ++ritr)
00291                                     {
00292                                         osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr);
00293                                         if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty()))
00294                                         {
00295                                             rootCamera = camera;
00296                                             break;
00297                                         }
00298                                     }
00299 
00300                                     _pointer.setCamera(rootCamera);
00301                                     _pointer.setMousePosition(ea.getX(), ea.getY());
00302 
00303                                     dragger->handle(_pointer, ea, aa);
00304                                     dragger->setDraggerActive(true);
00305                                     handled = true;
00306                                 }
00307                             }
00308                         }
00309                     }
00310                 }
00311             }
00312             case osgGA::GUIEventAdapter::DRAG:
00313             case osgGA::GUIEventAdapter::RELEASE:
00314             {
00315                 if (_draggerActive)
00316                 {
00317                     _pointer._hitIter = _pointer._hitList.begin();
00318 //                    _pointer.setCamera(view->getCamera());
00319                     _pointer.setMousePosition(ea.getX(), ea.getY());
00320 
00321                     handle(_pointer, ea, aa);
00322 
00323                     handled = true;
00324                 }
00325                 break;
00326             }
00327             default:
00328                 break;
00329         }
00330 
00331         if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
00332         {
00333             setDraggerActive(false);
00334             _pointer.reset();
00335         }
00336     }
00337 
00338     return handled;
00339 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines