2003-03-15 04:35:45 +08:00
# include <osg/Geode>
# include <osg/ShapeDrawable>
# include <osg/Material>
# include <osg/Texture2D>
# include <osg/Geometry>
# include <osg/MatrixTransform>
# include <osg/PositionAttitudeTransform>
# include <osg/BlendFunc>
# include <osg/ClearNode>
# include <osgUtil/Tesselator>
# include <osgUtil/CullVisitor>
# include <osgText/Text>
# include <osgGA/TrackballManipulator>
# include <osgProducer/Viewer>
# include <osgDB/ReadFile>
static bool s_ProfessionalServices = false ;
class MyBillboardTransform : public osg : : PositionAttitudeTransform
{
public :
MyBillboardTransform ( ) :
_axis ( 0.0f , 0.0f , 1.0f ) ,
_normal ( 0.0f , - 1.0f , 0.0f )
{
}
bool computeLocalToWorldMatrix ( osg : : Matrix & matrix , osg : : NodeVisitor * nv ) const
{
osg : : Quat billboardRotation ;
osgUtil : : CullVisitor * cullvisitor = dynamic_cast < osgUtil : : CullVisitor * > ( nv ) ;
if ( cullvisitor )
{
osg : : Vec3 eyevector = cullvisitor - > getEyeLocal ( ) - _position ;
eyevector . normalize ( ) ;
osg : : Vec3 side = _axis ^ _normal ;
side . normalize ( ) ;
float angle = atan2 ( eyevector * _normal , eyevector * side ) ;
billboardRotation . makeRotate ( osg : : PI_2 - angle , _axis ) ;
}
matrix . preMult ( osg : : Matrix : : translate ( - _pivotPoint ) *
osg : : Matrix : : rotate ( _attitude ) *
osg : : Matrix : : rotate ( billboardRotation ) *
osg : : Matrix : : translate ( _position ) ) ;
return true ;
}
void setAxis ( const osg : : Vec3 & axis ) { _axis = axis ; }
void setNormal ( const osg : : Vec3 & normal ) { _normal = normal ; }
protected :
virtual ~ MyBillboardTransform ( ) { }
osg : : Vec3 _axis ;
osg : : Vec3 _normal ;
} ;
osg : : Geometry * createWing ( const osg : : Vec3 & left , const osg : : Vec3 & nose , const osg : : Vec3 & right , float chordRatio , const osg : : Vec4 & color )
{
osg : : Geometry * geom = new osg : : Geometry ;
osg : : Vec3 normal = ( nose - right ) ^ ( left - nose ) ;
normal . normalize ( ) ;
osg : : Vec3 left_to_right = right - left ;
osg : : Vec3 mid = ( right + left ) * 0.5f ;
osg : : Vec3 mid_to_nose = ( nose - mid ) * chordRatio * 0.5f ;
osg : : Vec3Array * vertices = new osg : : Vec3Array ;
vertices - > push_back ( left ) ;
//vertices->push_back(mid+mid_to_nose);
unsigned int noSteps = 40 ;
for ( unsigned int i = 1 ; i < noSteps ; + + i )
{
float ratio = ( float ) i / ( float ) noSteps ;
vertices - > push_back ( left + left_to_right * ratio + mid_to_nose * ( cosf ( ( ratio - 0.5f ) * osg : : PI * 2.0f ) + 1.0f ) ) ;
}
vertices - > push_back ( right ) ;
vertices - > push_back ( nose ) ;
geom - > setVertexArray ( vertices ) ;
osg : : Vec3Array * normals = new osg : : Vec3Array ;
normals - > push_back ( normal ) ;
geom - > setNormalArray ( normals ) ;
geom - > setNormalBinding ( osg : : Geometry : : BIND_OVERALL ) ;
osg : : Vec4Array * colors = new osg : : Vec4Array ;
colors - > push_back ( color ) ;
geom - > setColorArray ( colors ) ;
geom - > setColorBinding ( osg : : Geometry : : BIND_OVERALL ) ;
geom - > addPrimitiveSet ( new osg : : DrawArrays ( GL_POLYGON , 0 , vertices - > getNumElements ( ) ) ) ;
osgUtil : : Tesselator tesselator ;
tesselator . retesselatePolygons ( * geom ) ;
return geom ;
}
osg : : Node * createTextBelow ( const osg : : BoundingBox & bb )
{
osg : : Geode * geode = new osg : : Geode ( ) ;
std : : string font ( " fonts/arial.ttf " ) ;
osgText : : Text * text = new osgText : : Text ;
text - > setFont ( font ) ;
2003-04-30 19:40:17 +08:00
text - > setFontResolution ( 64 , 64 ) ;
2003-03-15 04:35:45 +08:00
text - > setAlignment ( osgText : : Text : : CENTER_CENTER ) ;
text - > setAxisAlignment ( osgText : : Text : : XZ_PLANE ) ;
text - > setPosition ( bb . center ( ) - osg : : Vec3 ( 0.0f , 0.0f , ( bb . zMax ( ) - bb . zMin ( ) ) ) ) ;
text - > setColor ( osg : : Vec4 ( 0.37f , 0.48f , 0.67f , 1.0f ) ) ;
text - > setText ( " OpenSceneGraph " ) ;
geode - > addDrawable ( text ) ;
return geode ;
}
osg : : Node * createTextLeft ( const osg : : BoundingBox & bb )
{
osg : : Geode * geode = new osg : : Geode ( ) ;
osg : : StateSet * stateset = geode - > getOrCreateStateSet ( ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : OFF ) ;
//std::string font("fonts/times.ttf");
std : : string font ( " fonts/arial.ttf " ) ;
osgText : : Text * text = new osgText : : Text ;
text - > setFont ( font ) ;
2003-04-30 19:40:17 +08:00
text - > setFontResolution ( 110 , 120 ) ;
2003-03-15 04:35:45 +08:00
text - > setAlignment ( osgText : : Text : : RIGHT_CENTER ) ;
text - > setAxisAlignment ( osgText : : Text : : XZ_PLANE ) ;
2003-04-19 17:09:46 +08:00
text - > setCharacterSize ( ( bb . zMax ( ) - bb . zMin ( ) ) * 1.0f ) ;
text - > setPosition ( bb . center ( ) - osg : : Vec3 ( ( bb . xMax ( ) - bb . xMin ( ) ) , - ( bb . yMax ( ) - bb . yMin ( ) ) * 0.5f , ( bb . zMax ( ) - bb . zMin ( ) ) * 0.1f ) ) ;
2003-03-15 04:35:45 +08:00
//text->setColor(osg::Vec4(0.37f,0.48f,0.67f,1.0f)); // Neil's orignal OSG colour
text - > setColor ( osg : : Vec4 ( 0.20f , 0.45f , 0.60f , 1.0f ) ) ; // OGL logo colour
text - > setText ( " OpenSceneGraph " ) ;
2006-06-27 20:05:40 +08:00
# if 1
text - > setBackdropType ( osgText : : Text : : OUTLINE ) ;
2006-07-18 20:24:04 +08:00
// text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
text - > setBackdropImplementation ( osgText : : Text : : POLYGON_OFFSET ) ;
// text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
// text->setBackdropImplementation(osgText::Text::DEPTH_RANGE);
// text->setBackdropImplementation(osgText::Text::STENCIL_BUFFER);
2006-06-27 20:05:40 +08:00
text - > setBackdropOffset ( 0.05f ) ;
text - > setBackdropColor ( osg : : Vec4 ( 0.0f , 0.0f , 0.5f , 1.0f ) ) ;
# endif
# if 1
text - > setColorGradientMode ( osgText : : Text : : OVERALL ) ;
osg : : Vec4 lightblue ( 0.30f , 0.6f , 0.90f , 1.0f ) ;
osg : : Vec4 blue ( 0.10f , 0.30f , 0.40f , 1.0f ) ;
text - > setColorGradientCorners ( lightblue , blue , blue , lightblue ) ;
# else
text - > setColorGradientMode ( osgText : : Text : : OVERALL ) ;
osg : : Vec4 light = osg : : Vec4 ( 0.0f , 1.0f , 1.0f , 1.0f ) ;
osg : : Vec4 dark = osg : : Vec4 ( 0.0f , 0.0f , 0.5f , 1.0f ) ;
text - > setColorGradientCorners ( light , dark , dark , light ) ;
// text->setColorGradientCorners(dark, light, light, dark);
# endif
2003-03-15 04:35:45 +08:00
geode - > addDrawable ( text ) ;
if ( s_ProfessionalServices )
{
//osgText::Text* subscript = new osgText::Text(new osgText::TextureFont(font,45));
osgText : : Text * subscript = new osgText : : Text ;
subscript - > setFont ( font ) ;
subscript - > setText ( " Professional Services " ) ;
subscript - > setAlignment ( osgText : : Text : : RIGHT_CENTER ) ;
subscript - > setAxisAlignment ( osgText : : Text : : XZ_PLANE ) ;
2003-04-19 17:09:46 +08:00
subscript - > setPosition ( bb . center ( ) - osg : : Vec3 ( ( bb . xMax ( ) - bb . xMin ( ) ) * 4.3f , - ( bb . yMax ( ) - bb . yMin ( ) ) * 0.5f , ( bb . zMax ( ) - bb . zMin ( ) ) * 0.6f ) ) ;
2003-03-15 04:35:45 +08:00
subscript - > setColor ( osg : : Vec4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ; // black
geode - > addDrawable ( subscript ) ;
}
return geode ;
}
2003-11-05 18:24:51 +08:00
osg : : Node * createGlobe ( const osg : : BoundingBox & bb , float ratio , const std : : string & filename )
2003-03-15 04:35:45 +08:00
{
2003-11-05 18:24:51 +08:00
osg : : MatrixTransform * xform = new osg : : MatrixTransform ;
2005-11-09 23:11:22 +08:00
xform - > setUpdateCallback ( new osg : : AnimationPathCallback ( bb . center ( ) , osg : : Vec3 ( 0.0f , 0.0f , 1.0f ) , osg : : inDegrees ( 10.0f ) ) ) ;
2003-03-15 04:35:45 +08:00
2006-07-14 22:04:54 +08:00
osg : : Node * bluemarble = filename . empty ( ) ? 0 : osgDB : : readNodeFile ( filename . c_str ( ) ) ;
2003-11-05 18:24:51 +08:00
if ( bluemarble )
2003-03-15 04:35:45 +08:00
{
2003-11-05 18:24:51 +08:00
const osg : : BoundingSphere & bs = bluemarble - > getBound ( ) ;
float s = 1.2 * bb . radius ( ) / bs . radius ( ) ;
osg : : MatrixTransform * positioner = new osg : : MatrixTransform ;
positioner - > setMatrix ( osg : : Matrix : : translate ( - bs . center ( ) ) * osg : : Matrix : : scale ( s , s , s ) * osg : : Matrix : : translate ( bb . center ( ) ) ) ;
positioner - > addChild ( bluemarble ) ;
2003-03-15 04:35:45 +08:00
2003-11-05 18:24:51 +08:00
xform - > addChild ( positioner ) ;
}
else
{
osg : : Geode * geode = new osg : : Geode ( ) ;
osg : : StateSet * stateset = geode - > getOrCreateStateSet ( ) ;
osg : : Image * image = osgDB : : readImageFile ( " Images/land_shallow_topo_2048.jpg " ) ;
if ( image )
{
2005-11-18 04:22:55 +08:00
osg : : Texture2D * texture = new osg : : Texture2D ;
texture - > setImage ( image ) ;
texture - > setMaxAnisotropy ( 8 ) ;
stateset - > setTextureAttributeAndModes ( 0 , texture , osg : : StateAttribute : : ON ) ;
2003-11-05 18:24:51 +08:00
}
osg : : Material * material = new osg : : Material ;
stateset - > setAttribute ( material ) ;
// the globe
geode - > addDrawable ( new osg : : ShapeDrawable ( new osg : : Sphere ( bb . center ( ) , bb . radius ( ) * ratio ) ) ) ;
xform - > addChild ( geode ) ;
}
2003-03-15 04:35:45 +08:00
return xform ;
}
osg : : Node * createBox ( const osg : : BoundingBox & bb , float chordRatio )
{
osg : : Geode * geode = new osg : : Geode ( ) ;
osg : : Vec4 white ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
// front faces.
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 6 ) , bb . corner ( 7 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 5 ) , bb . corner ( 4 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 5 ) , bb . corner ( 1 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 0 ) , bb . corner ( 4 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 5 ) , bb . corner ( 7 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 3 ) , bb . corner ( 1 ) , chordRatio , white ) ) ;
// back faces
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 0 ) , bb . corner ( 1 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 3 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 3 ) , bb . corner ( 7 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 6 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 6 ) , bb . corner ( 4 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 0 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
return geode ;
}
osg : : Node * createBoxNo5 ( const osg : : BoundingBox & bb , float chordRatio )
{
osg : : Geode * geode = new osg : : Geode ( ) ;
osg : : Vec4 white ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
// front faces.
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 6 ) , bb . corner ( 7 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 0 ) , bb . corner ( 4 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 3 ) , bb . corner ( 1 ) , chordRatio , white ) ) ;
// back faces
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 0 ) , bb . corner ( 1 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 3 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 3 ) , bb . corner ( 7 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 6 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 2 ) , bb . corner ( 6 ) , bb . corner ( 4 ) , chordRatio , white ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 0 ) , bb . corner ( 2 ) , chordRatio , white ) ) ;
return geode ;
}
osg : : Node * createBoxNo5No2 ( const osg : : BoundingBox & bb , float chordRatio )
{
osg : : Geode * geode = new osg : : Geode ( ) ;
// osg::Vec4 red(1.0f,0.0f,0.0f,1.0f);
// osg::Vec4 green(0.0f,1.0f,0.0f,1.0f);
// osg::Vec4 blue(0.0f,0.0f,1.0f,1.0f);
osg : : Vec4 red ( 1.0f , 0.12f , 0.06f , 1.0f ) ;
osg : : Vec4 green ( 0.21f , 0.48f , 0.03f , 1.0f ) ;
osg : : Vec4 blue ( 0.20f , 0.45f , 0.60f , 1.0f ) ;
// front faces.
geode - > addDrawable ( createWing ( bb . corner ( 4 ) , bb . corner ( 6 ) , bb . corner ( 7 ) , chordRatio , red ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 1 ) , bb . corner ( 0 ) , bb . corner ( 4 ) , chordRatio , green ) ) ;
geode - > addDrawable ( createWing ( bb . corner ( 7 ) , bb . corner ( 3 ) , bb . corner ( 1 ) , chordRatio , blue ) ) ;
return geode ;
}
osg : : Node * createBackdrop ( const osg : : Vec3 & corner , const osg : : Vec3 & top , const osg : : Vec3 & right )
{
osg : : Geometry * geom = new osg : : Geometry ;
osg : : Vec3 normal = ( corner - top ) ^ ( right - corner ) ;
normal . normalize ( ) ;
osg : : Vec3Array * vertices = new osg : : Vec3Array ;
vertices - > push_back ( top ) ;
vertices - > push_back ( corner ) ;
vertices - > push_back ( right ) ;
vertices - > push_back ( right + ( top - corner ) ) ;
geom - > setVertexArray ( vertices ) ;
osg : : Vec3Array * normals = new osg : : Vec3Array ;
normals - > push_back ( normal ) ;
geom - > setNormalArray ( normals ) ;
geom - > setNormalBinding ( osg : : Geometry : : BIND_OVERALL ) ;
osg : : Vec4Array * colors = new osg : : Vec4Array ;
colors - > push_back ( osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
geom - > setColorArray ( colors ) ;
geom - > setColorBinding ( osg : : Geometry : : BIND_OVERALL ) ;
geom - > addPrimitiveSet ( new osg : : DrawArrays ( GL_QUADS , 0 , vertices - > getNumElements ( ) ) ) ;
osg : : Geode * geode = new osg : : Geode ( ) ;
geode - > addDrawable ( geom ) ;
return geode ;
}
2003-11-05 18:24:51 +08:00
osg : : Node * createLogo ( const std : : string & filename )
2003-03-15 04:35:45 +08:00
{
osg : : BoundingBox bb ( osg : : Vec3 ( 0.0f , 0.0f , 0.0f ) , osg : : Vec3 ( 100.0f , 100.0f , 100.0f ) ) ;
float chordRatio = 0.5f ;
float sphereRatio = 0.6f ;
// create a group to hold the whole model.
osg : : Group * logo_group = new osg : : Group ;
osg : : Quat r1 , r2 ;
r1 . makeRotate ( - osg : : inDegrees ( 45.0f ) , 0.0f , 0.0f , 1.0f ) ;
r2 . makeRotate ( osg : : inDegrees ( 45.0f ) , 1.0f , 0.0f , 0.0f ) ;
MyBillboardTransform * xform = new MyBillboardTransform ;
xform - > setPivotPoint ( bb . center ( ) ) ;
xform - > setPosition ( bb . center ( ) ) ;
xform - > setAttitude ( r1 * r2 ) ;
// // create a transform to orientate the box and globe.
// osg::MatrixTransform* xform = new osg::MatrixTransform;
// xform->setDataVariance(osg::Object::STATIC);
// xform->setMatrix(osg::Matrix::translate(-bb.center())*
// osg::Matrix::rotate(-osg::inDegrees(45.0f),0.0f,0.0f,1.0f)*
// osg::Matrix::rotate(osg::inDegrees(45.0f),1.0f,0.0f,0.0f)*
// osg::Matrix::translate(bb.center()));
// add the box and globe to it.
//xform->addChild(createBox(bb,chordRatio));
//xform->addChild(createBoxNo5(bb,chordRatio));
xform - > addChild ( createBoxNo5No2 ( bb , chordRatio ) ) ;
// add the transform to the group.
logo_group - > addChild ( xform ) ;
2003-11-05 18:24:51 +08:00
logo_group - > addChild ( createGlobe ( bb , sphereRatio , filename ) ) ;
2003-03-15 04:35:45 +08:00
// add the text to the group.
//group->addChild(createTextBelow(bb));
logo_group - > addChild ( createTextLeft ( bb ) ) ;
// create the backdrop to render the shadow to.
osg : : Vec3 corner ( - 900.0f , 150.0f , - 100.0f ) ;
osg : : Vec3 top ( 0.0f , 0.0f , 300.0f ) ; top + = corner ;
osg : : Vec3 right ( 1100.0f , 0.0f , 0.0f ) ; right + = corner ;
// osg::Group* backdrop = new osg::Group;
// backdrop->addChild(createBackdrop(corner,top,right));
osg : : ClearNode * backdrop = new osg : : ClearNode ;
backdrop - > setClearColor ( osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
//osg::Vec3 lightPosition(-500.0f,-2500.0f,500.0f);
//osg::Node* scene = createShadowedScene(logo_group,backdrop,lightPosition,0.0f,0);
osg : : Group * scene = new osg : : Group ;
osg : : StateSet * stateset = scene - > getOrCreateStateSet ( ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : OVERRIDE | osg : : StateAttribute : : OFF ) ;
scene - > addChild ( logo_group ) ;
scene - > addChild ( backdrop ) ;
return scene ;
}
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.
2003-04-09 19:44:32 +08:00
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the example which demonstrates both text, animation and billboard via custom transform to create the OpenSceneGraph logo.. " ) ;
2003-11-05 18:24:51 +08:00
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] [filename] ... " ) ;
2003-03-15 04:35:45 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " ps " , " Render the Professional Services logo " ) ;
// 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 ;
}
while ( arguments . read ( " ps " ) ) s_ProfessionalServices = true ;
// 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 ;
}
2003-04-07 05:32:44 +08:00
2003-11-05 18:24:51 +08:00
osg : : Node * node = 0 ;
if ( arguments . argc ( ) > 1 ) createLogo ( arguments [ 1 ] ) ;
2006-07-14 22:04:54 +08:00
else node = createLogo ( " " ) ;
2003-03-15 04:35:45 +08:00
// add model to viewer.
viewer . setSceneData ( node ) ;
// create the windows and run the threads.
2003-04-08 23:18:45 +08:00
viewer . realize ( ) ;
2003-03-15 04:35:45 +08:00
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 ( ) ;
}
2003-03-25 18:05:09 +08:00
// wait for all cull and draw threads to complete before exit.
viewer . sync ( ) ;
2003-03-15 04:35:45 +08:00
return 0 ;
}