diff --git a/examples/osgspotlight/GNUmakefile b/examples/osgspotlight/GNUmakefile new file mode 100644 index 000000000..2cc5f83b9 --- /dev/null +++ b/examples/osgspotlight/GNUmakefile @@ -0,0 +1,17 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgspotlight.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + GNUmakefile.inst=GNUmakefile + +EXEC = osgspotlight + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgspotlight/GNUmakefile.inst b/examples/osgspotlight/GNUmakefile.inst new file mode 100644 index 000000000..3e94b0850 --- /dev/null +++ b/examples/osgspotlight/GNUmakefile.inst @@ -0,0 +1,14 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgspotlight.cpp\ + +LIBS += -losgProducer -lProducer -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgspotlight + +INC += $(PRODUCER_INCLUDE_DIR) $(X_INC) +LDFLAGS += $(PRODUCER_LIB_DIR) + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgspotlight/osgspotlight.cpp b/examples/osgspotlight/osgspotlight.cpp new file mode 100644 index 000000000..861f872a0 --- /dev/null +++ b/examples/osgspotlight/osgspotlight.cpp @@ -0,0 +1,336 @@ +#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; +}