Added ImageSequence to .ive plugin, added support for multiple ImageThreads in osgDB::ImagePager

This commit is contained in:
Robert Osfield
2008-07-25 13:45:07 +00:00
parent 0d1656055c
commit ec4d189b64
18 changed files with 293 additions and 65 deletions

View File

@@ -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<osg::Image> > FileNameImagePair;
typedef std::list< FileNameImagePair > FileNameImageList;
FileNameImageList _filesRequested;
};

View File

@@ -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> _readQueue;
osg::ref_ptr<ImageThread> _imageThread;
typedef std::vector< osg::ref_ptr<ImageThread> > ImageThreads;
ImageThreads _imageThreads;
osg::ref_ptr<RequestQueue> _completedQueue;
};

View File

@@ -103,10 +103,54 @@ void ImageSequence::addImageFile(const std::string& fileName)
void ImageSequence::addImage(osg::Image* image)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> 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 : "<<image->getFileName()<<std::endl;
itr->second = image;
return;
}
}
// osg::notify(osg::NOTICE)<<"image not expected : "<<image->getFileName()<<std::endl;
_images.push_back(image);
}
else
{
// osg::notify(osg::NOTICE)<<"merging image in order expected : "<<image->getFileName()<<std::endl;
_images.push_back(image);
_filesRequested.pop_front();
FileNameImageList::iterator itr;
for(itr = _filesRequested.begin();
itr != _filesRequested.end() && itr->second.valid();
++itr)
{
// osg::notify(osg::NOTICE)<<" merging previously loaded, but out of order file : "<<itr->first<<std::endl;
_images.push_back(itr->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<<std::endl;
osg::notify(osg::NOTICE)<<" need to preLoad = "<<*_fileNamesIterator<<std::endl;
//osg::notify(osg::NOTICE)<<" _fileNamesIteratorTime = "<<_fileNamesIteratorTime<<std::endl;
//osg::notify(osg::NOTICE)<<" need to preLoad = "<<*_fileNamesIterator<<std::endl;
++_fileNamesIterator;
if (previous_fileNamesIterator==_fileNamesIterator) break;
@@ -181,6 +225,7 @@ void ImageSequence::update(osg::NodeVisitor* nv)
_fileNamesIterator = _fileNames.begin();
}
_filesRequested.push_back(FileNameImagePair(*_fileNamesIterator,0));
irh->requestImageFile(*_fileNamesIterator, this, _fileNamesIteratorTime, fs);
}

View File

@@ -199,16 +199,14 @@ void ImagePager::ImageThread::run()
}
else
{
osg::Texture* texture = dynamic_cast<osg::Texture*>(imageRequest->_objectToAttachTo.get());
if (texture)
{
texture->setImage(0, image.get());
}
imageRequest->_loadedImage = image;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_pager->_completedQueue->_requestMutex);
_pager->_completedQueue->_requestList.push_back(imageRequest);
}
}
}
else
{
OpenThreads::Thread::YieldCurrentThread();
@@ -242,7 +240,10 @@ ImagePager::ImagePager():
_databasePagerThreadPaused = false;
_readQueue = new ReadQueue(this,"Image Queue");
_imageThread = new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread");
_completedQueue = new RequestQueue;
_imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 1"));
_imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 2"));
_imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 3"));
}
ImagePager::~ImagePager()
@@ -254,12 +255,22 @@ int ImagePager::cancel()
{
int result = 0;
_imageThread->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()"<<std::endl;
return false;
return !(_completedQueue->_requestList.empty());
}
void ImagePager::updateSceneGraph(double currentFrameTime)
{
//osg::notify(osg::NOTICE)<<"ImagePager::updateSceneGraph(double currentFrameTime)"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<osg::Texture*>(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."<<std::endl;
}
}
_completedQueue->_requestList.clear();
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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<osg::ImageSequence*>(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) {

View File

@@ -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);

View File

@@ -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 <osg/Notify>
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<osg::Object*>(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<osg::Object*>(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.");
}
}

View File

@@ -0,0 +1,15 @@
#ifndef IVE_IMAGESEQUENCE
#define IVE_IMAGESEQUENCE 1
#include <osg/ImageSequence>
#include "ReadWrite.h"
namespace ive{
class ImageSequence : public osg::ImageSequence, public ReadWrite {
public:
void write(DataOutputStream* out);
void read(DataInputStream* in);
};
}
#endif

View File

@@ -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

View File

@@ -38,6 +38,7 @@ namespace ive {
#define IVECAMERAVIEW 0x00000029
#define IVEAUTOTRANSFORM 0x00000030
#define IVEOCCLUSIONQUERYNODE 0x00000031
#define IVEIMAGESEQUENCE 0x00000032
// Node callbacks
#define IVENODECALLBACK 0x00000050

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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{

View File

@@ -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);
}