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 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 }