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.
This commit is contained in:
parent
3a964a6b93
commit
8c0d510571
@ -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&) {};
|
||||
|
@ -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<KeySwitchCameraManipulator>::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<CameraManipulator> _current;
|
||||
|
||||
// Callbacks
|
||||
//CallbackList<KeySwitchCameraManipulator> _cameraManipChangeCallbacks;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -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<osgUtil::SceneView> sceneView;
|
||||
float viewport[4]; // Win-size-relative [0,1]
|
||||
|
||||
osg::ref_ptr<osgGA::CameraManipulator> _cameraManipulator;
|
||||
osg::ref_ptr<osgGA::CameraManipulator> _cameraManipulator;
|
||||
CameraManipList _cameraManipList;
|
||||
|
||||
osg::ref_ptr<osgGA::GUIEventHandler> _eventHandler;
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<ViewportDef> ViewportList;
|
||||
|
@ -7,15 +7,18 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
#include <osg/LineSegment>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/FlightManipulator>
|
||||
#include <osgGA/DriveManipulator>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <osgUtil/IntersectVisitor>
|
||||
|
||||
#include <osg/OccluderNode>
|
||||
#include <osg/Geometry>
|
||||
@ -27,6 +30,13 @@ void write_usage(std::ostream& out,const std::string& name)
|
||||
out <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
|
||||
out << std::endl;
|
||||
out <<"options:"<< std::endl;
|
||||
out <<" -c - set osgoccluder's manual mode for creating occluders."<< std::endl;
|
||||
out <<" press 'a' to start/add points to an occluder, using "<< std::endl;
|
||||
out <<" the nearest vertex to the current mouse poistion."<< std::endl;
|
||||
out <<" press 'e' to end occluder, this occluder is then added"<< std::endl;
|
||||
out <<" into the model."<< std::endl;
|
||||
out <<" press 'O' save just the occluders to disk. "<< std::endl;
|
||||
out << std::endl;
|
||||
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
|
||||
out <<" i.e. -l osgdb_pfb"<< std::endl;
|
||||
out <<" Useful for loading reader/writers which can load"<< std::endl;
|
||||
@ -52,6 +62,142 @@ void write_usage(std::ostream& out,const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OccluderEventHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
OccluderEventHandler(osgUtil::SceneView* sceneview,osg::Group* rootnode):_sceneview(sceneview),_rootnode(rootnode) {}
|
||||
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
|
||||
|
||||
virtual void accept(osgGA::GUIEventHandlerVisitor& v)
|
||||
{
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
void addPoint(const osg::Vec3& pos);
|
||||
|
||||
void endOccluder();
|
||||
|
||||
|
||||
osg::ref_ptr<osgUtil::SceneView> _sceneview;
|
||||
osg::ref_ptr<osg::Group> _rootnode;
|
||||
osg::ref_ptr<osg::Group> _occluders;
|
||||
osg::ref_ptr<osg::ConvexPlanerOccluder> _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<osg::LineSegment> 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'"<<std::endl;
|
||||
osgDB::writeNodeFile(*_occluders,"saved_occluders.osg");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"no occluders to save"<<std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OccluderEventHandler::addPoint(const osg::Vec3& pos)
|
||||
{
|
||||
std::cout<<"add point "<<pos<<std::endl;
|
||||
|
||||
if (!_convexPlanerOccluder.valid()) _convexPlanerOccluder = new osg::ConvexPlanerOccluder;
|
||||
|
||||
osg::ConvexPlanerPolygon& occluder = _convexPlanerOccluder->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"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"Occluder requires at least 3 points to create occluder."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"No occluder points to create occluder with."<<std::endl;
|
||||
}
|
||||
|
||||
// reset current occluder.
|
||||
_convexPlanerOccluder = NULL;
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f)
|
||||
{
|
||||
// create and occluder which will site along side the loadmodel model.
|
||||
@ -125,7 +271,7 @@ osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec
|
||||
|
||||
}
|
||||
|
||||
osg::Node* createOccludersAroundModel(osg::Node* model)
|
||||
osg::Group* createOccludersAroundModel(osg::Node* model)
|
||||
{
|
||||
osg::Group* scene = osgNew osg::Group;
|
||||
scene->setName("rootgroup");
|
||||
@ -187,6 +333,14 @@ int main( int argc, char **argv )
|
||||
std::vector<std::string> commandLine;
|
||||
for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);
|
||||
|
||||
bool manuallyCreateImpostors = false;
|
||||
|
||||
std::vector<std::string>::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();
|
||||
|
||||
|
@ -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){
|
||||
|
@ -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<GLUTEventAdapter> 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<GLUTEventAdapter> 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 "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_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 "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_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 "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_my<< std::endl;
|
||||
}
|
||||
@ -775,8 +802,14 @@ void Viewer::keyboard(unsigned char key, int x, int y)
|
||||
osg::ref_ptr<GLUTEventAdapter> 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osg/GeoSet>
|
||||
#include <osg/Notify>
|
||||
#include <osg/OccluderNode>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <algorithm>
|
||||
@ -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."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" This may impare performance significantly for larger models. It is recommend that one "<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" compiles against STLport or use Visual Studio .NET compiler which also fix these VS 6.0 STL bugs "<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"Warning: this application was built with VisualStudio 6.0's native STL,"<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" and due to bugs in VS's STL we are unable to run state optimizer."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" This may impare performance significantly for larger models."<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" It is recommend that one compiles against STLport or use "<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" Visual Studio .NET compiler which also fix these VS 6.0 STL bugs "<<std::endl;
|
||||
#else
|
||||
StateVisitor osv;
|
||||
node->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<osg::OccluderNode*>(&group))
|
||||
{
|
||||
_redundentNodeList.insert(&group);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user