/* OpenSceneGraph example, osgkeyboardmouse. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ // Simple example of use of osgViewer::GraphicsWindow + Viewer // example that provides the user with control over view position with basic picking. #include #include #include #include #include #include #include #include #include #include #include #include #include #include class CreateModelToSaveVisitor : public osg::NodeVisitor { public: CreateModelToSaveVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _group = new osg::Group; _addToModel = false; } virtual void apply(osg::Node& node) { osgFX::Scribe* scribe = dynamic_cast(&node); if (scribe) { for(unsigned int i=0; igetNumChildren(); ++i) { _group->addChild(scribe->getChild(i)); } } else { traverse(node); } } osg::ref_ptr _group; bool _addToModel; }; class DeleteSelectedNodesVisitor : public osg::NodeVisitor { public: DeleteSelectedNodesVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { } virtual void apply(osg::Node& node) { osgFX::Scribe* scribe = dynamic_cast(&node); if (scribe) { _selectedNodes.push_back(scribe); } else { traverse(node); } } void pruneSelectedNodes() { for(SelectedNodes::iterator itr = _selectedNodes.begin(); itr != _selectedNodes.end(); ++itr) { osg::Node* node = itr->get(); osg::Node::ParentList parents = node->getParents(); for(osg::Node::ParentList::iterator pitr = parents.begin(); pitr != parents.end(); ++pitr) { (*pitr)->removeChild(node); } } } typedef std::vector< osg::ref_ptr > SelectedNodes; SelectedNodes _selectedNodes; }; // class to handle events with a pick class PickHandler : public osgGA::GUIEventHandler { public: PickHandler(): _mx(0.0),_my(0.0), _usePolytopeIntersector(false), _useWindowCoordinates(false), _precisionHint(osgUtil::Intersector::USE_DOUBLE_CALCULATIONS), _primitiveMask(osgUtil::PolytopeIntersector::ALL_PRIMITIVES) {} ~PickHandler() {} void setPrimitiveMask(unsigned int primitiveMask) { _primitiveMask = primitiveMask; } bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::Viewer* viewer = dynamic_cast(&aa); if (!viewer) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): { if (ea.getKey()=='s') { saveSelectedModel(viewer->getSceneData()); } else if (ea.getKey()=='o') { osg::notify(osg::NOTICE)<<"Saved model to file 'saved_model.osgt'"<getSceneData()), "saved_model.osgt"); } else if (ea.getKey()=='p') { _usePolytopeIntersector = !_usePolytopeIntersector; if (_usePolytopeIntersector) { osg::notify(osg::NOTICE)<<"Using PolytopeIntersector"<getSceneData()->accept(dsnv); dsnv.pruneSelectedNodes(); } return false; } case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::MOVE): { _mx = ea.getX(); _my = ea.getY(); return false; } case(osgGA::GUIEventAdapter::RELEASE): { if (_mx == ea.getX() && _my == ea.getY()) { // only do a pick if the mouse hasn't moved pick(ea,viewer); } return true; } default: return false; } } void fullWindowIntersectionTest(osgViewer::Viewer* viewer) { osg::ref_ptr intersectors = new osgUtil::IntersectorGroup; osg::Viewport* viewport = viewer->getCamera()->getViewport(); unsigned int numX = 100; unsigned int numY = 100; double dx = viewport->width()/double(numX-1); double dy = viewport->width()/double(numX-1); double y = viewport->x(); for(unsigned int r=0; rx(); for(unsigned int c=0; c intersector; if (_usePolytopeIntersector) { osg::ref_ptr pi = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, x-dx*0.5, y-dy*0.5, x+dx*0.5, y+dy*0.5); pi->setPrimitiveMask(_primitiveMask); intersector = pi.get(); } else { intersector = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, x, y); } intersector->setPrecisionHint(_precisionHint); intersectors->getIntersectors().push_back(intersector); x += dx; } y += dy; } osgUtil::IntersectionVisitor iv(intersectors.get()); osg::ElapsedTime elapsedTime; viewer->getCamera()->accept(iv); OSG_NOTICE<<"Intersection traversal took "<getIntersectors().size()<<" intersectors"<getSceneData(); if (!scene) return; osg::notify(osg::NOTICE)<getCamera()->getViewport(); double mx = viewport->x() + (int)((double )viewport->width()*(ea.getXnormalized()*0.5+0.5)); double my = viewport->y() + (int)((double )viewport->height()*(ea.getYnormalized()*0.5+0.5)); // half width, height. double w = 5.0f; double h = 5.0f; picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, mx-w, my-h, mx+w, my+h ); } else { double mx = ea.getXnormalized(); double my = ea.getYnormalized(); double w = 0.05; double h = 0.05; picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::PROJECTION, mx-w, my-h, mx+w, my+h ); } picker->setPrecisionHint(_precisionHint); picker->setPrimitiveMask(_primitiveMask); osgUtil::IntersectionVisitor iv(picker); osg::ElapsedTime elapsedTime; viewer->getCamera()->accept(iv); OSG_NOTICE<<"PoltyopeIntersector traversal took "<containsIntersections()) { osgUtil::PolytopeIntersector::Intersection intersection = picker->getFirstIntersection(); osg::notify(osg::NOTICE)<<"Picked "<=1)?nodePath[nodePath.size()-1]:0; parent = (nodePath.size()>=2)?dynamic_cast(nodePath[nodePath.size()-2]):0; if (node) std::cout<<" Hits "<className()<<" nodePath size "<getCamera()->getViewport(); float mx = viewport->x() + (int)((float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f)); float my = viewport->y() + (int)((float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f)); picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, mx, my ); } picker->setPrecisionHint(_precisionHint); osgUtil::IntersectionVisitor iv(picker); osg::ElapsedTime elapsedTime; viewer->getCamera()->accept(iv); OSG_NOTICE<<"LineSegmentIntersector traversal took "<containsIntersections()) { osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection(); osg::notify(osg::NOTICE)<<"Picked "<=1)?nodePath[nodePath.size()-1]:0; parent = (nodePath.size()>=2)?dynamic_cast(nodePath[nodePath.size()-2]):0; if (node) std::cout<<" Hits "<className()<<" nodePath size"<className()<(parent); if (!parentAsScribe) { // node not already picked, so highlight it with an osgFX::Scribe osgFX::Scribe* scribe = new osgFX::Scribe(); scribe->addChild(node); parent->replaceChild(node,scribe); } else { // node already picked so we want to remove scribe to unpick it. osg::Node::ParentList parentList = parentAsScribe->getParents(); for(osg::Node::ParentList::iterator itr=parentList.begin(); itr!=parentList.end(); ++itr) { (*itr)->replaceChild(parentAsScribe,node); } } } void saveSelectedModel(osg::Node* scene) { if (!scene) return; CreateModelToSaveVisitor cmtsv; scene->accept(cmtsv); if (cmtsv._group->getNumChildren()>0) { std::cout<<"Writing selected components to 'selected_model.osgt'"<getNumElements(); if (_mode==osg::PrimitiveSet::POINTS) { // remove previous primitive sets. geometry.removePrimitiveSet(0, geometry.getNumPrimitiveSets()); geometry.addPrimitiveSet(new osg::DrawArrays(_mode, 0,numVertices)); } else if (_mode==osg::PrimitiveSet::LINES) { geometry.removePrimitiveSet(0, geometry.getNumPrimitiveSets()); geometry.addPrimitiveSet(new osg::DrawArrays(_mode, 0,numVertices)); } } }; int main( int argc, char **argv ) { osg::ArgumentParser arguments(&argc, argv); osgViewer::Viewer viewer(arguments); bool useKdTree = false; while (arguments.read("--kdtree")) { useKdTree = true; } osg::ref_ptr pickhandler = new PickHandler; while (arguments.read("--double")) { pickhandler->setPrecisionHint(osgUtil::Intersector::USE_DOUBLE_CALCULATIONS); } while (arguments.read("--float")) { pickhandler->setPrecisionHint(osgUtil::Intersector::USE_FLOAT_CALCULATIONS); } unsigned int mask = osgUtil::PolytopeIntersector::ALL_PRIMITIVES; while (arguments.read("--prim-mask", mask) || arguments.read("--pm", mask)) { pickhandler->setPrimitiveMask(mask); } // load model osg::ref_ptr loadedModel = osgDB::readRefNodeFiles(arguments); // if not loaded assume no arguments passed in, try use default mode instead. if (!loadedModel) loadedModel = osgDB::readRefNodeFile("dumptruck.osgt"); if (!loadedModel) { std::cout << argv[0] <<": No data loaded." << std::endl; return 1; } while(arguments.read("--points")) { ConvertPrimitives cp(osg::PrimitiveSet::POINTS); loadedModel->accept(cp); } while(arguments.read("--lines")) { ConvertPrimitives cp(osg::PrimitiveSet::LINES); loadedModel->accept(cp); } if (useKdTree) { OSG_NOTICE<<"Building KdTrees"< builder = new osg::KdTreeBuilder; loadedModel->accept(*builder); } // assign the scene graph to viewer viewer.setSceneData(loadedModel); // create a tracball manipulator to move the camera around in response to keyboard/mouse events viewer.setCameraManipulator( new osgGA::TrackballManipulator ); osg::ref_ptr statesetManipulator = new osgGA::StateSetManipulator(viewer.getCamera()->getStateSet()); viewer.addEventHandler(statesetManipulator.get()); // add the pick handler viewer.addEventHandler(pickhandler.get()); viewer.realize(); // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.) while(!viewer.done()) { viewer.frame(); } return 0; }