#include #include #include #include #include #include #include #include #include #include #include #include #include // for the grid data.. #include "../osghangglide/terrain_coords.h" osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power) { osg::Image* image = new osg::Image; image->allocateImage(size,size,1, GL_RGBA,GL_UNSIGNED_BYTE); float mid = (float(size)-1)*0.5f; float div = 2.0f/float(size); for(unsigned int r=0;rdata(0,r,0); for(unsigned int c=0;csetMode(GL_LIGHT0+lightNum, osg::StateAttribute::ON); osg::Vec4 centerColour(1.0f,1.0f,1.0f,1.0f); osg::Vec4 ambientColour(0.05f,0.05f,0.05f,1.0f); // set up spot light texture osg::Texture2D* texture = new osg::Texture2D(); texture->setImage(createSpotLightImage(centerColour, ambientColour, 64, 1.0)); texture->setBorderColor(osg::Vec4(ambientColour)); texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_BORDER); texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_BORDER); texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_BORDER); stateset->setTextureAttributeAndModes(textureUnit, texture, osg::StateAttribute::ON); // set up tex gens stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON); stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON); stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON); stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON); return stateset; } osg::Node* createSpotLightNode(const osg::Vec3& position, const osg::Vec3& direction, float angle, unsigned int lightNum, unsigned int textureUnit) { osg::Group* group = new osg::Group; // create light source. osg::LightSource* lightsource = new osg::LightSource; osg::Light* light = lightsource->getLight(); light->setLightNum(lightNum); light->setPosition(osg::Vec4(position,1.0f)); light->setAmbient(osg::Vec4(0.00f,0.00f,0.05f,1.0f)); light->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); group->addChild(lightsource); // create tex gen. osg::Vec3 up(0.0f,0.0f,1.0f); up = (direction ^ up) ^ direction; up.normalize(); osg::TexGenNode* texgenNode = new osg::TexGenNode; texgenNode->setTextureUnit(textureUnit); osg::TexGen* texgen = texgenNode->getTexGen(); texgen->setMode(osg::TexGen::EYE_LINEAR); texgen->setPlanesFromMatrix(osg::Matrixd::lookAt(position, position+direction, up)* osg::Matrixd::perspective(angle,1.0,0.1,100)); group->addChild(texgenNode); return group; } 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->allocateGrid(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); xform->addChild(createSpotLightNode(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(0.0f,1.0f,-1.0f), 60.0f, 0, 1)); 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.1),radius); // combine the models together to create one which has the shadower and the shadowed with the required callback. osg::Group* root = new osg::Group; root->setStateSet(createSpotLightDecoratorState(0,1)); root->addChild(shadower); root->addChild(shadowed); 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; }