2007-06-12 22:20:16 +08:00
/* OpenSceneGraph example, osgphotoalbum.
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
2003-12-09 20:11:21 +08:00
*/
# include <osg/Notify>
# include <osg/MatrixTransform>
# include <osg/Switch>
# include <osg/PolygonOffset>
2003-12-20 22:25:18 +08:00
# include <osg/CullFace>
# include <osgUtil/Optimizer>
2003-12-24 07:55:06 +08:00
# include <osgDB/FileNameUtils>
2003-12-09 20:11:21 +08:00
# include <osgText/Text>
2007-01-10 21:52:22 +08:00
# include <osgViewer/Viewer>
2003-12-20 22:25:18 +08:00
2003-12-23 05:05:10 +08:00
# include "ImageReaderWriter.h"
2003-12-09 20:11:21 +08:00
2007-01-10 21:52:22 +08:00
# include <iostream>
2004-01-29 23:47:51 +08:00
using namespace osg ;
2003-12-23 05:05:10 +08:00
// now register with Registry to instantiate the above reader/writer,
// declaring in main so that the code to set up PagedLOD can get a handle
// to the ImageReaderWriter's
2003-12-09 20:11:21 +08:00
osgDB : : RegisterReaderWriterProxy < ImageReaderWriter > g_ImageReaderWriter ;
2003-12-16 00:40:26 +08:00
class Album ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
class Page : public osg : : Transform
2003-12-09 20:11:21 +08:00
{
public :
2003-12-20 22:25:18 +08:00
static Page * createPage ( Album * album , unsigned int pageNo , const std : : string & frontFileName , const std : : string & backFileName , float width , float height )
2003-12-16 00:40:26 +08:00
{
2003-12-20 22:25:18 +08:00
osg : : ref_ptr < Page > page = new Page ( album , pageNo , frontFileName , backFileName , width , height ) ;
2003-12-16 00:40:26 +08:00
if ( page . valid ( ) ) return page . release ( ) ;
else return 0 ;
}
virtual void traverse ( osg : : NodeVisitor & nv ) ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
void setRotation ( float angle )
{
_rotation = angle ;
_targetRotation = angle ;
dirtyBound ( ) ;
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
float getRotation ( ) const { return _rotation ; }
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
void rotateTo ( float angle , float timeToRotateBy )
{
_targetRotation = angle ;
_targetTime = timeToRotateBy ;
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
bool rotating ( ) const { return _targetRotation ! = _rotation ; }
2003-12-09 20:11:21 +08:00
2003-12-20 22:25:18 +08:00
void setPageVisible ( bool frontVisible , bool backVisible )
{
_switch - > setValue ( 0 , ! frontVisible & & ! backVisible ) ;
_switch - > setValue ( 1 , frontVisible ) ;
_switch - > setValue ( 2 , backVisible ) ;
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
osg : : Switch * getSwitch ( ) { return _switch . get ( ) ; }
const osg : : Switch * getSwitch ( ) const { return _switch . get ( ) ; }
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
public :
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
virtual bool computeLocalToWorldMatrix ( osg : : Matrix & matrix , osg : : NodeVisitor * ) const
2003-12-09 20:11:21 +08:00
{
2004-10-25 04:04:00 +08:00
if ( _referenceFrame = = RELATIVE_RF )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
matrix . preMult ( getMatrix ( ) ) ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
else // absolute
{
matrix = getMatrix ( ) ;
}
return true ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
/** Get the transformation matrix which moves from world coords to local coords.*/
virtual bool computeWorldToLocalMatrix ( osg : : Matrix & matrix , osg : : NodeVisitor * ) const
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
const osg : : Matrix & inverse = getInverseMatrix ( ) ;
2004-10-25 04:04:00 +08:00
if ( _referenceFrame = = RELATIVE_RF )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
matrix . postMult ( inverse ) ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
else // absolute
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
matrix = inverse ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
return true ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
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 ( ) ) ; }
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
protected :
2003-12-20 22:25:18 +08:00
Page ( Album * album , unsigned int pageNo , const std : : string & frontFileName , const std : : string & backFileName , float width , float height ) ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
float _rotation ;
osg : : Matrix _pageOffset ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
float _targetRotation ;
float _targetTime ;
float _lastTimeTraverse ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
osg : : ref_ptr < osg : : Switch > _switch ;
} ;
class Album : public osg : : Referenced
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
public :
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
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 < Page > > PageList ;
osg : : ref_ptr < osg : : Group > _group ;
PageList _pages ;
osg : : ref_ptr < osg : : StateSet > _backgroundStateSet ;
unsigned int _currentPageNo ;
float _radiusOfRings ;
float _startAngleOfPages ;
float _deltaAngleBetweenPages ;
} ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2003-12-20 22:25:18 +08:00
Page : : Page ( Album * album , unsigned int pageNo , const std : : string & frontFileName , const std : : string & backFileName , float width , float height )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
// set up transform parts.
_rotation = 0 ;
_targetRotation = 0 ;
_targetTime = 0 ;
_lastTimeTraverse = 0 ;
_pageOffset = album - > getPageOffset ( pageNo ) ;
setNumChildrenRequiringUpdateTraversal ( 1 ) ;
// set up subgraph
2003-12-09 20:11:21 +08:00
osgDB : : ReaderWriter * readerWriter = osgDB : : Registry : : instance ( ) - > getReaderWriterForExtension ( " gdal " ) ;
if ( ! readerWriter )
{
std : : cout < < " Error: GDAL plugin not available, cannot preceed with database creation " < < std : : endl ;
}
2003-12-16 00:40:26 +08:00
_switch = new osg : : Switch ;
2003-12-09 20:11:21 +08:00
ImageReaderWriter * rw = g_ImageReaderWriter . get ( ) ;
2003-12-16 00:40:26 +08:00
// set up non visible page.
osg : : Group * non_visible_page = new osg : : Group ;
_switch - > addChild ( non_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 ) ;
2003-12-20 22:25:18 +08:00
2003-12-16 00:40:26 +08:00
2003-12-20 22:25:18 +08:00
osg : : Vec3Array * normals = new osg : : Vec3Array ( 4 ) ;
( * normals ) [ 0 ] . set ( - 1.0f , 0.0f , 0.0f ) ;
( * normals ) [ 1 ] . set ( 0.0f , 0.0f , - 1.0f ) ;
( * normals ) [ 2 ] . set ( 1.0f , 0.0f , 0.0f ) ;
( * normals ) [ 3 ] . set ( 0.0f , 0.0f , 1.0f ) ;
2003-12-16 00:40:26 +08:00
geom - > setNormalArray ( normals ) ;
2003-12-20 22:25:18 +08:00
geom - > setNormalBinding ( osg : : Geometry : : BIND_PER_PRIMITIVE ) ;
2003-12-16 00:40:26 +08:00
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 ) ;
2003-12-20 22:25:18 +08:00
osg : : UByteArray * vindices = new osg : : UByteArray ( 8 ) ;
( * vindices ) [ 0 ] = 0 ;
( * vindices ) [ 1 ] = 1 ;
( * vindices ) [ 2 ] = 1 ;
( * vindices ) [ 3 ] = 2 ;
( * vindices ) [ 4 ] = 2 ;
( * vindices ) [ 5 ] = 3 ;
( * vindices ) [ 6 ] = 3 ;
( * vindices ) [ 7 ] = 0 ;
geom - > setVertexIndices ( vindices ) ;
geom - > setTexCoordIndices ( 0 , vindices ) ;
geom - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINES , 0 , 8 ) ) ;
2003-12-16 00:40:26 +08:00
// set up the geode.
osg : : Geode * geode = new osg : : Geode ;
geode - > addDrawable ( geom ) ;
non_visible_page - > addChild ( geode ) ;
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
// set up visible page.
2003-12-20 22:25:18 +08:00
osg : : Group * front_page = new osg : : Group ;
_switch - > addChild ( front_page ) ;
2003-12-16 00:40:26 +08:00
{
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 ) ;
2003-12-20 22:25:18 +08:00
front_page - > addChild ( geode ) ;
2003-12-16 00:40:26 +08:00
}
2003-12-09 20:11:21 +08:00
2003-12-20 22:25:18 +08:00
if ( ! frontFileName . empty ( ) )
2003-12-09 20:11:21 +08:00
{
float cut_off_distance = 8.0f ;
float max_visible_distance = 300.0f ;
2003-12-16 00:40:26 +08:00
osg : : Vec3 center ( width * 0.5f , 0.0f , height * 0.5f ) ;
2003-12-09 20:11:21 +08:00
osgText : : Text * text = new osgText : : Text ;
text - > setFont ( " fonts/arial.ttf " ) ;
text - > setPosition ( center ) ;
2003-12-16 00:40:26 +08:00
text - > setCharacterSize ( height / 20.0f ) ;
2003-12-09 20:11:21 +08:00
text - > setAlignment ( osgText : : Text : : CENTER_CENTER ) ;
text - > setAxisAlignment ( osgText : : Text : : XZ_PLANE ) ;
2003-12-16 00:40:26 +08:00
text - > setColor ( osg : : Vec4 ( 1.0f , 1.0f , 0.0f , 1.0f ) ) ;
2003-12-20 22:25:18 +08:00
text - > setText ( std : : string ( " Loading " ) + frontFileName ) ;
2003-12-09 20:11:21 +08:00
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 ) ;
2003-12-20 22:25:18 +08:00
pagedlod - > setFileName ( 1 , rw - > insertReference ( frontFileName , 256 , width , height , false ) ) ;
2003-12-09 20:11:21 +08:00
pagedlod - > setRange ( 2 , 0.0f , cut_off_distance ) ;
2003-12-20 22:25:18 +08:00
pagedlod - > setFileName ( 2 , rw - > insertReference ( frontFileName , 1024 , width , height , false ) ) ;
2003-12-16 00:40:26 +08:00
2003-12-20 22:25:18 +08:00
front_page - > addChild ( pagedlod ) ;
2003-12-16 00:40:26 +08:00
}
2003-12-20 22:25:18 +08:00
// set up back of page.
osg : : Group * back_page = new osg : : Group ;
_switch - > addChild ( back_page ) ;
{
osg : : Geometry * geom = new osg : : Geometry ;
geom - > setStateSet ( album - > getBackgroundStateSet ( ) ) ;
osg : : Vec3Array * coords = new osg : : Vec3Array ( 4 ) ;
( * coords ) [ 0 ] . set ( width , 0.0 , height ) ;
( * coords ) [ 1 ] . set ( width , 0.0 , 0 ) ;
( * coords ) [ 2 ] . set ( 0.0f , 0.0 , 0 ) ;
( * coords ) [ 3 ] . set ( 0.0f , 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 ( 1.0f , 1.0f ) ;
( * tcoords ) [ 1 ] . set ( 1.0f , 0.0f ) ;
( * tcoords ) [ 2 ] . set ( 0.0f , 0.0f ) ;
( * tcoords ) [ 3 ] . set ( 0.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 ) ;
2003-12-16 00:40:26 +08:00
2003-12-20 22:25:18 +08:00
back_page - > addChild ( geode ) ;
}
if ( ! backFileName . empty ( ) )
{
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 : : REVERSED_XZ_PLANE ) ;
text - > setColor ( osg : : Vec4 ( 1.0f , 1.0f , 0.0f , 1.0f ) ) ;
text - > setText ( std : : string ( " Loading " ) + backFileName ) ;
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 ( backFileName , 256 , width , height , true ) ) ;
pagedlod - > setRange ( 2 , 0.0f , cut_off_distance ) ;
pagedlod - > setFileName ( 2 , rw - > insertReference ( backFileName , 1024 , width , height , true ) ) ;
back_page - > addChild ( pagedlod ) ;
}
2003-12-16 00:40:26 +08:00
addChild ( _switch . get ( ) ) ;
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
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 )
{
2007-01-25 20:02:51 +08:00
double t = framestamp - > getSimulationTime ( ) ;
2003-12-16 00:40:26 +08:00
if ( _rotation ! = _targetRotation )
{
if ( t > = _targetTime ) _rotation = _targetRotation ;
else _rotation + = ( _targetRotation - _rotation ) * ( t - _lastTimeTraverse ) / ( _targetTime - _lastTimeTraverse ) ;
dirtyBound ( ) ;
}
_lastTimeTraverse = t ;
}
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
Transform : : traverse ( nv ) ;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Album : : Album ( osg : : ArgumentParser & arguments , float width , float height )
{
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
typedef std : : vector < std : : string > FileList ;
FileList fileList ;
for ( int pos = 1 ; pos < arguments . argc ( ) ; + + pos )
{
2003-12-24 07:55:06 +08:00
if ( arguments . isString ( pos ) )
{
std : : string filename ( arguments [ pos ] ) ;
if ( osgDB : : getLowerCaseFileExtension ( filename ) = = " album " )
{
PhotoArchive * photoArchive = PhotoArchive : : open ( filename ) ;
if ( photoArchive )
{
g_ImageReaderWriter . get ( ) - > addPhotoArchive ( photoArchive ) ;
photoArchive - > getImageFileNameList ( fileList ) ;
}
}
else
{
fileList . push_back ( arguments [ pos ] ) ;
}
}
2003-12-16 00:40:26 +08:00
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
_radiusOfRings = 0.02 ;
_startAngleOfPages = 0.0f ;
_deltaAngleBetweenPages = osg : : PI / ( float ) fileList . size ( ) ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
_group = new osg : : Group ;
2003-12-20 22:25:18 +08:00
_group - > getOrCreateStateSet ( ) - > setAttributeAndModes ( new osg : : CullFace , osg : : StateAttribute : : ON ) ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
_backgroundStateSet = new osg : : StateSet ;
_backgroundStateSet - > setAttributeAndModes ( new osg : : PolygonOffset ( 1.0f , 1.0f ) , osg : : StateAttribute : : ON ) ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
// load the images.
unsigned int i ;
2003-12-20 22:25:18 +08:00
for ( i = 0 ; i < fileList . size ( ) ; i + = 2 )
2003-12-16 00:40:26 +08:00
{
2003-12-20 22:25:18 +08:00
Page * page = i + 1 < fileList . size ( ) ?
Page : : createPage ( this , _pages . size ( ) , fileList [ i ] , fileList [ i + 1 ] , width , height ) :
Page : : createPage ( this , _pages . size ( ) , fileList [ i ] , " " , width , height ) ;
2003-12-16 00:40:26 +08:00
if ( page )
{
_pages . push_back ( page ) ;
_group - > addChild ( page ) ;
}
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
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 )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
for ( unsigned int i = _currentPageNo ; i < pageNo ; + + i )
{
_pages [ i ] - > rotateTo ( osg : : PI , timeToRotateBy ) ;
}
_currentPageNo = pageNo ;
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
return true ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
else if ( pageNo < _currentPageNo )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
for ( unsigned int i = pageNo ; i < _currentPageNo ; + + i )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
_pages [ i ] - > rotateTo ( 0 , timeToRotateBy ) ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
_currentPageNo = pageNo ;
return true ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
return false ;
}
void Album : : setVisibility ( )
{
for ( unsigned int i = 0 ; i < _pages . size ( ) ; + + i )
2003-12-09 20:11:21 +08:00
{
2003-12-20 22:25:18 +08:00
bool front_visible = _pages [ i ] - > rotating ( ) | |
( i > 0 ? _pages [ i - 1 ] - > rotating ( ) : false ) | |
i = = _currentPageNo | |
i = = 0 ;
bool back_visible = _pages [ i ] - > rotating ( ) | |
( ( i + 1 ) < _pages . size ( ) ? _pages [ i + 1 ] - > rotating ( ) : false ) | |
i = = _currentPageNo - 1 | |
i = = _pages . size ( ) - 1 ;
_pages [ i ] - > setPageVisible ( front_visible , back_visible ) ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class SlideEventHandler : public osgGA : : GUIEventHandler
{
public :
SlideEventHandler ( ) ;
META_Object ( osgStereImageApp , SlideEventHandler ) ;
void set ( Album * album , float timePerSlide , bool autoSteppingActive ) ;
virtual bool handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & ) ;
virtual void getUsage ( osg : : ApplicationUsage & usage ) const ;
protected :
~ SlideEventHandler ( ) { }
SlideEventHandler ( const SlideEventHandler & , const osg : : CopyOp & ) { }
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
osg : : ref_ptr < Album > _album ;
bool _firstTraversal ;
double _previousTime ;
double _timePerSlide ;
bool _autoSteppingActive ;
} ;
SlideEventHandler : : SlideEventHandler ( ) :
_album ( 0 ) ,
_firstTraversal ( true ) ,
_previousTime ( - 1.0f ) ,
_timePerSlide ( 5.0 ) ,
_autoSteppingActive ( false )
{
}
void SlideEventHandler : : set ( Album * album , float timePerSlide , bool autoSteppingActive )
{
_album = album ;
_timePerSlide = timePerSlide ;
_autoSteppingActive = autoSteppingActive ;
}
bool SlideEventHandler : : handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & )
{
switch ( ea . getEventType ( ) )
2003-12-09 20:11:21 +08:00
{
2003-12-16 00:40:26 +08:00
case ( osgGA : : GUIEventAdapter : : KEYDOWN ) :
{
if ( ea . getKey ( ) = = ' a ' )
{
_autoSteppingActive = ! _autoSteppingActive ;
2006-03-08 22:09:47 +08:00
_previousTime = ea . getTime ( ) ;
2003-12-16 00:40:26 +08:00
return true ;
}
else if ( ea . getKey ( ) = = ' n ' )
{
2006-03-08 22:09:47 +08:00
_album - > nextPage ( ea . getTime ( ) + 1.0f ) ;
2003-12-16 00:40:26 +08:00
return true ;
}
else if ( ea . getKey ( ) = = ' p ' )
{
2006-03-08 22:09:47 +08:00
_album - > previousPage ( ea . getTime ( ) + 1.0f ) ;
2003-12-16 00:40:26 +08:00
return true ;
}
return false ;
}
case ( osgGA : : GUIEventAdapter : : FRAME ) :
{
if ( _autoSteppingActive )
{
if ( _firstTraversal )
{
_firstTraversal = false ;
2006-03-08 22:09:47 +08:00
_previousTime = ea . getTime ( ) ;
2003-12-16 00:40:26 +08:00
}
2006-03-08 22:09:47 +08:00
else if ( ea . getTime ( ) - _previousTime > _timePerSlide )
2003-12-16 00:40:26 +08:00
{
2006-03-08 22:09:47 +08:00
_previousTime = ea . getTime ( ) ;
2003-12-16 00:40:26 +08:00
2006-03-08 22:09:47 +08:00
_album - > nextPage ( ea . getTime ( ) + 1.0f ) ;
2003-12-16 00:40:26 +08:00
}
}
_album - > setVisibility ( ) ;
}
default :
return false ;
2003-12-09 20:11:21 +08:00
}
2003-12-16 00:40:26 +08:00
}
2003-12-09 20:11:21 +08:00
2003-12-16 00:40:26 +08:00
void SlideEventHandler : : getUsage ( osg : : ApplicationUsage & usage ) const
{
usage . addKeyboardMouseBinding ( " Space " , " Reset the image position to center " ) ;
usage . addKeyboardMouseBinding ( " a " , " Toggle on/off the automatic advancement for image to image " ) ;
usage . addKeyboardMouseBinding ( " n " , " Advance to next image " ) ;
usage . addKeyboardMouseBinding ( " p " , " Move to previous image " ) ;
2003-12-09 20:11:21 +08:00
}
int main ( int argc , char * * argv )
{
// use an ArgumentParser object to manage the program arguments.
osg : : ArgumentParser arguments ( & argc , argv ) ;
// set up the usage document, in case we need to print out how to use this program.
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the example which demonstrates use node masks to create stereo images. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] image_file [image_file] " ) ;
2007-12-11 01:30:18 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -d <float> " , " Time delay in seconds between the display of successive image pairs when in auto advance mode. " ) ;
2003-12-09 20:11:21 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -a " , " Enter auto advance of image pairs on start up. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
2003-12-24 07:55:06 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --create <filename> " , " Create an photo archive of specified files " ) ;
2003-12-09 20:11:21 +08:00
// construct the viewer.
2007-10-05 17:03:51 +08:00
osgViewer : : Viewer viewer ( arguments ) ;
viewer . setThreadingModel ( osgViewer : : Viewer : : SingleThreaded ) ;
2003-12-09 20:11:21 +08:00
2007-12-11 01:30:18 +08:00
// register the handler to add keyboard and mouse handling.
2003-12-09 20:11:21 +08:00
SlideEventHandler * seh = new SlideEventHandler ( ) ;
2007-01-10 21:52:22 +08:00
viewer . addEventHandler ( seh ) ;
2003-12-09 20:11:21 +08:00
// read any time delay argument.
float timeDelayBetweenSlides = 5.0f ;
while ( arguments . read ( " -d " , timeDelayBetweenSlides ) ) { }
bool autoSteppingActive = false ;
while ( arguments . read ( " -a " ) ) autoSteppingActive = true ;
// if user request help write it out to cout.
if ( arguments . read ( " -h " ) | | arguments . read ( " --help " ) )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout ) ;
return 1 ;
}
2003-12-24 07:55:06 +08:00
std : : string archiveName ;
while ( arguments . read ( " --create " , archiveName ) ) { }
2003-12-09 20:11:21 +08:00
// any option left unread are converted into errors to write out later.
arguments . reportRemainingOptionsAsUnrecognized ( ) ;
2007-12-11 01:30:18 +08:00
// report any errors if they have occurred when parsing the program arguments.
2003-12-09 20:11:21 +08:00
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( std : : cout ) ;
return 1 ;
}
if ( arguments . argc ( ) < = 1 )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout , osg : : ApplicationUsage : : COMMAND_LINE_OPTION ) ;
return 1 ;
}
2003-12-24 07:55:06 +08:00
if ( ! archiveName . empty ( ) )
{
// archive name set to create
PhotoArchive : : FileNameList fileNameList ;
for ( int i = 1 ; i < arguments . argc ( ) ; + + i )
{
if ( arguments . isString ( i ) ) fileNameList . push_back ( std : : string ( arguments [ i ] ) ) ;
}
PhotoArchive : : buildArchive ( archiveName , fileNameList ) ;
return 0 ;
}
2003-12-09 20:11:21 +08:00
// now the windows have been realized we switch off the cursor to prevent it
// distracting the people seeing the stereo images.
2007-01-10 21:52:22 +08:00
double fovy , aspectRatio , zNear , zFar ;
viewer . getCamera ( ) - > getProjectionMatrixAsPerspective ( fovy , aspectRatio , zNear , zFar ) ;
2003-12-09 20:11:21 +08:00
2007-01-10 21:52:22 +08:00
fovy = osg : : DegreesToRadians ( fovy ) ;
double fovx = atan ( tan ( fovy * 0.5 ) * aspectRatio ) * 2.0 ;
2003-12-09 20:11:21 +08:00
float radius = 1.0f ;
2003-12-16 00:40:26 +08:00
float width = 2 * radius * tan ( fovx * 0.5f ) ;
2003-12-09 20:11:21 +08:00
float height = 2 * radius * tan ( fovy * 0.5f ) ;
2003-12-16 00:40:26 +08:00
osg : : ref_ptr < Album > album = new Album ( arguments , width , height ) ;
2003-12-09 20:11:21 +08:00
// creat the scene from the file list.
2003-12-16 00:40:26 +08:00
osg : : ref_ptr < osg : : Group > rootNode = album - > getScene ( ) ;
2003-12-09 20:11:21 +08:00
if ( ! rootNode ) return 0 ;
//osgDB::writeNodeFile(*rootNode,"test.osg");
// set the scene to render
2003-12-16 00:40:26 +08:00
viewer . setSceneData ( album - > getScene ( ) ) ;
2003-12-09 20:11:21 +08:00
// set up the SlideEventHandler.
2003-12-16 00:40:26 +08:00
seh - > set ( album . get ( ) , timeDelayBetweenSlides , autoSteppingActive ) ;
2003-12-09 20:11:21 +08:00
viewer . realize ( ) ;
2007-01-10 21:52:22 +08:00
// switch off the cursor
osgViewer : : Viewer : : Windows windows ;
viewer . getWindows ( windows ) ;
for ( osgViewer : : Viewer : : Windows : : iterator itr = windows . begin ( ) ;
itr ! = windows . end ( ) ;
+ + itr )
2003-12-09 20:11:21 +08:00
{
2007-01-10 21:52:22 +08:00
( * itr ) - > useCursor ( false ) ;
2003-12-09 20:11:21 +08:00
}
2006-08-03 03:55:03 +08:00
2007-01-10 21:52:22 +08:00
return viewer . run ( ) ;
2003-12-09 20:11:21 +08:00
}