2003-12-28 06:17:41 +08:00
# include <osg/GLExtensions>
# include <osg/Node>
# include <osg/Geometry>
# include <osg/Notify>
# include <osg/MatrixTransform>
# include <osg/Texture2D>
# include <osg/Stencil>
# include <osg/ColorMask>
# include <osg/Depth>
# include <osg/Billboard>
# include <osg/Material>
# include <osg/Projection>
# include <osgGA/TrackballManipulator>
# include <osgGA/FlightManipulator>
# include <osgGA/DriveManipulator>
# include <osgUtil/SmoothingVisitor>
# include <osgDB/Registry>
# include <osgDB/ReadFile>
# include <osgProducer/Viewer>
2004-01-29 23:47:51 +08:00
using namespace osg ;
2005-07-20 00:30:55 +08:00
osg : : Node * createDistortionSubgraph ( osg : : Node * subgraph , const osg : : Vec4 & clearColour )
2003-12-28 06:17:41 +08:00
{
2005-07-09 22:35:35 +08:00
osg : : Group * distortionNode = new osg : : Group ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
unsigned int tex_width = 1024 ;
unsigned int tex_height = 1024 ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Texture2D * texture = new osg : : Texture2D ;
texture - > setTextureSize ( tex_width , tex_height ) ;
texture - > setInternalFormat ( GL_RGBA ) ;
texture - > setFilter ( osg : : Texture2D : : MIN_FILTER , osg : : Texture2D : : LINEAR ) ;
texture - > setFilter ( osg : : Texture2D : : MAG_FILTER , osg : : Texture2D : : LINEAR ) ;
// set up the render to texture camera.
2003-12-28 06:17:41 +08:00
{
2006-11-27 22:52:07 +08:00
osg : : Camera * camera = new osg : : Camera ;
2003-12-28 06:17:41 +08:00
2005-07-20 00:30:55 +08:00
// set clear the color and depth buffer
camera - > setClearColor ( clearColour ) ;
camera - > setClearMask ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2005-07-09 22:35:35 +08:00
// just inherit the main cameras view
camera - > setReferenceFrame ( osg : : Transform : : RELATIVE_RF ) ;
camera - > setProjectionMatrix ( osg : : Matrixd : : identity ( ) ) ;
camera - > setViewMatrix ( osg : : Matrixd : : identity ( ) ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// set viewport
camera - > setViewport ( 0 , 0 , tex_width , tex_height ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// set the camera to render before the main camera.
2006-11-27 22:52:07 +08:00
camera - > setRenderOrder ( osg : : Camera : : PRE_RENDER ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// tell the camera to use OpenGL frame buffer object where supported.
2006-11-27 22:52:07 +08:00
camera - > setRenderTargetImplementation ( osg : : Camera : : FRAME_BUFFER_OBJECT ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// attach the texture and use it as the color buffer.
2006-11-27 22:52:07 +08:00
camera - > attach ( osg : : Camera : : COLOR_BUFFER , texture ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// add subgraph to render
camera - > addChild ( subgraph ) ;
distortionNode - > addChild ( camera ) ;
}
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// set up the render to texture camera.
{
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// create the quad to visualize.
osg : : Geometry * polyGeom = new osg : : Geometry ( ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
polyGeom - > setSupportsDisplayList ( false ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Vec3 origin ( 0.0f , 0.0f , 0.0f ) ;
osg : : Vec3 xAxis ( 1.0f , 0.0f , 0.0f ) ;
osg : : Vec3 yAxis ( 0.0f , 1.0f , 0.0f ) ;
osg : : Vec3 zAxis ( 0.0f , 0.0f , 1.0f ) ;
float height = 1024.0f ;
float width = 1280.0f ;
int noSteps = 50 ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Vec3Array * vertices = new osg : : Vec3Array ;
osg : : Vec2Array * texcoords = new osg : : Vec2Array ;
osg : : Vec4Array * colors = new osg : : Vec4Array ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Vec3 bottom = origin ;
osg : : Vec3 dx = xAxis * ( width / ( ( float ) ( noSteps - 1 ) ) ) ;
osg : : Vec3 dy = yAxis * ( height / ( ( float ) ( noSteps - 1 ) ) ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Vec2 bottom_texcoord ( 0.0f , 0.0f ) ;
osg : : Vec2 dx_texcoord ( 1.0f / ( float ) ( noSteps - 1 ) , 0.0f ) ;
osg : : Vec2 dy_texcoord ( 0.0f , 1.0f / ( float ) ( noSteps - 1 ) ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Vec3 cursor = bottom ;
osg : : Vec2 texcoord = bottom_texcoord ;
int i , j ;
for ( i = 0 ; i < noSteps ; + + i )
2003-12-28 06:17:41 +08:00
{
2005-07-09 22:35:35 +08:00
osg : : Vec3 cursor = bottom + dy * ( float ) i ;
osg : : Vec2 texcoord = bottom_texcoord + dy_texcoord * ( float ) i ;
for ( j = 0 ; j < noSteps ; + + j )
{
vertices - > push_back ( cursor ) ;
texcoords - > push_back ( osg : : Vec2 ( ( sin ( texcoord . x ( ) * osg : : PI - osg : : PI * 0.5 ) + 1.0f ) * 0.5f , ( sin ( texcoord . y ( ) * osg : : PI - osg : : PI * 0.5 ) + 1.0f ) * 0.5f ) ) ;
colors - > push_back ( osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
cursor + = dx ;
texcoord + = dx_texcoord ;
}
2003-12-28 06:17:41 +08:00
}
2005-07-09 22:35:35 +08:00
// pass the created vertex array to the points geometry object.
polyGeom - > setVertexArray ( vertices ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
polyGeom - > setColorArray ( colors ) ;
polyGeom - > setColorBinding ( osg : : Geometry : : BIND_PER_VERTEX ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
polyGeom - > setTexCoordArray ( 0 , texcoords ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
for ( i = 0 ; i < noSteps - 1 ; + + i )
{
osg : : DrawElementsUShort * elements = new osg : : DrawElementsUShort ( osg : : PrimitiveSet : : QUAD_STRIP ) ;
for ( j = 0 ; j < noSteps ; + + j )
{
elements - > push_back ( j + ( i + 1 ) * noSteps ) ;
elements - > push_back ( j + ( i ) * noSteps ) ;
}
polyGeom - > addPrimitiveSet ( elements ) ;
}
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// new we need to add the texture to the Drawable, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg : : StateSet * stateset = polyGeom - > getOrCreateStateSet ( ) ;
stateset - > setTextureAttributeAndModes ( 0 , texture , osg : : StateAttribute : : ON ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : OFF ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
osg : : Geode * geode = new osg : : Geode ( ) ;
geode - > addDrawable ( polyGeom ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// set up the camera to render the textured quad
2006-11-27 22:52:07 +08:00
osg : : Camera * camera = new osg : : Camera ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// just inherit the main cameras view
camera - > setReferenceFrame ( osg : : Transform : : ABSOLUTE_RF ) ;
camera - > setViewMatrix ( osg : : Matrix : : identity ( ) ) ;
camera - > setProjectionMatrixAsOrtho2D ( 0 , 1280 , 0 , 1024 ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// set the camera to render before the main camera.
2006-11-27 22:52:07 +08:00
camera - > setRenderOrder ( osg : : Camera : : NESTED_RENDER ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// tell the camera to use OpenGL frame buffer object where supported.
2006-11-27 22:52:07 +08:00
camera - > setRenderTargetImplementation ( osg : : Camera : : FRAME_BUFFER_OBJECT ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// attach the texture and use it as the color buffer.
2006-11-27 22:52:07 +08:00
camera - > attach ( osg : : Camera : : COLOR_BUFFER , texture ) ;
2003-12-28 06:17:41 +08:00
2005-07-09 22:35:35 +08:00
// add subgraph to render
camera - > addChild ( geode ) ;
distortionNode - > addChild ( camera ) ;
2003-12-28 06:17:41 +08:00
}
2005-07-09 22:35:35 +08:00
return distortionNode ;
2003-12-28 06:17:41 +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 pre rendering of scene to a texture, and then apply this texture to geometry. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
// 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 ( ) ) ;
// if user request help write it out to cout.
if ( arguments . read ( " -h " ) | | arguments . read ( " --help " ) )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout ) ;
return 1 ;
}
// 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 ;
}
// load the nodes from the commandline arguments.
osg : : Node * loadedModel = osgDB : : readNodeFiles ( arguments ) ;
if ( ! loadedModel )
{
// write_usage(osg::notify(osg::NOTICE),argv[0]);
return 1 ;
}
2005-07-20 00:30:55 +08:00
osg : : Node * distortionNode = createDistortionSubgraph ( loadedModel , viewer . getClearColor ( ) ) ;
2005-07-09 22:35:35 +08:00
2003-12-28 06:17:41 +08:00
// add model to the viewer.
viewer . setSceneData ( distortionNode ) ;
// 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-12-28 06:17:41 +08:00
viewer . sync ( ) ;
return 0 ;
}