From ff6b9099cf0aee5aa6f4949ece26d6959ce35b2f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 Dec 2003 16:40:26 +0000 Subject: [PATCH] Added gemetry of photo album and page turning animation. --- examples/osgphotoalbum/osgphotoalbum.cpp | 716 ++++++++++++++++------- 1 file changed, 510 insertions(+), 206 deletions(-) diff --git a/examples/osgphotoalbum/osgphotoalbum.cpp b/examples/osgphotoalbum/osgphotoalbum.cpp index 7cd33bccb..e74d4b94d 100644 --- a/examples/osgphotoalbum/osgphotoalbum.cpp +++ b/examples/osgphotoalbum/osgphotoalbum.cpp @@ -42,19 +42,19 @@ class ImageReaderWriter : public osgDB::ReaderWriter _fileName(), _resolutionX(256), _resolutionY(256), - _center(0.0f,0.0f,0.0f), + _center(0.625f,0.0f,0.0f), _maximumWidth(1.25f,0.0f,0.0f), _maximumHeight(0.0f,0.0f,1.0f), _numPointsAcross(10), _numPointsUp(10) {} - DataReference(const std::string& fileName, unsigned int res): + DataReference(const std::string& fileName, unsigned int res, float width, float height): _fileName(fileName), _resolutionX(res), _resolutionY(res), - _center(0.0f,0.0f,0.0f), - _maximumWidth(1.25f,0.0f,0.0f), - _maximumHeight(0.0f,0.0f,1.0f), + _center(width*0.5f,0.0f,height*0.5f), + _maximumWidth(width,0.0f,0.0f), + _maximumHeight(0.0f,0.0f,height), _numPointsAcross(10), _numPointsUp(10) {} @@ -81,13 +81,13 @@ class ImageReaderWriter : public osgDB::ReaderWriter typedef std::map DataReferenceMap; DataReferenceMap _dataReferences; - std::string insertReference(const std::string& fileName, unsigned int res) + std::string insertReference(const std::string& fileName, unsigned int res, float width, float height) { std::stringstream ostr; ostr<<"res_"<_sourcePixelWindow.windowWidth:1.0f; float t = options.valid()?options->_sourcePixelWindow.windowHeight:1.0f; - osg::Geode* geode = osg::createGeodeForImage(image,s,t); + float photoWidth = 0.0f; + float photoHeight = 0.0f; + float maxWidth = dr._maximumWidth.length(); + float maxHeight = dr._maximumHeight.length(); + + + if ((s/t)>(maxWidth/maxHeight)) + { + // photo wider than tall relative to the required pictures size. + // so need to clamp the width to the maximum width and then + // set the height to keep the original photo aspect ratio. + + photoWidth = maxWidth; + photoHeight = photoWidth*(t/s); + } + else + { + // photo tall than wide relative to the required pictures size. + // so need to clamp the height to the maximum height and then + // set the width to keep the original photo aspect ratio. + + photoHeight = maxHeight; + photoWidth = photoHeight*(s/t); + } + + osg::Vec3 halfWidthVector(dr._maximumWidth*(photoWidth*0.5f/maxWidth)); + osg::Vec3 halfHeightVector(dr._maximumHeight*(photoHeight*0.5f/maxHeight)); + + + // set up the texture. + osg::Texture2D* texture = new osg::Texture2D; + texture->setImage(image); + texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); + + // set up the drawstate. + osg::StateSet* dstate = new osg::StateSet; + dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); + + // set up the geoset. + osg::Geometry* geom = new osg::Geometry; + geom->setStateSet(dstate); + + osg::Vec3Array* coords = new osg::Vec3Array(4); + (*coords)[0] = dr._center - halfWidthVector + halfHeightVector; + (*coords)[1] = dr._center - halfWidthVector - halfHeightVector; + (*coords)[2] = dr._center + halfWidthVector - halfHeightVector; + (*coords)[3] = dr._center + halfWidthVector + halfHeightVector; + geom->setVertexArray(coords); + + osg::Vec2Array* tcoords = new osg::Vec2Array(4); + (*tcoords)[0].set(0.0f,1.0f); + (*tcoords)[1].set(0.0f,0.0f); + (*tcoords)[2].set(1.0f,0.0f); + (*tcoords)[3].set(1.0f,1.0f); + geom->setTexCoordArray(0,tcoords); + + osg::Vec4Array* colours = new osg::Vec4Array(1); + (*colours)[0].set(1.0f,1.0f,1.0,1.0f); + geom->setColorArray(colours); + geom->setColorBinding(osg::Geometry::BIND_OVERALL); + + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)); + + // set up the geode. + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geom); + return geode; } @@ -141,11 +209,407 @@ class ImageReaderWriter : public osgDB::ReaderWriter // reader/writer. osgDB::RegisterReaderWriterProxy g_ImageReaderWriter; +class Album; + +class Page : public osg::Transform +{ +public: -typedef std::vector FileList; + static Page* createPage(Album* album, unsigned int pageNo, const std::string& filename, float width, float height) + { + osg::ref_ptr page = new Page(album, pageNo, filename, width, height); + if (page.valid()) return page.release(); + else return 0; + } + + virtual void traverse(osg::NodeVisitor& nv); -class SlideEventHandler : public osgGA::GUIEventHandler, public osg::NodeCallback + void setRotation(float angle) + { + _rotation = angle; + _targetRotation = angle; + dirtyBound(); + } + + float getRotation() const { return _rotation; } + + void rotateTo(float angle, float timeToRotateBy) + { + _targetRotation = angle; + _targetTime = timeToRotateBy; + } + + bool rotating() const { return _targetRotation!=_rotation; } + + void setPageVisible(bool visible) { _switch->setSingleChildOn(visible?1:0); } + + osg::Switch* getSwitch() { return _switch.get(); } + const osg::Switch* getSwitch() const { return _switch.get(); } + +public: + + virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const + { + if (_referenceFrame==RELATIVE_TO_PARENTS) + { + matrix.preMult(getMatrix()); + } + else // absolute + { + matrix = getMatrix(); + } + return true; + } + + /** Get the transformation matrix which moves from world coords to local coords.*/ + virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const + { + const osg::Matrix& inverse = getInverseMatrix(); + + if (_referenceFrame==RELATIVE_TO_PARENTS) + { + matrix.postMult(inverse); + } + else // absolute + { + matrix = inverse; + } + return true; + } + + osg::Matrix getMatrix() const { return _pageOffset*osg::Matrix::rotate(-_rotation,0.0f,0.0f,1.0f); } + osg::Matrix getInverseMatrix() const { return osg::Matrix::inverse(getMatrix()); } + +protected: + + Page(Album* album, unsigned int pageNo, const std::string& filename, float width, float height); + + float _rotation; + osg::Matrix _pageOffset; + + float _targetRotation; + float _targetTime; + float _lastTimeTraverse; + + osg::ref_ptr _switch; + +}; + + +class Album : public osg::Referenced +{ +public: + + Album(osg::ArgumentParser& ap, float width, float height); + + osg::Group* getScene() { return _group.get(); } + + const osg::Group* getScene() const { return _group.get(); } + + osg::Matrix getPageOffset(unsigned int pageNo) const; + + bool nextPage(float timeToRotateBy) { return gotoPage(_currentPageNo+1,timeToRotateBy); } + + bool previousPage(float timeToRotateBy) { return _currentPageNo>=1?gotoPage(_currentPageNo-1,timeToRotateBy):false; } + + bool gotoPage(unsigned int pageNo, float timeToRotateBy); + + osg::StateSet* getBackgroundStateSet() { return _backgroundStateSet.get(); } + + void setVisibility(); + +protected: + + typedef std::vector< osg::ref_ptr > PageList; + + osg::ref_ptr _group; + PageList _pages; + + osg::ref_ptr _backgroundStateSet; + + unsigned int _currentPageNo; + float _radiusOfRings; + float _startAngleOfPages; + float _deltaAngleBetweenPages; + +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +Page::Page(Album* album, unsigned int pageNo, const std::string& filename, float width, float height) +{ + // set up transform parts. + _rotation = 0; + _targetRotation = 0; + _targetTime = 0; + _lastTimeTraverse = 0; + + _pageOffset = album->getPageOffset(pageNo); + + setNumChildrenRequiringUpdateTraversal(1); + + + // set up subgraph + osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal"); + if (!readerWriter) + { + std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"<addChild(non_visible_page); + { + // just an empty group for the time being... will need to create geometry soon. + osg::Geometry* geom = new osg::Geometry; + geom->setStateSet(album->getBackgroundStateSet()); + + osg::Vec3Array* coords = new osg::Vec3Array(4); + (*coords)[0].set(0.0f,0.0,height); + (*coords)[1].set(0.0f,0.0,0); + (*coords)[2].set(width,0.0,0); + (*coords)[3].set(width,0.0,height); + geom->setVertexArray(coords); + + osg::Vec3Array* normals = new osg::Vec3Array(1); + (*normals)[0].set(0.0f,-1.0f,0.0f); + geom->setNormalArray(normals); + geom->setNormalBinding(osg::Geometry::BIND_OVERALL); + + osg::Vec2Array* tcoords = new osg::Vec2Array(4); + (*tcoords)[0].set(0.0f,1.0f); + (*tcoords)[1].set(0.0f,0.0f); + (*tcoords)[2].set(1.0f,0.0f); + (*tcoords)[3].set(1.0f,1.0f); + geom->setTexCoordArray(0,tcoords); + + osg::Vec4Array* colours = new osg::Vec4Array(1); + (*colours)[0].set(1.0f,1.0f,1.0,1.0f); + geom->setColorArray(colours); + geom->setColorBinding(osg::Geometry::BIND_OVERALL); + + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4)); + + // set up the geode. + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geom); + + + non_visible_page->addChild(geode); + } + + + // set up visible page. + osg::Group* visible_page = new osg::Group; + _switch->addChild(visible_page); + + { + + + osg::Geometry* geom = new osg::Geometry; + geom->setStateSet(album->getBackgroundStateSet()); + + osg::Vec3Array* coords = new osg::Vec3Array(4); + (*coords)[0].set(0.0f,0.0,height); + (*coords)[1].set(0.0f,0.0,0); + (*coords)[2].set(width,0.0,0); + (*coords)[3].set(width,0.0,height); + geom->setVertexArray(coords); + + osg::Vec3Array* normals = new osg::Vec3Array(1); + (*normals)[0].set(0.0f,-1.0f,0.0f); + geom->setNormalArray(normals); + geom->setNormalBinding(osg::Geometry::BIND_OVERALL); + + osg::Vec2Array* tcoords = new osg::Vec2Array(4); + (*tcoords)[0].set(0.0f,1.0f); + (*tcoords)[1].set(0.0f,0.0f); + (*tcoords)[2].set(1.0f,0.0f); + (*tcoords)[3].set(1.0f,1.0f); + geom->setTexCoordArray(0,tcoords); + + osg::Vec4Array* colours = new osg::Vec4Array(1); + (*colours)[0].set(1.0f,1.0f,1.0,1.0f); + geom->setColorArray(colours); + geom->setColorBinding(osg::Geometry::BIND_OVERALL); + + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)); + + // set up the geode. + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geom); + + + visible_page->addChild(geode); + } + + { + float cut_off_distance = 8.0f; + float max_visible_distance = 300.0f; + + osg::Vec3 center(width*0.5f,0.0f,height*0.5f); + + osgText::Text* text = new osgText::Text; + text->setFont("fonts/arial.ttf"); + text->setPosition(center); + text->setCharacterSize(height/20.0f); + text->setAlignment(osgText::Text::CENTER_CENTER); + text->setAxisAlignment(osgText::Text::XZ_PLANE); + text->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f)); + text->setText(std::string("Loading ")+filename); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + + osg::PagedLOD* pagedlod = new osg::PagedLOD; + pagedlod->setCenter(center); + pagedlod->setRadius(1.6f); + pagedlod->setNumChildrenThatCannotBeExpired(2); + + pagedlod->setRange(0,max_visible_distance,1e7); + pagedlod->addChild(geode); + + pagedlod->setRange(1,cut_off_distance,max_visible_distance); + pagedlod->setFileName(1,rw->insertReference(filename,256,width,height)); + + pagedlod->setRange(2,0.0f,cut_off_distance); + pagedlod->setFileName(2,rw->insertReference(filename,1024,width,height)); + + visible_page->addChild(pagedlod); + } + + addChild(_switch.get()); +} + +void Page::traverse(osg::NodeVisitor& nv) +{ + // if app traversal update the frame count. + if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) + { + const osg::FrameStamp* framestamp = nv.getFrameStamp(); + if (framestamp) + { + double t = framestamp->getReferenceTime(); + + if (_rotation!=_targetRotation) + { + if (t>=_targetTime) _rotation = _targetRotation; + else _rotation += (_targetRotation-_rotation)*(t-_lastTimeTraverse)/(_targetTime-_lastTimeTraverse); + + dirtyBound(); + } + + _lastTimeTraverse = t; + + } + } + Transform::traverse(nv); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Album::Album(osg::ArgumentParser& arguments, float width, float height) +{ + + + typedef std::vector FileList; + FileList fileList; + + for(int pos=1;possetAttributeAndModes(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON); + + // load the images. + unsigned int i; + for(i=0;iaddChild(page); + } + } + + setVisibility(); + +} + +osg::Matrix Album::getPageOffset(unsigned int pageNo) const +{ + float angleForPage = _startAngleOfPages+_deltaAngleBetweenPages*(float)pageNo; + osg::Vec3 delta(_radiusOfRings*sinf(angleForPage),-_radiusOfRings*cosf(angleForPage),0.0f); + return osg::Matrix::translate(delta); +} + +bool Album::gotoPage(unsigned int pageNo, float timeToRotateBy) +{ + if (pageNo>=_pages.size()) return false; + + if (pageNo>_currentPageNo) + { + for(unsigned int i=_currentPageNo;irotateTo(osg::PI,timeToRotateBy); + } + _pages[pageNo]->setPageVisible(true); + _currentPageNo = pageNo; + + return true; + } + else if (pageNo<_currentPageNo) + { + for(unsigned int i=pageNo;i<_currentPageNo;++i) + { + _pages[i]->rotateTo(0,timeToRotateBy); + } + _pages[pageNo]->setPageVisible(true); + _currentPageNo = pageNo; + + return true; + } + + return false; +} + +void Album::setVisibility() +{ + for(unsigned int i=0;i<_pages.size();++i) + { + _pages[i]->setPageVisible(_pages[i]->rotating()); + } + + //_pages[0]->setPageVisible(true); + //if (_currentPageNo>=1) _pages[_currentPageNo-1]->setPageVisible(true); + _pages[_currentPageNo]->setPageVisible(true); + //if (_currentPageNo<_pages.size()-1) _pages[_currentPageNo+1]->setPageVisible(true); + //_pages[_pages.size()-1]->setPageVisible(true); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +class SlideEventHandler : public osgGA::GUIEventHandler { public: @@ -153,7 +617,7 @@ public: META_Object(osgStereImageApp,SlideEventHandler); - void set(osg::Switch* sw, float timePerSlide, bool autoSteppingActive); + void set(Album* album, float timePerSlide, bool autoSteppingActive); virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); } @@ -161,39 +625,30 @@ public: virtual void getUsage(osg::ApplicationUsage& usage) const; - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); - - void nextSlide(); - - void previousSlide(); - protected: ~SlideEventHandler() {} SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {} - osg::ref_ptr _switch; + osg::ref_ptr _album; bool _firstTraversal; - unsigned int _activeSlide; double _previousTime; double _timePerSlide; bool _autoSteppingActive; }; SlideEventHandler::SlideEventHandler(): - _switch(0), + _album(0), _firstTraversal(true), - _activeSlide(0), _previousTime(-1.0f), _timePerSlide(5.0), _autoSteppingActive(false) { } -void SlideEventHandler::set(osg::Switch* sw, float timePerSlide, bool autoSteppingActive) +void SlideEventHandler::set(Album* album, float timePerSlide, bool autoSteppingActive) { - _switch = sw; - _switch->setUpdateCallback(this); + _album = album; _timePerSlide = timePerSlide; _autoSteppingActive = autoSteppingActive; @@ -214,16 +669,36 @@ bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction } else if (ea.getKey()=='n') { - nextSlide(); + _album->nextPage(ea.time()+1.0f); return true; } else if (ea.getKey()=='p') { - previousSlide(); + _album->previousPage(ea.time()+1.0f); return true; } return false; } + case(osgGA::GUIEventAdapter::FRAME): + { + if (_autoSteppingActive) + { + if (_firstTraversal) + { + _firstTraversal = false; + _previousTime = ea.time(); + } + else if (ea.time()-_previousTime>_timePerSlide) + { + _previousTime = ea.time(); + + _album->nextPage(ea.time()+1.0f); + } + } + + _album->setVisibility(); + + } default: return false; @@ -238,170 +713,6 @@ void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const usage.addKeyboardMouseBinding("p","Move to previous image"); } -void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv) -{ - if (_autoSteppingActive && nv->getFrameStamp()) - { - double time = nv->getFrameStamp()->getReferenceTime(); - - if (_firstTraversal) - { - _firstTraversal = false; - _previousTime = time; - } - else if (time-_previousTime>_timePerSlide) - { - _previousTime = time; - - nextSlide(); - } - - } - - traverse(node,nv); -} - -void SlideEventHandler::nextSlide() -{ - if (_switch->getNumChildren()==0) return; - - ++_activeSlide; - if (_activeSlide>=_switch->getNumChildren()) _activeSlide = 0; - - _switch->setSingleChildOn(_activeSlide); -} - -void SlideEventHandler::previousSlide() -{ - if (_switch->getNumChildren()==0) return; - - if (_activeSlide==0) _activeSlide = _switch->getNumChildren()-1; - else --_activeSlide; - - _switch->setSingleChildOn(_activeSlide); -} - -// create a switch containing a set of child each containing a -// stereo image pair. -osg::Switch* createScene(const FileList& fileList, float height, float length) -{ - osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal"); - if (!readerWriter) - { - std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"< > NodeList; - NodeList nodes; - - // load the images. - unsigned int i; - for(i=0;isetFont("fonts/arial.ttf"); - text->setPosition(center); - text->setCharacterSize(0.1f); - text->setAlignment(osgText::Text::CENTER_CENTER); - text->setAxisAlignment(osgText::Text::XZ_PLANE); - text->setText(fileList[i]); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(text); - - osg::PagedLOD* pagedlod = new osg::PagedLOD; - pagedlod->setCenter(center); - pagedlod->setRadius(1.6f); - pagedlod->setNumChildrenThatCannotBeExpired(2); - - pagedlod->setRange(0,max_visible_distance,1e7); - pagedlod->addChild(geode); - - pagedlod->setRange(1,cut_off_distance,max_visible_distance); - pagedlod->setFileName(1,rw->insertReference(fileList[i],128)); - - pagedlod->setRange(2,0.0f,cut_off_distance); - pagedlod->setFileName(2,rw->insertReference(fileList[i],1024)); - - nodes.push_back(pagedlod); - } - - - if (nodes.empty()) return 0; - - osg::Group* front = new osg::Group; - sw->addChild(front); - - unsigned int nodes_across = (unsigned int)ceilf(sqrtf((float)nodes.size()*1.25)); - unsigned int nodes_down = (unsigned int)ceilf((float)nodes.size()/(float)nodes_across); - - float scale = 1.0f/(float)nodes_down; - - osg::Vec3 down_delta(0.0f,0.0f,-scale); - osg::Vec3 across_delta(scale*1.25,0.0f,0.0f); - osg::Vec3 leftMargin(-down_delta*((float)nodes_down*0.5f)-across_delta*((float)nodes_across*0.5f)); - - osg::Vec3 pos = leftMargin; - i=0; - - // front cover background - { - osg::Geometry* geometry = createTexturedQuadGeometry(osg::Vec3(-1.25f,0.0f,-1.0f),osg::Vec3(2.5f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,2.0f)); - osg::Geode* background = new osg::Geode; - background->addDrawable(geometry); - front->addChild(background); - - osg::StateSet* stateset = geometry->getOrCreateStateSet(); - stateset->setAttributeAndModes(new osg::PolygonOffset(2.0f,2.0f),osg::StateAttribute::ON); - stateset->setTextureAttributeAndModes(0,new osg::Texture2D(osgDB::readImageFile("lz.rgb")),osg::StateAttribute::ON); - } - - NodeList::iterator itr; - for(itr=nodes.begin(); - itr!=nodes.end(); - ++itr) - { - osg::MatrixTransform* mt = new osg::MatrixTransform; - mt->setMatrix(osg::Matrix::scale(scale*0.45f,scale*0.45f,scale*0.45f)*osg::Matrix::translate(pos)); - mt->addChild(itr->get()); - front->addChild(mt); - - i++; - if ((i%nodes_across)==0) - { - leftMargin += down_delta; - pos = leftMargin; - } - else pos += across_delta; - } - - - for(itr=nodes.begin(); - itr!=nodes.end(); - ++itr) - { - sw->addChild(itr->get()); - } - - if (sw->getNumChildren()>0) - { - // select first child. - sw->setSingleChildOn(0); - } - - return sw; -} - int main( int argc, char **argv ) { @@ -461,36 +772,29 @@ int main( int argc, char **argv ) return 1; } - // extract the filenames from the arguments list. - FileList fileList; - for(int pos=1;posgetNumberOfCameras(); i++ ) { Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i); Producer::RenderSurface* rs = cam->getRenderSurface(); - rs->useCursor(false); + //rs->useCursor(false); + fovx = cam->getLensHorizontalFov(); fovy = cam->getLensVerticalFov(); } float radius = 1.0f; + float width = 2*radius*tan(fovx*0.5f); float height = 2*radius*tan(fovy*0.5f); - float length = osg::PI*radius; // half a cylinder. + + osg::ref_ptr album = new Album(arguments,width,height); // creat the scene from the file list. - osg::ref_ptr rootNode = createScene(fileList,height,length); + osg::ref_ptr rootNode = album->getScene(); if (!rootNode) return 0; @@ -498,11 +802,11 @@ int main( int argc, char **argv ) //osgDB::writeNodeFile(*rootNode,"test.osg"); // set the scene to render - viewer.setSceneData(rootNode.get()); + viewer.setSceneData(album->getScene()); // set up the SlideEventHandler. - seh->set(rootNode.get(),timeDelayBetweenSlides,autoSteppingActive); + seh->set(album.get(),timeDelayBetweenSlides,autoSteppingActive); // create the windows and run the threads.