2006-07-18 23:21:48 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2003-06-25 05:57:13 +08:00
*
* This application is open source and may be redistributed and / or modified
* freely and without restriction , both in commericial and non commericial applications ,
* as long as this copyright notice is maintained .
*
* This application is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
*/
# include <osgDB/ReadFile>
# include <osgUtil/Optimizer>
# include <osgProducer/Viewer>
# include <osg/Point>
2005-07-01 17:10:37 +08:00
# include <osg/BlendFunc>
# include <osg/Texture2D>
# include <osg/PointSprite>
2003-06-25 05:57:13 +08:00
class KeyboardEventHandler : public osgGA : : GUIEventHandler
{
public :
KeyboardEventHandler ( osg : : StateSet * stateset ) :
_stateset ( stateset )
{
_point = new osg : : Point ;
2005-06-27 22:28:29 +08:00
_point - > setDistanceAttenuation ( osg : : Vec3 ( 0.0 , 0.0000 , 0.05f ) ) ;
2003-06-25 05:57:13 +08:00
_stateset - > setAttribute ( _point . get ( ) ) ;
}
virtual bool handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & )
{
switch ( ea . getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : KEYDOWN ) :
{
if ( ea . getKey ( ) = = ' + ' | | ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Add )
{
changePointSize ( 1.0f ) ;
return true ;
}
else if ( ea . getKey ( ) = = ' - ' | | ea . getKey ( ) = = osgGA : : GUIEventAdapter : : KEY_KP_Subtract )
{
changePointSize ( - 1.0f ) ;
return true ;
}
2005-07-01 17:10:37 +08:00
else if ( ea . getKey ( ) = = ' < ' )
2005-06-27 22:28:29 +08:00
{
changePointAttenuation ( 1.1f ) ;
return true ;
}
2005-07-01 17:10:37 +08:00
else if ( ea . getKey ( ) = = ' > ' )
2005-06-27 22:28:29 +08:00
{
changePointAttenuation ( 1.0f / 1.1f ) ;
return true ;
}
2003-06-25 05:57:13 +08:00
break ;
}
default :
break ;
}
return false ;
}
float getPointSize ( ) const
{
return _point - > getSize ( ) ;
}
void setPointSize ( float psize )
{
if ( psize > 0.0 )
{
_point - > setSize ( psize ) ;
}
std : : cout < < " Point size " < < psize < < std : : endl ;
}
void changePointSize ( float delta )
{
setPointSize ( getPointSize ( ) + delta ) ;
}
2005-06-27 22:28:29 +08:00
void changePointAttenuation ( float scale )
{
_point - > setDistanceAttenuation ( _point - > getDistanceAttenuation ( ) * scale ) ;
}
2003-06-25 05:57:13 +08:00
osg : : ref_ptr < osg : : StateSet > _stateset ;
osg : : ref_ptr < osg : : Point > _point ;
} ;
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 ( ) - > setApplicationName ( arguments . getApplicationName ( ) ) ;
2005-11-16 06:07:54 +08:00
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " example provides an interactive viewer for visualising point clouds.. " ) ;
2003-06-25 05:57:13 +08:00
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
2005-07-01 17:10:37 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --sprites " , " Point sprites. " ) ;
2003-06-25 05:57:13 +08:00
// construct the viewer.
osgProducer : : Viewer viewer ( arguments ) ;
// set up the value with sensible default event handlers.
viewer . setUpViewer ( osgProducer : : Viewer : : STANDARD_SETTINGS ) ;
// get details on keyboard and mouse bindings used by the viewer.
viewer . getUsage ( * arguments . getApplicationUsage ( ) ) ;
2005-07-20 00:30:55 +08:00
bool shader = false ;
while ( arguments . read ( " --shader " ) ) shader = true ;
2003-06-25 05:57:13 +08:00
// if user request help write it out to cout.
if ( arguments . read ( " -h " ) | | arguments . read ( " --help " ) )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout ) ;
return 1 ;
}
2005-07-01 17:10:37 +08:00
bool usePointSprites = false ;
while ( arguments . read ( " --sprites " ) ) { usePointSprites = true ; } ;
2003-06-25 05:57:13 +08:00
// any option left unread are converted into errors to write out later.
arguments . reportRemainingOptionsAsUnrecognized ( ) ;
// report any errors if they have occured when parsing the program aguments.
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 ;
}
osg : : Timer timer ;
osg : : Timer_t start_tick = timer . tick ( ) ;
// read the scene from the list of file specified commandline args.
osg : : ref_ptr < osg : : Node > loadedModel = osgDB : : readNodeFiles ( arguments ) ;
// if no model has been successfully loaded report failure.
if ( ! loadedModel )
{
std : : cout < < arguments . getApplicationName ( ) < < " : No data loaded " < < std : : endl ;
return 1 ;
}
osg : : Timer_t end_tick = timer . tick ( ) ;
std : : cout < < " Time to load = " < < timer . delta_s ( start_tick , end_tick ) < < std : : endl ;
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil : : Optimizer optimizer ;
optimizer . optimize ( loadedModel . get ( ) ) ;
// set the scene to render
viewer . setSceneData ( loadedModel . get ( ) ) ;
2005-07-01 17:10:37 +08:00
if ( usePointSprites )
{
osg : : StateSet * stateset = loadedModel - > getOrCreateStateSet ( ) ;
/// Setup cool blending
osg : : BlendFunc * fn = new osg : : BlendFunc ( ) ;
stateset - > setAttributeAndModes ( fn , osg : : StateAttribute : : ON ) ;
/// Setup the point sprites
osg : : PointSprite * sprite = new osg : : PointSprite ( ) ;
stateset - > setTextureAttributeAndModes ( 0 , sprite , osg : : StateAttribute : : ON ) ;
/// The texture for the sprites
osg : : Texture2D * tex = new osg : : Texture2D ( ) ;
tex - > setImage ( osgDB : : readImageFile ( " Images/particle.rgb " ) ) ;
stateset - > setTextureAttributeAndModes ( 0 , tex , osg : : StateAttribute : : ON ) ;
}
2003-06-25 05:57:13 +08:00
// register the handler for modifying the point size
viewer . getEventHandlerList ( ) . push_front ( new KeyboardEventHandler ( viewer . getGlobalStateSet ( ) ) ) ;
2005-07-20 00:30:55 +08:00
if ( shader )
{
osg : : StateSet * stateset = loadedModel - > getOrCreateStateSet ( ) ;
///////////////////////////////////////////////////////////////////
// vertex shader using just Vec4 coefficients
char vertexShaderSource [ ] =
" void main(void) \n "
" { \n "
" \n "
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n "
" } \n " ;
2005-10-24 21:46:31 +08:00
osg : : Program * program = new osg : : Program ;
stateset - > setAttribute ( program ) ;
osg : : Shader * vertex_shader = new osg : : Shader ( osg : : Shader : : VERTEX , vertexShaderSource ) ;
program - > addShader ( vertex_shader ) ;
#if 0
2005-07-20 00:30:55 +08:00
//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource [ ] =
" void main(void) \n "
" { \n "
" gl_FragColor = gl_Color; \n "
" } \n " ;
2005-10-24 21:46:31 +08:00
osg : : Shader * fragment_shader = new osg : : Shader ( osg : : Shader : : FRAGMENT , fragmentShaderSource ) ;
program - > addShader ( fragment_shader ) ;
# endif
2005-07-20 00:30:55 +08:00
}
2003-06-25 05:57:13 +08:00
// create the windows and run the threads.
viewer . realize ( ) ;
while ( ! viewer . done ( ) )
{
// wait for all cull and draw threads to complete.
viewer . sync ( ) ;
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer . update ( ) ;
// fire off the cull and draw traversals of the scene.
viewer . frame ( ) ;
}
2006-08-03 03:55:03 +08:00
// wait for all cull and draw threads to complete.
viewer . sync ( ) ;
// run a clean up frame to delete all OpenGL objects.
viewer . cleanup_frame ( ) ;
// wait for all the clean up frame to complete.
2003-06-25 05:57:13 +08:00
viewer . sync ( ) ;
return 0 ;
}