From 041a06b89daa8e79d8424c95fdc8672a3d1fcd0a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 21 Jul 2008 21:00:57 +0000 Subject: [PATCH] Further work on osg::ImageSequence/osgDB::ImagePager --- .../osgimagesequence/osgimagesequence.cpp | 29 ++----- include/osg/Image | 5 +- include/osg/ImageSequence | 35 ++++++--- include/osg/NodeVisitor | 25 ++++++ include/osgDB/ImagePager | 13 ++-- src/osg/ImageSequence.cpp | 78 ++++++++++++------- src/osgDB/ImagePager.cpp | 5 ++ src/osgViewer/CompositeViewer.cpp | 2 + src/osgViewer/Renderer.cpp | 5 ++ src/osgViewer/Viewer.cpp | 1 + src/osgWrappers/osg/Image.cpp | 6 +- src/osgWrappers/osg/NodeVisitor.cpp | 32 ++++++++ 12 files changed, 168 insertions(+), 68 deletions(-) diff --git a/examples/osgimagesequence/osgimagesequence.cpp b/examples/osgimagesequence/osgimagesequence.cpp index 82143f4cc..7d9986fca 100644 --- a/examples/osgimagesequence/osgimagesequence.cpp +++ b/examples/osgimagesequence/osgimagesequence.cpp @@ -31,24 +31,9 @@ #include // -// A simple demo demonstrating different texturing modes, -// including using of texture extensions. +// A simple demo demonstrating how to set on an animated texture using an osg::ImageSequence // -struct ImageUpdateCallback : public osg::StateAttribute::Callback -{ - /** do customized update code.*/ - virtual void operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv) - { - const osg::FrameStamp* fs = nv!=0 ? nv->getFrameStamp() : 0; - osg::Texture2D* texture2D = dynamic_cast(attr); - if (texture2D && texture2D->getImage() && fs) - { - texture2D->getImage()->update(fs); - } - } -}; - osg::StateSet* createState() { // read 4 2d images @@ -58,11 +43,11 @@ osg::StateSet* createState() osg::ref_ptr image_3 = osgDB::readImageFile("Images/skymap.jpg"); osg::ref_ptr imageSequence = new osg::ImageSequence; - imageSequence->addImage(image_0.get(), 0.25); - imageSequence->addImage(image_1.get(), 0.25); - imageSequence->addImage(image_2.get(), 0.25); - imageSequence->addImage(image_3.get(), 0.25); - + imageSequence->addImage(image_0.get()); + imageSequence->addImage(image_1.get()); + imageSequence->addImage(image_2.get()); + imageSequence->addImage(image_3.get()); + osg::Texture2D* texture = new osg::Texture2D; texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); @@ -71,7 +56,7 @@ osg::StateSet* createState() texture->setImage(imageSequence.get()); //texture->setTextureSize(512,512); - texture->setUpdateCallback(new ImageUpdateCallback); + texture->setUpdateCallback(new osg::ImageSequence::UpdateCallback); // create the StateSet to store the texture data osg::StateSet* stateset = new osg::StateSet; diff --git a/include/osg/Image b/include/osg/Image index 1375754e2..df3cf2bb2 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -53,6 +53,9 @@ namespace osg { +// forward declare +class NodeVisitor; + /** Image class for encapsulating the storage texture image data. */ class OSG_EXPORT Image : public Object { @@ -295,7 +298,7 @@ class OSG_EXPORT Image : public Object /** Get the const PixelBufferObject.*/ const PixelBufferObject* getPixelBufferObject() const { return _bufferObject.get(); } - virtual void update(const osg::FrameStamp* fs) {} + virtual void update(NodeVisitor* nv) {} protected : diff --git a/include/osg/ImageSequence b/include/osg/ImageSequence index 80fee41f3..a16fef3ab 100644 --- a/include/osg/ImageSequence +++ b/include/osg/ImageSequence @@ -16,6 +16,7 @@ #include #include +#include #include @@ -30,7 +31,7 @@ class OSG_EXPORT ImageSequence : public ImageStream ImageSequence(); /** Copy constructor using CopyOp to manage deep vs shallow copy. */ - ImageSequence(const ImageSequence& ImageSequence,const CopyOp& copyop=CopyOp::SHALLOW_COPY); + ImageSequence(const ImageSequence& ImageSequence, const CopyOp& copyop=CopyOp::SHALLOW_COPY); virtual Object* cloneType() const { return new ImageSequence(); } virtual Object* clone(const CopyOp& copyop) const { return new ImageSequence(*this,copyop); } @@ -47,18 +48,25 @@ class OSG_EXPORT ImageSequence : public ImageStream virtual void setTimeMultiplier(double tm) { _timeMultiplier = tm; } virtual double getTimeMultiplier() const { return _timeMultiplier; } + typedef std::list< osg::ref_ptr > Images; + typedef std::list< std::string > FileNames; - typedef std::pair, double> ImageDurationPair; - typedef std::pair FileNameDurationPair; + void setDuration(double duration) { _duration = duration; } + double getDuration() const { return _duration; } - typedef std::list ImageDurationSequence; - typedef std::list FileNameDurationSequence; + void setPruneOldImages(bool prune) { _pruneOldImages = prune; } + bool getPruneOldImages() const { return _pruneOldImages; } - void addImageFile(const std::string& fileName, double duration = 0.040); + void addImageFile(const std::string& fileName); - void addImage(osg::Image* image, double duration = 0.040); + void addImage(osg::Image* image); - virtual void update(const osg::FrameStamp* fs); + virtual void update(NodeVisitor* nv); + + struct OSG_EXPORT UpdateCallback : public osg::StateAttribute::Callback + { + virtual void operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv); + }; protected: @@ -70,10 +78,15 @@ class OSG_EXPORT ImageSequence : public ImageStream double _timeMultiplier; OpenThreads::Mutex _mutex; - FileNameDurationSequence _fileNameDurationSequence; - ImageDurationSequence _imageDuationSequence; + FileNames _fileNames; + + double _duration; + bool _pruneOldImages; + + double _imageHeadTime; + Images _images; - ImageDurationSequence::iterator _imageIterator; + Images::iterator _imageIterator; double _imageIteratorTime; diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index cd950d9d3..4b3bd75ce 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -284,6 +284,30 @@ class OSG_EXPORT NodeVisitor : public virtual Referenced const DatabaseRequestHandler* getDatabaseRequestHandler() const { return _databaseRequestHandler.get(); } + /** Callback for managing database paging, such as generated by PagedLOD nodes.*/ + class ImageRequestHandler : public osg::Referenced + { + public: + + ImageRequestHandler(): + Referenced(true) {} + + virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp, osg::ref_ptr& imageRequest) = 0; + + protected: + virtual ~ImageRequestHandler() {} + }; + + /** Set the handler for image requests.*/ + void setImageRequestHandler(ImageRequestHandler* handler) { _imageRequestHandler = handler; } + + /** Get the handler for image requests.*/ + ImageRequestHandler* getImageRequestHandler() { return _imageRequestHandler.get(); } + + /** Get the const handler for image requests.*/ + const ImageRequestHandler* getImageRequestHandler() const { return _imageRequestHandler.get(); } + + protected: @@ -301,6 +325,7 @@ class OSG_EXPORT NodeVisitor : public virtual Referenced ref_ptr _userData; ref_ptr _databaseRequestHandler; + ref_ptr _imageRequestHandler; }; diff --git a/include/osgDB/ImagePager b/include/osgDB/ImagePager index 2e59b6de9..4162342ee 100644 --- a/include/osgDB/ImagePager +++ b/include/osgDB/ImagePager @@ -15,6 +15,7 @@ #define OSGDB_IMAGEPAGER 1 #include +#include #include #include @@ -24,7 +25,7 @@ namespace osgDB { -class OSGDB_EXPORT ImagePager : public osg::Referenced +class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler { public: @@ -33,12 +34,12 @@ class OSGDB_EXPORT ImagePager : public osg::Referenced struct ImageRequest : public osg::Referenced { ImageRequest(): - osg::Referenced(true) {} + osg::Referenced(true), + _timeToMergeBy(0.0) {} + double _timeToMergeBy; std::string _fileName; osg::ref_ptr _loadOptions; - - osg::ref_ptr _objectToAttachTo; osg::ref_ptr _loadedImage; @@ -76,8 +77,10 @@ class OSGDB_EXPORT ImagePager : public osg::Referenced std::string _name; }; + virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp, osg::ref_ptr& imageRequest); + /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */ - bool requiresUpdateSceneGraph() const; + virtual bool requiresUpdateSceneGraph() const; /** Merge the changes to the scene graph. */ virtual void updateSceneGraph(double currentFrameTime); diff --git a/src/osg/ImageSequence.cpp b/src/osg/ImageSequence.cpp index f419554ac..15b3b5b6d 100644 --- a/src/osg/ImageSequence.cpp +++ b/src/osg/ImageSequence.cpp @@ -15,24 +15,44 @@ #include #include #include +#include +#include #include using namespace osg; +void ImageSequence::UpdateCallback::operator () (osg::StateAttribute* attr, osg::NodeVisitor* nv) +{ + const osg::FrameStamp* fs = nv!=0 ? nv->getFrameStamp() : 0; + osg::Texture2D* texture2D = dynamic_cast(attr); + if (texture2D && texture2D->getImage() && fs) + { + texture2D->getImage()->update(nv); + } +} + ImageSequence::ImageSequence() { _referenceTime = DBL_MAX; - _imageIteratorTime = DBL_MAX; _timeMultiplier = 1.0; - _imageIterator = _imageDuationSequence.end(); + + _duration = 1.0; + _pruneOldImages = false; + + _imageIteratorTime = DBL_MAX; + _imageIterator = _images.end(); } ImageSequence::ImageSequence(const ImageSequence& is,const CopyOp& copyop): osg::ImageStream(is,copyop), _referenceTime(is._referenceTime), - _timeMultiplier(is._timeMultiplier) + _timeMultiplier(is._timeMultiplier), + _duration(is._duration), + _pruneOldImages(is._pruneOldImages) { + _imageIteratorTime = DBL_MAX; + _imageIterator = _images.end(); } int ImageSequence::compare(const Image& rhs) const @@ -40,32 +60,29 @@ int ImageSequence::compare(const Image& rhs) const return ImageStream::compare(rhs); } -void ImageSequence::addImageFile(const std::string& fileName, double duration) +void ImageSequence::addImageFile(const std::string& fileName) { - if (duration<0.01) duration = 0.01; - OpenThreads::ScopedLock lock(_mutex); - _fileNameDurationSequence.push_back(FileNameDurationPair(fileName, duration)); + _fileNames.push_back(fileName); } -void ImageSequence::addImage(osg::Image* image, double duration) +void ImageSequence::addImage(osg::Image* image) { - if (duration<0.01) duration = 0.01; - OpenThreads::ScopedLock lock(_mutex); - _imageDuationSequence.push_back(ImageDurationPair(image, duration)); + _images.push_back(image); - if (_imageIterator==_imageDuationSequence.end()) + if (_imageIterator==_images.end()) { - _imageIterator = _imageDuationSequence.begin(); + _imageIterator = _images.begin(); _imageIteratorTime = _referenceTime; - setImageToChild(_imageIterator->first.get()); + setImageToChild(_imageIterator->get()); } - } void ImageSequence::setImageToChild(const osg::Image* image) { + // osg::notify(osg::NOTICE)<<"setImageToChild("<s(),image->t(),image->r(), image->getInternalTextureFormat(), image->getPixelFormat(),image->getDataType(), @@ -74,10 +91,14 @@ void ImageSequence::setImageToChild(const osg::Image* image) image->getPacking()); } -void ImageSequence::update(const osg::FrameStamp* fs) +void ImageSequence::update(osg::NodeVisitor* nv) { OpenThreads::ScopedLock lock(_mutex); - // osg::notify(osg::NOTICE)<<"ImageSequence::update("<getImageRequestHandler(); + const osg::FrameStamp* fs = nv->getFrameStamp(); + + // osg::notify(osg::NOTICE)<<"ImageSequence::update("<getSimulationTime() - _referenceTime)*_timeMultiplier; + double delta = _fileNames.empty() ? + _duration / _images.size() : + _duration / _fileNames.size(); + + Images::iterator previous_imageIterator = _imageIterator; // osg::notify(osg::NOTICE)<<"time = "<getSceneData()) { + _updateVisitor->setImageRequestHandler(scene->getImagePager()); + scene->getSceneData()->accept(*_updateVisitor); } diff --git a/src/osgViewer/Renderer.cpp b/src/osgViewer/Renderer.cpp index af125c526..758733ed2 100644 --- a/src/osgViewer/Renderer.cpp +++ b/src/osgViewer/Renderer.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -237,8 +238,12 @@ void Renderer::updateSceneView(osgUtil::SceneView* sceneView) } osgViewer::View* view = dynamic_cast(_camera->getView()); + osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0; sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager); + + osgDB::ImagePager* imagePager = view ? view->getImagePager() : 0; + sceneView->getCullVisitor()->setImageRequestHandler(imagePager); sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp()); diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index b953a53c6..6c832e708 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -882,6 +882,7 @@ void Viewer::updateTraversal() if (getSceneData()) { + _updateVisitor->setImageRequestHandler(_scene->getImagePager()); getSceneData()->accept(*_updateVisitor); } diff --git a/src/osgWrappers/osg/Image.cpp b/src/osgWrappers/osg/Image.cpp index 0b8a6724a..e4ae38d52 100644 --- a/src/osgWrappers/osg/Image.cpp +++ b/src/osgWrappers/osg/Image.cpp @@ -12,8 +12,8 @@ #include #include -#include #include +#include #include #include #include @@ -352,9 +352,9 @@ BEGIN_OBJECT_REFLECTOR(osg::Image) __C5_PixelBufferObject_P1__getPixelBufferObject, "Get the const PixelBufferObject. ", ""); - I_Method1(void, update, IN, const osg::FrameStamp *, fs, + I_Method1(void, update, IN, osg::NodeVisitor *, nv, Properties::VIRTUAL, - __void__update__C5_osg_FrameStamp_P1, + __void__update__NodeVisitor_P1, "", ""); I_StaticMethod1(bool, isPackedType, IN, GLenum, type, diff --git a/src/osgWrappers/osg/NodeVisitor.cpp b/src/osgWrappers/osg/NodeVisitor.cpp index a2b5677d4..88dc3e01c 100644 --- a/src/osgWrappers/osg/NodeVisitor.cpp +++ b/src/osgWrappers/osg/NodeVisitor.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -343,6 +344,21 @@ BEGIN_OBJECT_REFLECTOR(osg::NodeVisitor) __C5_DatabaseRequestHandler_P1__getDatabaseRequestHandler, "Get the const handler for database requests. ", ""); + I_Method1(void, setImageRequestHandler, IN, osg::NodeVisitor::ImageRequestHandler *, handler, + Properties::NON_VIRTUAL, + __void__setImageRequestHandler__ImageRequestHandler_P1, + "Set the handler for image requests. ", + ""); + I_Method0(osg::NodeVisitor::ImageRequestHandler *, getImageRequestHandler, + Properties::NON_VIRTUAL, + __ImageRequestHandler_P1__getImageRequestHandler, + "Get the handler for image requests. ", + ""); + I_Method0(const osg::NodeVisitor::ImageRequestHandler *, getImageRequestHandler, + Properties::NON_VIRTUAL, + __C5_ImageRequestHandler_P1__getImageRequestHandler, + "Get the const handler for image requests. ", + ""); I_SimpleProperty(osg::NodeVisitor::DatabaseRequestHandler *, DatabaseRequestHandler, __DatabaseRequestHandler_P1__getDatabaseRequestHandler, __void__setDatabaseRequestHandler__DatabaseRequestHandler_P1); @@ -352,6 +368,9 @@ BEGIN_OBJECT_REFLECTOR(osg::NodeVisitor) I_SimpleProperty(osg::FrameStamp *, FrameStamp, 0, __void__setFrameStamp__FrameStamp_P1); + I_SimpleProperty(osg::NodeVisitor::ImageRequestHandler *, ImageRequestHandler, + __ImageRequestHandler_P1__getImageRequestHandler, + __void__setImageRequestHandler__ImageRequestHandler_P1); I_SimpleProperty(osg::Node::NodeMask, NodeMaskOverride, __Node_NodeMask__getNodeMaskOverride, __void__setNodeMaskOverride__Node_NodeMask); @@ -391,6 +410,19 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::NodeVisitor::DatabaseRequestHandler) ""); END_REFLECTOR +BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::NodeVisitor::ImageRequestHandler) + I_DeclaringFile("osg/NodeVisitor"); + I_BaseType(osg::Referenced); + I_Constructor0(____ImageRequestHandler, + "", + ""); + I_Method5(void, requestNodeFile, IN, const std::string &, fileName, IN, osg::Object *, attachmentPoint, IN, double, timeToMergeBy, IN, const osg::FrameStamp *, framestamp, IN, osg::ref_ptr< osg::Referenced > &, imageRequest, + Properties::PURE_VIRTUAL, + __void__requestNodeFile__C5_std_string_R1__osg_Object_P1__double__C5_FrameStamp_P1__osg_ref_ptrT1_osg_Referenced__R1, + "", + ""); +END_REFLECTOR + BEGIN_VALUE_REFLECTOR(osg::ref_ptr< osg::Referenced >) I_DeclaringFile("osg/ref_ptr"); I_Constructor0(____ref_ptr,