diff --git a/include/osg/ImageSequence b/include/osg/ImageSequence index d6b40e955..b5e5d9a8a 100644 --- a/include/osg/ImageSequence +++ b/include/osg/ImageSequence @@ -105,6 +105,11 @@ class OSG_EXPORT ImageSequence : public ImageStream Images _images; Images::iterator _imageIterator; double _imageIteratorTime; + + typedef std::pair< std::string, osg::ref_ptr > FileNameImagePair; + typedef std::list< FileNameImagePair > FileNameImageList; + + FileNameImageList _filesRequested; }; diff --git a/include/osgDB/ImagePager b/include/osgDB/ImagePager index 4ca11f5aa..280d550eb 100644 --- a/include/osgDB/ImagePager +++ b/include/osgDB/ImagePager @@ -67,6 +67,14 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler std::string _name; }; + + ImageThread* getImageThread(unsigned int i) { return _imageThreads[i].get(); } + + const ImageThread* getImageThread(unsigned int i) const { return _imageThreads[i].get(); } + + unsigned int getNumImageThreads() const { return _imageThreads.size(); } + + virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp); /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */ @@ -144,8 +152,11 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler bool _databasePagerThreadPaused; osg::ref_ptr _readQueue; - osg::ref_ptr _imageThread; + typedef std::vector< osg::ref_ptr > ImageThreads; + ImageThreads _imageThreads; + + osg::ref_ptr _completedQueue; }; diff --git a/src/osg/ImageSequence.cpp b/src/osg/ImageSequence.cpp index e1b1158bf..a625d7cd9 100644 --- a/src/osg/ImageSequence.cpp +++ b/src/osg/ImageSequence.cpp @@ -103,10 +103,54 @@ void ImageSequence::addImageFile(const std::string& fileName) void ImageSequence::addImage(osg::Image* image) { OpenThreads::ScopedLock lock(_mutex); - _images.push_back(image); - computeTimePerImage(); - if (_imageIterator==_images.end()) + if (!_filesRequested.empty()) + { + // follows is a mechanism that ensures that requested images + // get merged in the correct time order. + if (_filesRequested.front().first != image->getFileName()) + { + for(FileNameImageList::iterator itr = _filesRequested.begin(); + itr != _filesRequested.end(); + ++itr) + { + if (itr->first == image->getFileName()) + { + osg::notify(osg::NOTICE)<<"inserting image into waiting stake : "<getFileName()<second = image; + return; + } + } + // osg::notify(osg::NOTICE)<<"image not expected : "<getFileName()<getFileName()<second.valid(); + ++itr) + { + // osg::notify(osg::NOTICE)<<" merging previously loaded, but out of order file : "<first<second); + } + + _filesRequested.erase(_filesRequested.begin(), itr); + } + } + else + { + _images.push_back(image); + } + + computeTimePerImage(); + + if (data()==0) { _imageIterator = _images.begin(); _imageIteratorTime = _referenceTime; @@ -169,8 +213,8 @@ void ImageSequence::update(osg::NodeVisitor* nv) while(preLoadTime > (_fileNamesIteratorTime + _timePerImage)) { _fileNamesIteratorTime += _timePerImage; - osg::notify(osg::NOTICE)<<" _fileNamesIteratorTime = "<<_fileNamesIteratorTime<setDone(true); + for(ImageThreads::iterator itr = _imageThreads.begin(); + itr != _imageThreads.end(); + ++itr) + { + (*itr)->setDone(true); + } // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation. _readQueue->release(); - _imageThread->cancel(); + for(ImageThreads::iterator itr = _imageThreads.begin(); + itr != _imageThreads.end(); + ++itr) + { + (*itr)->cancel(); + } _done = true; _startThreadCalled = false; @@ -289,7 +300,13 @@ void ImagePager::requestImageFile(const std::string& fileName,osg::Object* attac { _startThreadCalled = true; _done = false; - _imageThread->startThread(); + + for(ImageThreads::iterator itr = _imageThreads.begin(); + itr != _imageThreads.end(); + ++itr) + { + (*itr)->startThread(); + } } } @@ -298,11 +315,29 @@ void ImagePager::requestImageFile(const std::string& fileName,osg::Object* attac bool ImagePager::requiresUpdateSceneGraph() const { //osg::notify(osg::NOTICE)<<"ImagePager::requiresUpdateSceneGraph()"<_requestList.empty()); } void ImagePager::updateSceneGraph(double currentFrameTime) { - //osg::notify(osg::NOTICE)<<"ImagePager::updateSceneGraph(double currentFrameTime)"< lock(_completedQueue->_requestMutex); + + for(RequestQueue::RequestList::iterator itr = _completedQueue->_requestList.begin(); + itr != _completedQueue->_requestList.end(); + ++itr) + { + ImageRequest* imageRequest = itr->get(); + osg::Texture* texture = dynamic_cast(imageRequest->_objectToAttachTo.get()); + if (texture) + { + texture->setImage(0, imageRequest->_loadedImage.get()); + } + else + { + osg::notify(osg::NOTICE)<<"ImagePager::updateSceneGraph() : error, image request attachment type not handled yet."<_requestList.clear(); } diff --git a/src/osgPlugins/ive/CMakeLists.txt b/src/osgPlugins/ive/CMakeLists.txt index 8d80c0e15..3735c5bf3 100644 --- a/src/osgPlugins/ive/CMakeLists.txt +++ b/src/osgPlugins/ive/CMakeLists.txt @@ -46,6 +46,7 @@ SET(TARGET_SRC Group.cpp HeightFieldLayer.cpp Image.cpp + ImageSequence.cpp ImageLayer.cpp Impostor.cpp Layer.cpp @@ -153,6 +154,7 @@ SET(TARGET_H Group.h HeightFieldLayer.h Image.h + ImageSequence.h ImageLayer.h Impostor.h IveVersion.h diff --git a/src/osgPlugins/ive/DataInputStream.cpp b/src/osgPlugins/ive/DataInputStream.cpp index 9fbdc6aac..7ea90555d 100644 --- a/src/osgPlugins/ive/DataInputStream.cpp +++ b/src/osgPlugins/ive/DataInputStream.cpp @@ -50,6 +50,7 @@ #include "Viewport.h" #include "Scissor.h" #include "Image.h" +#include "ImageSequence.h" #include "PointSprite.h" #include "Multisample.h" #include "Fog.h" @@ -956,6 +957,31 @@ osg::Image* DataInputStream::readImage(std::string filename) return image; } +osg::Image* DataInputStream::readImage() +{ + if ( getVersion() >= VERSION_0029 ) + { + int id = peekInt(); + if(id == IVEIMAGESEQUENCE) + { + osg::ImageSequence* image = new osg::ImageSequence(); + ((ive::ImageSequence*)image)->read(this); + return image; + } + else + { + readInt(); + IncludeImageMode includeImg = (IncludeImageMode)readChar(); + return readImage(includeImg); + } + } + else + { + IncludeImageMode includeImg = (IncludeImageMode)readChar(); + return readImage(includeImg); + } +} + osg::Image* DataInputStream::readImage(IncludeImageMode mode) { switch(mode) { diff --git a/src/osgPlugins/ive/DataInputStream.h b/src/osgPlugins/ive/DataInputStream.h index 3133d7f33..bb8015300 100644 --- a/src/osgPlugins/ive/DataInputStream.h +++ b/src/osgPlugins/ive/DataInputStream.h @@ -91,6 +91,7 @@ public: osg::Image* readImage(std::string s); osg::Image* readImage(IncludeImageMode mode); + osg::Image* readImage(); osg::StateSet* readStateSet(); osg::StateAttribute* readStateAttribute(); osg::Uniform* readUniform(); diff --git a/src/osgPlugins/ive/DataOutputStream.cpp b/src/osgPlugins/ive/DataOutputStream.cpp index ea04e2c77..61814c10f 100644 --- a/src/osgPlugins/ive/DataOutputStream.cpp +++ b/src/osgPlugins/ive/DataOutputStream.cpp @@ -53,6 +53,7 @@ #include "Viewport.h" #include "Scissor.h" #include "Image.h" +#include "ImageSequence.h" #include "PointSprite.h" #include "Multisample.h" #include "Fog.h" @@ -1094,6 +1095,29 @@ void DataOutputStream::writeNode(const osg::Node* node) } } +void DataOutputStream::writeImage(osg::Image *image) +{ + if ( getVersion() >= VERSION_0029) + { + osg::ImageSequence* is = dynamic_cast(image); + if (is) + { + ((ive::ImageSequence*)(is))->write(this); + } + else + { + writeInt(IVEIMAGE); + writeChar(getIncludeImageMode()); + writeImage(getIncludeImageMode(),image); + } + } + else + { + writeChar(getIncludeImageMode()); + writeImage(getIncludeImageMode(),image); + } +} + void DataOutputStream::writeImage(IncludeImageMode mode, osg::Image *image) { switch(mode) { diff --git a/src/osgPlugins/ive/DataOutputStream.h b/src/osgPlugins/ive/DataOutputStream.h index e795f8c6b..08139a259 100644 --- a/src/osgPlugins/ive/DataOutputStream.h +++ b/src/osgPlugins/ive/DataOutputStream.h @@ -94,6 +94,7 @@ public: void writeShape(const osg::Shape* sa); void writeNode(const osg::Node* sa); void writeImage(IncludeImageMode mode, osg::Image *image); + void writeImage(osg::Image *image); void writeLayer(const osgTerrain::Layer* layer); void writeLocator(const osgTerrain::Locator* locator); diff --git a/src/osgPlugins/ive/ImageSequence.cpp b/src/osgPlugins/ive/ImageSequence.cpp new file mode 100644 index 000000000..88088749d --- /dev/null +++ b/src/osgPlugins/ive/ImageSequence.cpp @@ -0,0 +1,58 @@ +/********************************************************************** + * + * FILE: Image.cpp + * + * DESCRIPTION: Read/Write osg::Image in binary format to disk. + * + * CREATED BY: Auto generated by iveGenerated + * and later modified by Rune Schmidt Jensen. + * + * HISTORY: Created 20.3.2003 + * + * Copyright 2003 VR-C + **********************************************************************/ + +#include "Exception.h" +#include "ImageSequence.h" +#include "Object.h" + +#include + +using namespace ive; + +void ImageSequence::write(DataOutputStream* out) +{ + // Write ImageSequence's identification. + out->writeInt(IVEIMAGESEQUENCE); + // If the osg class is inherited by any other class we should also write this to file. + osg::Object* obj = dynamic_cast(this); + if(obj){ + ((ive::Object*)(obj))->write(out); + } + else + throw Exception("ImageSequence::write(): Could not cast this osg::ImageSequence to an osg::Object."); + // Write ImageSequence's properties. + +} + +void ImageSequence::read(DataInputStream* in) +{ + // Peek ImageSequence's identification. + int id = in->peekInt(); + if(id == IVEIMAGESEQUENCE){ + // Read ImageSequence's identification. + id = in->readInt(); + // If the osg class is inherited by any other class we should also read this from file. + osg::Object* obj = dynamic_cast(this); + if(obj){ + ((ive::Object*)(obj))->read(in); + } + else + throw Exception("ImageSequence::read(): Could not cast this osg::ImageSequence to an osg::Object."); + // Read ImageSequence's properties. + + } + else{ + throw Exception("ImageSequence::read(): Expected ImageSequence identification."); + } +} diff --git a/src/osgPlugins/ive/ImageSequence.h b/src/osgPlugins/ive/ImageSequence.h new file mode 100644 index 000000000..0f6311995 --- /dev/null +++ b/src/osgPlugins/ive/ImageSequence.h @@ -0,0 +1,15 @@ +#ifndef IVE_IMAGESEQUENCE +#define IVE_IMAGESEQUENCE 1 + +#include +#include "ReadWrite.h" + +namespace ive{ +class ImageSequence : public osg::ImageSequence, public ReadWrite { +public: + void write(DataOutputStream* out); + void read(DataInputStream* in); +}; +} + +#endif diff --git a/src/osgPlugins/ive/IveVersion.h b/src/osgPlugins/ive/IveVersion.h index 805779b0a..dbcf6b321 100644 --- a/src/osgPlugins/ive/IveVersion.h +++ b/src/osgPlugins/ive/IveVersion.h @@ -37,8 +37,9 @@ #define VERSION_0026 26 #define VERSION_0027 27 #define VERSION_0028 28 +#define VERSION_0029 29 -#define VERSION VERSION_0028 +#define VERSION VERSION_0029 /* The BYTE_SEX tag is used to check the endian of the IVE file being read in. The IVE format diff --git a/src/osgPlugins/ive/ReadWrite.h b/src/osgPlugins/ive/ReadWrite.h index 2c026fa4b..c93db9fbe 100644 --- a/src/osgPlugins/ive/ReadWrite.h +++ b/src/osgPlugins/ive/ReadWrite.h @@ -38,6 +38,7 @@ namespace ive { #define IVECAMERAVIEW 0x00000029 #define IVEAUTOTRANSFORM 0x00000030 #define IVEOCCLUSIONQUERYNODE 0x00000031 +#define IVEIMAGESEQUENCE 0x00000032 // Node callbacks #define IVENODECALLBACK 0x00000050 diff --git a/src/osgPlugins/ive/Texture1D.cpp b/src/osgPlugins/ive/Texture1D.cpp index a3d271c9f..25e50f5cb 100644 --- a/src/osgPlugins/ive/Texture1D.cpp +++ b/src/osgPlugins/ive/Texture1D.cpp @@ -33,10 +33,7 @@ void Texture1D::write(DataOutputStream* out){ // Write image. // Should we include images date in stream - IncludeImageMode includeImg = out->getIncludeImageMode(); - out->writeChar(includeImg); - - out->writeImage(includeImg,getImage()); + out->writeImage(getImage()); } void Texture1D::read(DataInputStream* in){ @@ -55,9 +52,7 @@ void Texture1D::read(DataInputStream* in){ // Read image. // Should we read image data from stream - IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); - - osg::Image *image = in->readImage(includeImg); + osg::Image *image = in->readImage(); if(image) { setImage(image); } diff --git a/src/osgPlugins/ive/Texture2D.cpp b/src/osgPlugins/ive/Texture2D.cpp index aeefda23a..3742d83f3 100644 --- a/src/osgPlugins/ive/Texture2D.cpp +++ b/src/osgPlugins/ive/Texture2D.cpp @@ -33,10 +33,7 @@ void Texture2D::write(DataOutputStream* out){ // Write image. // Should we include images date in stream - IncludeImageMode includeImg = out->getIncludeImageMode(); - out->writeChar(includeImg); - - out->writeImage(includeImg,getImage()); + out->writeImage(getImage()); } void Texture2D::read(DataInputStream* in){ @@ -54,10 +51,7 @@ void Texture2D::read(DataInputStream* in){ throw Exception("Texture2D::read(): Could not cast this osg::Texture2D to an osg::Texture."); // Read image. - // Should we read image data from stream - IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); - - osg::Image *image = in->readImage(includeImg); + osg::Image *image = in->readImage(); if(image) { setImage(image); } diff --git a/src/osgPlugins/ive/Texture3D.cpp b/src/osgPlugins/ive/Texture3D.cpp index dc968beaa..418188577 100644 --- a/src/osgPlugins/ive/Texture3D.cpp +++ b/src/osgPlugins/ive/Texture3D.cpp @@ -33,10 +33,7 @@ void Texture3D::write(DataOutputStream* out){ // Write image. // Should we include images date in stream - IncludeImageMode includeImg = out->getIncludeImageMode(); - out->writeChar(includeImg); - - out->writeImage(includeImg,getImage()); + out->writeImage(getImage()); } void Texture3D::read(DataInputStream* in){ @@ -55,9 +52,7 @@ void Texture3D::read(DataInputStream* in){ // Read image. // Should we read image data from stream - IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); - - osg::Image *image = in->readImage(includeImg); + osg::Image *image = in->readImage(); if(image) { setImage(image); } diff --git a/src/osgPlugins/ive/TextureCubeMap.cpp b/src/osgPlugins/ive/TextureCubeMap.cpp index e2bb71aba..435c3c759 100644 --- a/src/osgPlugins/ive/TextureCubeMap.cpp +++ b/src/osgPlugins/ive/TextureCubeMap.cpp @@ -38,16 +38,28 @@ void TextureCubeMap::write(DataOutputStream* out){ // Write number of mipmap levels out->writeInt(getNumMipmapLevels()); - // Should we include images date in stream - IncludeImageMode includeImg = out->getIncludeImageMode(); - out->writeChar(includeImg); + if (out->getVersion() >= VERSION_0029) + { + out->writeImage(getImage(osg::TextureCubeMap::POSITIVE_X)); + out->writeImage(getImage(osg::TextureCubeMap::NEGATIVE_X)); + out->writeImage(getImage(osg::TextureCubeMap::POSITIVE_Y)); + out->writeImage(getImage(osg::TextureCubeMap::NEGATIVE_Y)); + out->writeImage(getImage(osg::TextureCubeMap::POSITIVE_Z)); + out->writeImage(getImage(osg::TextureCubeMap::NEGATIVE_Z)); + } + else + { + // Should we include images date in stream + IncludeImageMode includeImg = out->getIncludeImageMode(); + out->writeChar(includeImg); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_X)); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_X)); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_Y)); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_Y)); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_Z)); - out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_Z)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_X)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_X)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_Y)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_Y)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::POSITIVE_Z)); + out->writeImage(includeImg,getImage(osg::TextureCubeMap::NEGATIVE_Z)); + } } void TextureCubeMap::read(DataInputStream* in) @@ -74,15 +86,27 @@ void TextureCubeMap::read(DataInputStream* in) // Read number of mipmap levels setNumMipmapLevels((unsigned int)in->readInt()); - // Should we read image data from stream - IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); + if (in->getVersion() >= VERSION_0029) + { + setImage(osg::TextureCubeMap::POSITIVE_X,in->readImage()); + setImage(osg::TextureCubeMap::NEGATIVE_X,in->readImage()); + setImage(osg::TextureCubeMap::POSITIVE_Y,in->readImage()); + setImage(osg::TextureCubeMap::NEGATIVE_Y,in->readImage()); + setImage(osg::TextureCubeMap::POSITIVE_Z,in->readImage()); + setImage(osg::TextureCubeMap::NEGATIVE_Z,in->readImage()); + } + else + { + // Should we read image data from stream + IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); - setImage(osg::TextureCubeMap::POSITIVE_X,in->readImage(includeImg)); - setImage(osg::TextureCubeMap::NEGATIVE_X,in->readImage(includeImg)); - setImage(osg::TextureCubeMap::POSITIVE_Y,in->readImage(includeImg)); - setImage(osg::TextureCubeMap::NEGATIVE_Y,in->readImage(includeImg)); - setImage(osg::TextureCubeMap::POSITIVE_Z,in->readImage(includeImg)); - setImage(osg::TextureCubeMap::NEGATIVE_Z,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::POSITIVE_X,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::NEGATIVE_X,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::POSITIVE_Y,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::NEGATIVE_Y,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::POSITIVE_Z,in->readImage(includeImg)); + setImage(osg::TextureCubeMap::NEGATIVE_Z,in->readImage(includeImg)); + } } else{ diff --git a/src/osgPlugins/ive/TextureRectangle.cpp b/src/osgPlugins/ive/TextureRectangle.cpp index 4a9fb2e0f..3056d2c48 100644 --- a/src/osgPlugins/ive/TextureRectangle.cpp +++ b/src/osgPlugins/ive/TextureRectangle.cpp @@ -33,10 +33,7 @@ void TextureRectangle::write(DataOutputStream* out){ // Write image. // Should we include images date in stream - IncludeImageMode includeImg = out->getIncludeImageMode(); - out->writeChar(includeImg); - - out->writeImage(includeImg,getImage()); + out->writeImage(getImage()); } void TextureRectangle::read(DataInputStream* in){ @@ -55,9 +52,7 @@ void TextureRectangle::read(DataInputStream* in){ // Read image. // Should we read image data from stream - IncludeImageMode includeImg = (IncludeImageMode)in->readChar(); - - osg::Image *image = in->readImage(includeImg); + osg::Image *image = in->readImage(); if(image) { setImage(image); }