#include #include #include #include #include #include #include #include #include #include #include // include the call which creates the shadowed subgraph. #include "CreateShadowedScene.h" // for the grid data.. #include "../osghangglide/terrain_coords.h" osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) { // set up the animation path osg::AnimationPath* animationPath = new osg::AnimationPath; animationPath->setLoopMode(osg::AnimationPath::LOOP); int numSamples = 40; float yaw = 0.0f; float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f); float roll = osg::inDegrees(30.0f); double time=0.0f; double time_delta = looptime/(double)numSamples; for(int i=0;iinsert(time,osg::AnimationPath::ControlPoint(position,rotation)); yaw += yaw_delta; time += time_delta; } return animationPath; } osg::Node* createBase(const osg::Vec3& center,float radius) { osg::Geode* geode = new osg::Geode; // set up the texture of the base. osg::StateSet* stateset = new osg::StateSet(); osg::Image* image = osgDB::readImageFile("Images/lz.rgb"); if (image) { osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } geode->setStateSet( stateset ); osg::HeightField* grid = new osg::HeightField; grid->allocate(38,39); grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f)); grid->setXInterval(radius*2.0f/(float)(38-1)); grid->setYInterval(radius*2.0f/(float)(39-1)); float minHeight = FLT_MAX; float maxHeight = -FLT_MAX; unsigned int r; for(r=0;r<39;++r) { for(unsigned int c=0;c<38;++c) { float h = vertex[r+c*39][2]; if (h>maxHeight) maxHeight=h; if (hsetHeight(c,r,(h+hieghtOffset)*hieghtScale); } } geode->addDrawable(new osg::ShapeDrawable(grid)); osg::Group* group = new osg::Group; group->addChild(geode); return group; } osg::Node* createMovingModel(const osg::Vec3& center, float radius) { float animationLength = 10.0f; osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); osg::Group* model = new osg::Group; osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); if (cessna) { const osg::BoundingSphere& bs = cessna->getBound(); float size = radius/bs.radius()*0.3f; osg::MatrixTransform* positioned = new osg::MatrixTransform; positioned->setDataVariance(osg::Object::STATIC); positioned->setMatrix(osg::Matrix::translate(-bs.center())* osg::Matrix::scale(size,size,size)* osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,2.0f)); positioned->addChild(cessna); osg::MatrixTransform* xform = new osg::MatrixTransform; xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0)); xform->addChild(positioned); model->addChild(xform); } return model; } osg::Node* createModel() { osg::Vec3 center(0.0f,0.0f,0.0f); float radius = 100.0f; osg::Vec3 lightPosition(center+osg::Vec3(0.0f,0.0f,radius)); // the shadower model osg::Node* shadower = createMovingModel(center,radius*0.5f); // the shadowed model osg::Node* shadowed = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.25),radius); // combine the models together to create one which has the shadower and the shadowed with the required callback. osg::Group* root = createShadowedScene(shadower,shadowed,lightPosition,radius/100.0f,1); return root; } 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 of pre rendering to texture to create a shadow effect.."); 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; } // load the nodes from the commandline arguments. osg::Node* model = createModel(); if (!model) { return 1; } // comment out optimization over the scene graph right now as it optimizers away the shadow... will look into this.. //osgUtil::Optimizer optimzer; //optimzer.optimize(rootnode); // add a viewport to the viewer and attach the scene graph. viewer.setSceneData( model ); // 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(); } // wait for all cull and draw threads to complete before exit. viewer.sync(); return 0; }