From 8c0d510571b15e673b555e22186a7110355fca1a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 Jul 2002 10:00:50 +0000 Subject: [PATCH] Several items of work related to adding a manual creation of occluders option to the osgoccluder demo. First the osgGA classes have been generalised a little to better support new GUIEventHandler subclasses. Second osgGLUT has a new option for registering a user defined event handler, the allows the application to add externally extra options to the osgGLUT viewer. Third, the osgoccluder demo now works in two modes. The original create four occluder sides to wrap an loaded model, the second an interactive mode which allows the users to add occluders to the model by pointing to points and pressing 'a' to add a point, the 'e' to end the occluder polygon, polygons must be convex, planer and be defined in an anitclockwise order. To start the osgoccluder in this mode one simple runs it with the '-c' option. Run osgoccluder with no parameter to get a list of options. --- include/osgGA/GUIEventHandlerVisitor | 2 + include/osgGA/KeySwitchCameraManipulator | 14 +- include/osgGLUT/Viewer | 7 +- src/Demos/osgoccluder/osgoccluder.cpp | 180 ++++++++++++++++++++++- src/osgGA/KeySwitchCameraManipulator.cpp | 7 + src/osgGLUT/Viewer.cpp | 45 +++++- src/osgUtil/Optimizer.cpp | 12 +- 7 files changed, 238 insertions(+), 29 deletions(-) diff --git a/include/osgGA/GUIEventHandlerVisitor b/include/osgGA/GUIEventHandlerVisitor index 44c0441d4..b363ac311 100644 --- a/include/osgGA/GUIEventHandlerVisitor +++ b/include/osgGA/GUIEventHandlerVisitor @@ -9,6 +9,7 @@ namespace osgGA{ // Some forward declarations class GUIActionAdapter; +class GUIEventHandler; class CompositeGUIEventHandler; class CameraManipulator; class StateSetManipulator; @@ -26,6 +27,7 @@ class OSGGA_EXPORT GUIEventHandlerVisitor { public: + virtual void visit(GUIEventHandler&) {} virtual void visit(CompositeGUIEventHandler&); virtual void visit(CameraManipulator&) {}; virtual void visit(StateSetManipulator&) {}; diff --git a/include/osgGA/KeySwitchCameraManipulator b/include/osgGA/KeySwitchCameraManipulator index 484f7dd29..c614fef77 100644 --- a/include/osgGA/KeySwitchCameraManipulator +++ b/include/osgGA/KeySwitchCameraManipulator @@ -24,17 +24,8 @@ class OSGGA_EXPORT KeySwitchCameraManipulator : public CameraManipulator void addCameraManipulator(int key, std::string name, CameraManipulator *cm); - //typedef void (* Callback)(KeySwitchCameraManipulator *); + void addNumberedCameraManipulator(CameraManipulator *cm); -// class Callback: public osgUtil::CallbackList::Callback { -// public: -// virtual ~Callback() {}; -// virtual void operator()(KeySwitchCameraManipulator *) = 0; -// }; -// -// void addCallback(Callback*); -// -// void removeCallback(Callback*); // Overrides from CameraManipulator... @@ -64,9 +55,6 @@ class OSGGA_EXPORT KeySwitchCameraManipulator : public CameraManipulator osg::ref_ptr _current; - // Callbacks - //CallbackList _cameraManipChangeCallbacks; - }; }; diff --git a/include/osgGLUT/Viewer b/include/osgGLUT/Viewer index e9d08fd11..d92292354 100644 --- a/include/osgGLUT/Viewer +++ b/include/osgGLUT/Viewer @@ -81,6 +81,8 @@ class OSGGLUT_EXPORT Viewer : public Window, public osgGA::GUIActionAdapter void selectCameraManipulator(unsigned int pos, unsigned int viewport = 0); + void setEventHandler(osgGA::GUIEventHandler* handler,unsigned int viewport = 0); + // derived from osgGA::GUIActionAdapter virtual void requestRedraw() {} // redraw always by idle callback done. virtual void requestContinuousUpdate(bool /*needed*/) {} // continuous update always @@ -119,8 +121,11 @@ class OSGGLUT_EXPORT Viewer : public Window, public osgGA::GUIActionAdapter osg::ref_ptr sceneView; float viewport[4]; // Win-size-relative [0,1] - osg::ref_ptr _cameraManipulator; + osg::ref_ptr _cameraManipulator; CameraManipList _cameraManipList; + + osg::ref_ptr _eventHandler; + }; typedef std::vector ViewportList; diff --git a/src/Demos/osgoccluder/osgoccluder.cpp b/src/Demos/osgoccluder/osgoccluder.cpp index 99b04e974..3ba08dd7b 100644 --- a/src/Demos/osgoccluder/osgoccluder.cpp +++ b/src/Demos/osgoccluder/osgoccluder.cpp @@ -7,15 +7,18 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include @@ -27,6 +30,13 @@ void write_usage(std::ostream& out,const std::string& name) out <<" "< _sceneview; + osg::ref_ptr _rootnode; + osg::ref_ptr _occluders; + osg::ref_ptr _convexPlanerOccluder; +}; + +bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) +{ + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYBOARD): + { + if (ea.getKey()=='a') + { + + int x = ea.getX(); + int y = ea.getY(); + + osg::Vec3 near_point,far_point; + if (!_sceneview->projectWindowXYIntoObject(x,ea.getYmax()-y,near_point,far_point)) + { + return true; + } + + osg::ref_ptr lineSegment = osgNew osg::LineSegment; + lineSegment->set(near_point,far_point); + + osgUtil::IntersectVisitor iv; + iv.addLineSegment(lineSegment.get()); + + _rootnode->accept(iv); + + if (iv.hits()) + { + + osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(lineSegment.get()); + if (!hitList.empty()) + { + + osgUtil::Hit& hit = hitList.front(); + addPoint(hit.getWorldIntersectPoint()); + } + + } + + return true; + } + else if (ea.getKey()=='e') + { + endOccluder(); + return true; + } + else if (ea.getKey()=='O') + { + if (_occluders.valid()) + { + std::cout<<"saving occluders to 'saved_occluders.osg'"<getOccluder(); + occluder.add(pos); + +} + +void OccluderEventHandler::endOccluder() +{ + if (_convexPlanerOccluder.valid()) + { + if (_convexPlanerOccluder->getOccluder().getVertexList().size()>=3) + { + osg::OccluderNode* occluderNode = osgNew osg::OccluderNode; + occluderNode->setOccluder(_convexPlanerOccluder.get()); + + if (!_occluders.valid()) + { + _occluders = new osg::Group; + _rootnode->addChild(_occluders.get()); + } + _occluders->addChild(occluderNode); + + std::cout<<"created occluder"<setName("rootgroup"); @@ -187,6 +333,14 @@ int main( int argc, char **argv ) std::vector commandLine; for(int i=1;i::iterator itr=std::find(commandLine.begin(),commandLine.end(),std::string("-c")); + if (itr!=commandLine.end()) + { + manuallyCreateImpostors = true; + commandLine.erase(itr); + } // initialize the viewer. osgGLUT::Viewer viewer; @@ -208,12 +362,23 @@ int main( int argc, char **argv ) return 1; } - // add the occluders to the loaded model. - osg::Node* rootnode = createOccludersAroundModel(loadedmodel); - // run optimization over the scene graph osgUtil::Optimizer optimzer; - optimzer.optimize(rootnode); + optimzer.optimize(loadedmodel); + + // add the occluders to the loaded model. + osg::Group* rootnode = NULL; + + if (manuallyCreateImpostors) + { + rootnode = new osg::Group; + rootnode->addChild(loadedmodel); + } + else + { + rootnode = createOccludersAroundModel(loadedmodel); + } + // add a viewport to the viewer and attach the scene graph. viewer.addViewport( rootnode ); @@ -223,6 +388,11 @@ int main( int argc, char **argv ) viewer.registerCameraManipulator(new osgGA::FlightManipulator); viewer.registerCameraManipulator(new osgGA::DriveManipulator); + if (manuallyCreateImpostors) + { + viewer.setEventHandler(new OccluderEventHandler(viewer.getViewportSceneView(0),rootnode)); + } + // open the viewer window. viewer.open(); diff --git a/src/osgGA/KeySwitchCameraManipulator.cpp b/src/osgGA/KeySwitchCameraManipulator.cpp index 315a2a829..9f87189cc 100644 --- a/src/osgGA/KeySwitchCameraManipulator.cpp +++ b/src/osgGA/KeySwitchCameraManipulator.cpp @@ -13,6 +13,13 @@ void KeySwitchCameraManipulator::addCameraManipulator(int key, std::string name, } } +void KeySwitchCameraManipulator::addNumberedCameraManipulator(CameraManipulator *cm) +{ + if(!cm) return; + addCameraManipulator('1'+_manips.size(),"camera",cm); +} + + bool KeySwitchCameraManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa) { if(ea.getEventType()==GUIEventAdapter::KEYBOARD){ diff --git a/src/osgGLUT/Viewer.cpp b/src/osgGLUT/Viewer.cpp index b02d638fd..71f10eea7 100644 --- a/src/osgGLUT/Viewer.cpp +++ b/src/osgGLUT/Viewer.cpp @@ -290,6 +290,11 @@ unsigned int Viewer::registerCameraManipulator(osgGA::CameraManipulator* cm, return pos; } +void Viewer::setEventHandler(osgGA::GUIEventHandler* handler,unsigned int viewport = 0) +{ + ViewportDef &viewp = _viewportList[viewport]; + viewp._eventHandler = handler; +} void Viewer::setFocusedViewport(unsigned int pos) { @@ -337,11 +342,16 @@ float Viewer::app(unsigned int viewport) osg::ref_ptr ea = osgNew GLUTEventAdapter; ea->adaptFrame(_frameStamp->getReferenceTime()); - if (_viewportList[viewport]._cameraManipulator->handle(*ea,*this)) + if (_viewportList[viewport]._eventHandler.valid() && _viewportList[viewport]._eventHandler->handle(*ea,*this)) + { + // event handler handle this call. + } + else if (_viewportList[viewport]._cameraManipulator->handle(*ea,*this)) { // osg::notify(osg::INFO) << "Handled update frame"<< std::endl; } + // do app traversal. getViewportSceneView(viewport)->setFrameStamp(_frameStamp.get()); @@ -704,6 +714,11 @@ void Viewer::reshape(GLint w, GLint h) { // osg::notify(osg::INFO) << "Handled reshape "<< std::endl; } + if (itr->_eventHandler.valid() && itr->_eventHandler->handle(*ea,*this)) + { + // event handler handle this call. + } + } } @@ -713,7 +728,11 @@ void Viewer::mouseMotion(int x, int y) osg::ref_ptr ea = osgNew GLUTEventAdapter; ea->adaptMouseMotion(clockSeconds(),x,y); - if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) + if (_viewportList[_focusedViewport]._eventHandler.valid() && _viewportList[_focusedViewport]._eventHandler->handle(*ea,*this)) + { + // event handler handle this call. + } + else if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) { // osg::notify(osg::INFO) << "Handled mouseMotion "<_buttonMask<<" x="<_mx<<" y="<_my<< std::endl; } @@ -737,7 +756,11 @@ void Viewer::mousePassiveMotion(int x, int y) setFocusedViewport(focus); } - if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) + if (_viewportList[_focusedViewport]._eventHandler.valid() && _viewportList[_focusedViewport]._eventHandler->handle(*ea,*this)) + { + // event handler handle this call. + } + else if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) { // osg::notify(osg::INFO) << "Handled mousePassiveMotion "<_buttonMask<<" x="<_mx<<" y="<_my<< std::endl; } @@ -761,7 +784,11 @@ void Viewer::mouse(int button, int state, int x, int y) setFocusedViewport(focus); } - if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) + if (_viewportList[_focusedViewport]._eventHandler.valid() && _viewportList[_focusedViewport]._eventHandler->handle(*ea,*this)) + { + // event handler handle this call. + } + else if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) { // osg::notify(osg::INFO) << "Handled mouse "<_buttonMask<<" x="<_mx<<" y="<_my<< std::endl; } @@ -775,8 +802,14 @@ void Viewer::keyboard(unsigned char key, int x, int y) osg::ref_ptr ea = osgNew GLUTEventAdapter; ea->adaptKeyboard(clockSeconds(),key,x,y); - if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) - return; + if (_viewportList[_focusedViewport]._eventHandler.valid() && _viewportList[_focusedViewport]._eventHandler->handle(*ea,*this)) + { + return; + } + else if (_viewportList[_focusedViewport]._cameraManipulator->handle(*ea,*this)) + { + return; + } diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 3b2425dc5..a3a1dd68e 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -72,9 +73,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) if (options & SHARE_DUPLICATE_STATE) { #if (defined(_MSC_VER) && _MSC_VER<1300 && !defined(_STLPORT_VERSION)) - osg::notify(osg::NOTICE)<<"Warning: VisualStudio 6.0 native STL build, unable to run state optimizer due to bugs in its STL."<accept(osv); @@ -931,7 +934,8 @@ void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group) { if (group.getNumParents()>0) { - if (group.getNumChildren()==0) + // only remove empty groups, but not empty occluders. + if (group.getNumChildren()==0 && !dynamic_cast(&group)) { _redundentNodeList.insert(&group); }