From e5a365afee623fde241e20371f99ef1436ae8595 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 11 Aug 2007 10:28:14 +0000 Subject: [PATCH] Added support for an update OperationQueue to Viewer and CompositeViewer to allow asyncrnous adding of operations to be added to the view to be done during syncronous updateTraversal(). This feature can be used for doing things like merging subgraphs that have been loaded in a background thread. --- include/osg/OperationThread | 3 + include/osgViewer/CompositeViewer | 46 ++++++++- include/osgViewer/Viewer | 41 ++++++++ src/osg/OperationThread.cpp | 34 +++++++ src/osgViewer/CompositeViewer.cpp | 33 ++++++- src/osgViewer/Viewer.cpp | 24 +++++ src/osgWrappers/osg/OperationThread.cpp | 5 + src/osgWrappers/osgViewer/CompositeViewer.cpp | 99 ++++++++++++++++++- src/osgWrappers/osgViewer/Viewer.cpp | 66 +++++++++++++ 9 files changed, 348 insertions(+), 3 deletions(-) diff --git a/include/osg/OperationThread b/include/osg/OperationThread index 20a579bdd..13a2187cf 100644 --- a/include/osg/OperationThread +++ b/include/osg/OperationThread @@ -109,6 +109,9 @@ class OSG_EXPORT OperationQueue : public Referenced /** Remove all operations from OperationQueue.*/ void removeAllOperations(); + + /** Run the operations. */ + void runOperations(Object* callingObject=0); /** Call release on all operations. */ void releaseAllOperations(); diff --git a/include/osgViewer/CompositeViewer b/include/osgViewer/CompositeViewer index a5b93fa66..be2d334d1 100644 --- a/include/osgViewer/CompositeViewer +++ b/include/osgViewer/CompositeViewer @@ -22,13 +22,17 @@ namespace osgViewer { /** CompsiteViewer holds a or more views to a one more scenes.*/ -class OSGVIEWER_EXPORT CompositeViewer : public osg::Referenced +class OSGVIEWER_EXPORT CompositeViewer : public osg::Object { public: CompositeViewer(); + CompositeViewer(const CompositeViewer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + CompositeViewer(osg::ArgumentParser& arguments); + + META_Object(osg,CompositeViewer); virtual ~CompositeViewer(); @@ -88,6 +92,18 @@ class OSGVIEWER_EXPORT CompositeViewer : public osg::Referenced /** Get the end barrier position.*/ BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } + + + /** Set the EventVisitor. */ + void setEventVisitor(osgGA::EventVisitor* eventVisitor) { _eventVisitor = eventVisitor; } + + /** Get the EventVisitor. */ + osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); } + + /** Get the const EventVisitor. */ + const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); } + + void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; } osgGA::EventQueue* getEventQueue() { return _eventQueue.get(); } const osgGA::EventQueue* getEventQueue() const { return _eventQueue.get(); } @@ -107,6 +123,34 @@ class OSGVIEWER_EXPORT CompositeViewer : public osg::Referenced /** @return true if the viewer respond to the QUIT_APPLICATION-event */ bool getQuitEventSetsDone() const { return _quitEventSetsDone; } + + + /** Set the UpdateVisitor. */ + void setUpdateVisitor(osgUtil::UpdateVisitor* updateVisitor) { _updateVisitor = updateVisitor; } + + /** Get the UpdateVisitor. */ + osgUtil::UpdateVisitor* getUpdateVisitor() { return _updateVisitor.get(); } + + /** Get the const UpdateVisitor. */ + const osgUtil::UpdateVisitor* getUpdateVisitor() const { return _updateVisitor.get(); } + + + /** Set the Update OperationQueue. */ + void setUpdateOperations(osg::OperationQueue* operations) { _updateOperations = operations; } + + /** Get the Update OperationQueue. */ + osg::OperationQueue* getUpdateOperations() { return _updateOperations.get(); } + + /** Get the const Update OperationQueue. */ + const osg::OperationQueue* getUpdateOperations() const { return _updateOperations.get(); } + + /** Add an update operation.*/ + void addUpdateOperation(osg::Operation* operation); + + /** Remove an update operation.*/ + void removeUpdateOperation(osg::Operation* operation); + + /** Execute a main frame loop. * Equivialant to while (!viewer.done()) viewer.frame(); * Also calls realize() if the viewer is not already realized, diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 11cb6fc58..4fb1e916b 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -97,6 +97,17 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** Get the end barrier position.*/ BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } + + + /** Set the EventVisitor. */ + void setEventVisitor(osgGA::EventVisitor* eventVisitor) { _eventVisitor = eventVisitor; } + + /** Get the EventVisitor. */ + osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); } + + /** Get the const EventVisitor. */ + const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); } + /** Set the key event that the viewer checks on each frame to see if the viewer's done flag should be set to * signal end of viewers main loop. * Default value is Escape (osgGA::GUIEVentAdapter::KEY_Escape). @@ -112,6 +123,36 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** @return true if the viewer respond to the QUIT_APPLICATION-event */ bool getQuitEventSetsDone() const { return _quitEventSetsDone; } + + + + + /** Set the UpdateVisitor. */ + void setUpdateVisitor(osgUtil::UpdateVisitor* updateVisitor) { _updateVisitor = updateVisitor; } + + /** Get the UpdateVisitor. */ + osgUtil::UpdateVisitor* getUpdateVisitor() { return _updateVisitor.get(); } + + /** Get the const UpdateVisitor. */ + const osgUtil::UpdateVisitor* getUpdateVisitor() const { return _updateVisitor.get(); } + + + /** Set the Update OperationQueue. */ + void setUpdateOperations(osg::OperationQueue* operations) { _updateOperations = operations; } + + /** Get the Update OperationQueue. */ + osg::OperationQueue* getUpdateOperations() { return _updateOperations.get(); } + + /** Get the const Update OperationQueue. */ + const osg::OperationQueue* getUpdateOperations() const { return _updateOperations.get(); } + + /** Add an update operation.*/ + void addUpdateOperation(osg::Operation* operation); + + /** Remove an update operation.*/ + void removeUpdateOperation(osg::Operation* operation); + + /** Execute a main frame loop. * Equivialant to while (!viewer.done()) viewer.frame(); * Also calls realize() if the viewer is not already realized, diff --git a/src/osg/OperationThread.cpp b/src/osg/OperationThread.cpp index 4cc00419c..d7ceda3d4 100644 --- a/src/osg/OperationThread.cpp +++ b/src/osg/OperationThread.cpp @@ -181,6 +181,40 @@ void OperationQueue::removeAllOperations() } } +void OperationQueue::runOperations(Object* callingObject) +{ + OpenThreads::ScopedLock lock(_operationsMutex); + + // reset current operation iterator to begining if at end. + if (_currentOperationIterator==_operations.end()) _currentOperationIterator = _operations.begin(); + + for(; + _currentOperationIterator != _operations.end(); + ) + { + ref_ptr operation = *_currentOperationIterator; + + if (!operation->getKeep()) + { + _currentOperationIterator = _operations.erase(_currentOperationIterator); + } + else + { + ++_currentOperationIterator; + } + + // osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<set(false); + } +} + void OperationQueue::releaseOperationsBlock() { _operationsBlock->release(); diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index dabaf7633..adad489b8 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -27,6 +27,12 @@ CompositeViewer::CompositeViewer() constructorInit(); } +CompositeViewer::CompositeViewer(const CompositeViewer& cv,const osg::CopyOp& copyop): + osg::Object(cv,copyop) +{ + constructorInit(); +} + CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments) { constructorInit(); @@ -978,6 +984,26 @@ void CompositeViewer::eventTraversal() } } + +void CompositeViewer::addUpdateOperation(osg::Operation* operation) +{ + if (!operation) return; + + if (!_updateOperations) _updateOperations = new osg::OperationQueue; + + _updateOperations->add(operation); +} + +void CompositeViewer::removeUpdateOperation(osg::Operation* operation) +{ + if (!operation) return; + + if (_updateOperations.valid()) + { + _updateOperations->remove(operation); + } +} + void CompositeViewer::updateTraversal() { if (_done) return; @@ -1001,7 +1027,12 @@ void CompositeViewer::updateTraversal() } } - + + if (_updateOperations.valid()) + { + _updateOperations->runOperations(this); + } + for(Views::iterator vitr = _views.begin(); vitr != _views.end(); ++vitr) diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 2ec9f6ec9..733e5260d 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -1326,6 +1326,25 @@ void Viewer::eventTraversal() } +void Viewer::addUpdateOperation(osg::Operation* operation) +{ + if (!operation) return; + + if (!_updateOperations) _updateOperations = new osg::OperationQueue; + + _updateOperations->add(operation); +} + +void Viewer::removeUpdateOperation(osg::Operation* operation) +{ + if (!operation) return; + + if (_updateOperations.valid()) + { + _updateOperations->remove(operation); + } +} + void Viewer::updateTraversal() { if (_done) return; @@ -1343,6 +1362,11 @@ void Viewer::updateTraversal() _scene->getDatabasePager()->updateSceneGraph(_frameStamp->getReferenceTime()); } + if (_updateOperations.valid()) + { + _updateOperations->runOperations(this); + } + { // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph // leave that to the scene update traversal. diff --git a/src/osgWrappers/osg/OperationThread.cpp b/src/osgWrappers/osg/OperationThread.cpp index 95c2bf835..02bdc5c93 100644 --- a/src/osgWrappers/osg/OperationThread.cpp +++ b/src/osgWrappers/osg/OperationThread.cpp @@ -99,6 +99,11 @@ BEGIN_OBJECT_REFLECTOR(osg::OperationQueue) __void__removeAllOperations, "Remove all operations from OperationQueue. ", ""); + I_MethodWithDefaults1(void, runOperations, IN, osg::Object *, callingObject, 0, + Properties::NON_VIRTUAL, + __void__runOperations__Object_P1, + "Run the operations. ", + ""); I_Method0(void, releaseAllOperations, Properties::NON_VIRTUAL, __void__releaseAllOperations, diff --git a/src/osgWrappers/osgViewer/CompositeViewer.cpp b/src/osgWrappers/osgViewer/CompositeViewer.cpp index 993f54966..528eca0a8 100644 --- a/src/osgWrappers/osgViewer/CompositeViewer.cpp +++ b/src/osgWrappers/osgViewer/CompositeViewer.cpp @@ -12,10 +12,14 @@ #include #include +#include #include +#include #include #include #include +#include +#include #include #include @@ -48,15 +52,44 @@ END_REFLECTOR BEGIN_OBJECT_REFLECTOR(osgViewer::CompositeViewer) I_DeclaringFile("osgViewer/CompositeViewer"); - I_BaseType(osg::Referenced); + I_BaseType(osg::Object); I_Constructor0(____CompositeViewer, "", ""); + I_ConstructorWithDefaults2(IN, const osgViewer::CompositeViewer &, x, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY, + ____CompositeViewer__C5_CompositeViewer_R1__C5_osg_CopyOp_R1, + "", + ""); I_Constructor1(IN, osg::ArgumentParser &, arguments, Properties::NON_EXPLICIT, ____CompositeViewer__osg_ArgumentParser_R1, "", ""); + I_Method0(osg::Object *, cloneType, + Properties::VIRTUAL, + __osg_Object_P1__cloneType, + "Clone the type of an object, with Object* return type. ", + "Must be defined by derived classes. "); + I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop, + Properties::VIRTUAL, + __osg_Object_P1__clone__C5_osg_CopyOp_R1, + "Clone an object, with Object* return type. ", + "Must be defined by derived classes. "); + I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj, + Properties::VIRTUAL, + __bool__isSameKindAs__C5_osg_Object_P1, + "", + ""); + I_Method0(const char *, libraryName, + Properties::VIRTUAL, + __C5_char_P1__libraryName, + "return the name of the object's library. ", + "Must be defined by derived classes. The OpenSceneGraph convention is that the namespace of a library is the same as the library name. "); + I_Method0(const char *, className, + Properties::VIRTUAL, + __C5_char_P1__className, + "return the name of the object's class type. ", + "Must be defined by derived classes. "); I_Method1(void, addView, IN, osgViewer::View *, view, Properties::NON_VIRTUAL, __void__addView__osgViewer_View_P1, @@ -147,6 +180,21 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::CompositeViewer) __BarrierPosition__getEndBarrierPosition, "Get the end barrier position. ", ""); + I_Method1(void, setEventVisitor, IN, osgGA::EventVisitor *, eventVisitor, + Properties::NON_VIRTUAL, + __void__setEventVisitor__osgGA_EventVisitor_P1, + "Set the EventVisitor. ", + ""); + I_Method0(osgGA::EventVisitor *, getEventVisitor, + Properties::NON_VIRTUAL, + __osgGA_EventVisitor_P1__getEventVisitor, + "Get the EventVisitor. ", + ""); + I_Method0(const osgGA::EventVisitor *, getEventVisitor, + Properties::NON_VIRTUAL, + __C5_osgGA_EventVisitor_P1__getEventVisitor, + "Get the const EventVisitor. ", + ""); I_Method1(void, setEventQueue, IN, osgGA::EventQueue *, eventQueue, Properties::NON_VIRTUAL, __void__setEventQueue__osgGA_EventQueue_P1, @@ -182,6 +230,46 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::CompositeViewer) __bool__getQuitEventSetsDone, "", "true if the viewer respond to the QUIT_APPLICATION-event "); + I_Method1(void, setUpdateVisitor, IN, osgUtil::UpdateVisitor *, updateVisitor, + Properties::NON_VIRTUAL, + __void__setUpdateVisitor__osgUtil_UpdateVisitor_P1, + "Set the UpdateVisitor. ", + ""); + I_Method0(osgUtil::UpdateVisitor *, getUpdateVisitor, + Properties::NON_VIRTUAL, + __osgUtil_UpdateVisitor_P1__getUpdateVisitor, + "Get the UpdateVisitor. ", + ""); + I_Method0(const osgUtil::UpdateVisitor *, getUpdateVisitor, + Properties::NON_VIRTUAL, + __C5_osgUtil_UpdateVisitor_P1__getUpdateVisitor, + "Get the const UpdateVisitor. ", + ""); + I_Method1(void, setUpdateOperations, IN, osg::OperationQueue *, operations, + Properties::NON_VIRTUAL, + __void__setUpdateOperations__osg_OperationQueue_P1, + "Set the Update OperationQueue. ", + ""); + I_Method0(osg::OperationQueue *, getUpdateOperations, + Properties::NON_VIRTUAL, + __osg_OperationQueue_P1__getUpdateOperations, + "Get the Update OperationQueue. ", + ""); + I_Method0(const osg::OperationQueue *, getUpdateOperations, + Properties::NON_VIRTUAL, + __C5_osg_OperationQueue_P1__getUpdateOperations, + "Get the const Update OperationQueue. ", + ""); + I_Method1(void, addUpdateOperation, IN, osg::Operation *, operation, + Properties::NON_VIRTUAL, + __void__addUpdateOperation__osg_Operation_P1, + "Add an update operation. ", + ""); + I_Method1(void, removeUpdateOperation, IN, osg::Operation *, operation, + Properties::NON_VIRTUAL, + __void__removeUpdateOperation__osg_Operation_P1, + "Remove an update operation. ", + ""); I_Method0(int, run, Properties::VIRTUAL, __int__run, @@ -313,6 +401,9 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::CompositeViewer) I_SimpleProperty(osgGA::EventQueue *, EventQueue, __osgGA_EventQueue_P1__getEventQueue, __void__setEventQueue__osgGA_EventQueue_P1); + I_SimpleProperty(osgGA::EventVisitor *, EventVisitor, + __osgGA_EventVisitor_P1__getEventVisitor, + __void__setEventVisitor__osgGA_EventVisitor_P1); I_SimpleProperty(osg::FrameStamp *, FrameStamp, __osg_FrameStamp_P1__getFrameStamp, 0); @@ -334,6 +425,12 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::CompositeViewer) I_SimpleProperty(osgViewer::CompositeViewer::ThreadingModel, ThreadingModel, __ThreadingModel__getThreadingModel, __void__setThreadingModel__ThreadingModel); + I_SimpleProperty(osg::OperationQueue *, UpdateOperations, + __osg_OperationQueue_P1__getUpdateOperations, + __void__setUpdateOperations__osg_OperationQueue_P1); + I_SimpleProperty(osgUtil::UpdateVisitor *, UpdateVisitor, + __osgUtil_UpdateVisitor_P1__getUpdateVisitor, + __void__setUpdateVisitor__osgUtil_UpdateVisitor_P1); I_ArrayProperty(osgViewer::View *, View, __osgViewer_View_P1__getView__unsigned, 0, diff --git a/src/osgWrappers/osgViewer/Viewer.cpp b/src/osgWrappers/osgViewer/Viewer.cpp index f0c7756d3..2671b272f 100644 --- a/src/osgWrappers/osgViewer/Viewer.cpp +++ b/src/osgWrappers/osgViewer/Viewer.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -138,6 +140,21 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) __BarrierPosition__getEndBarrierPosition, "Get the end barrier position. ", ""); + I_Method1(void, setEventVisitor, IN, osgGA::EventVisitor *, eventVisitor, + Properties::NON_VIRTUAL, + __void__setEventVisitor__osgGA_EventVisitor_P1, + "Set the EventVisitor. ", + ""); + I_Method0(osgGA::EventVisitor *, getEventVisitor, + Properties::NON_VIRTUAL, + __osgGA_EventVisitor_P1__getEventVisitor, + "Get the EventVisitor. ", + ""); + I_Method0(const osgGA::EventVisitor *, getEventVisitor, + Properties::NON_VIRTUAL, + __C5_osgGA_EventVisitor_P1__getEventVisitor, + "Get the const EventVisitor. ", + ""); I_Method1(void, setKeyEventSetsDone, IN, int, key, Properties::NON_VIRTUAL, __void__setKeyEventSetsDone__int, @@ -158,6 +175,46 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) __bool__getQuitEventSetsDone, "", "true if the viewer respond to the QUIT_APPLICATION-event "); + I_Method1(void, setUpdateVisitor, IN, osgUtil::UpdateVisitor *, updateVisitor, + Properties::NON_VIRTUAL, + __void__setUpdateVisitor__osgUtil_UpdateVisitor_P1, + "Set the UpdateVisitor. ", + ""); + I_Method0(osgUtil::UpdateVisitor *, getUpdateVisitor, + Properties::NON_VIRTUAL, + __osgUtil_UpdateVisitor_P1__getUpdateVisitor, + "Get the UpdateVisitor. ", + ""); + I_Method0(const osgUtil::UpdateVisitor *, getUpdateVisitor, + Properties::NON_VIRTUAL, + __C5_osgUtil_UpdateVisitor_P1__getUpdateVisitor, + "Get the const UpdateVisitor. ", + ""); + I_Method1(void, setUpdateOperations, IN, osg::OperationQueue *, operations, + Properties::NON_VIRTUAL, + __void__setUpdateOperations__osg_OperationQueue_P1, + "Set the Update OperationQueue. ", + ""); + I_Method0(osg::OperationQueue *, getUpdateOperations, + Properties::NON_VIRTUAL, + __osg_OperationQueue_P1__getUpdateOperations, + "Get the Update OperationQueue. ", + ""); + I_Method0(const osg::OperationQueue *, getUpdateOperations, + Properties::NON_VIRTUAL, + __C5_osg_OperationQueue_P1__getUpdateOperations, + "Get the const Update OperationQueue. ", + ""); + I_Method1(void, addUpdateOperation, IN, osg::Operation *, operation, + Properties::NON_VIRTUAL, + __void__addUpdateOperation__osg_Operation_P1, + "Add an update operation. ", + ""); + I_Method1(void, removeUpdateOperation, IN, osg::Operation *, operation, + Properties::NON_VIRTUAL, + __void__removeUpdateOperation__osg_Operation_P1, + "Remove an update operation. ", + ""); I_Method0(int, run, Properties::VIRTUAL, __int__run, @@ -296,6 +353,9 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) I_SimpleProperty(osgViewer::Viewer::BarrierPosition, EndBarrierPosition, __BarrierPosition__getEndBarrierPosition, __void__setEndBarrierPosition__BarrierPosition); + I_SimpleProperty(osgGA::EventVisitor *, EventVisitor, + __osgGA_EventVisitor_P1__getEventVisitor, + __void__setEventVisitor__osgGA_EventVisitor_P1); I_SimpleProperty(int, KeyEventSetsDone, __int__getKeyEventSetsDone, __void__setKeyEventSetsDone__int); @@ -317,6 +377,12 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) I_SimpleProperty(osgViewer::Viewer::ThreadingModel, ThreadingModel, __ThreadingModel__getThreadingModel, __void__setThreadingModel__ThreadingModel); + I_SimpleProperty(osg::OperationQueue *, UpdateOperations, + __osg_OperationQueue_P1__getUpdateOperations, + __void__setUpdateOperations__osg_OperationQueue_P1); + I_SimpleProperty(osgUtil::UpdateVisitor *, UpdateVisitor, + __osgUtil_UpdateVisitor_P1__getUpdateVisitor, + __void__setUpdateVisitor__osgUtil_UpdateVisitor_P1); I_SimpleProperty(bool, UseMainThreadForRenderingTraversals, __bool__getUseMainThreadForRenderingTraversals, __void__setUseMainThreadForRenderingTraversals__bool);