diff --git a/examples/osgspheresegment/GNUmakefile b/examples/osgspheresegment/GNUmakefile index fd8ab76d9..e9c447f48 100644 --- a/examples/osgspheresegment/GNUmakefile +++ b/examples/osgspheresegment/GNUmakefile @@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs CXXFILES =\ osgspheresegment.cpp\ -LIBS += -losgText -losgProducer -lProducer -losgSim -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) +LIBS += -losgProducer -lProducer -losgParticle -losgSim -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) INSTFILES = \ $(CXXFILES)\ diff --git a/examples/osgspheresegment/osgspheresegment.cpp b/examples/osgspheresegment/osgspheresegment.cpp index 15575b762..96ae6a286 100644 --- a/examples/osgspheresegment/osgspheresegment.cpp +++ b/examples/osgspheresegment/osgspheresegment.cpp @@ -1,106 +1,266 @@ +#include + +#include #include #include -#include #include -#include -#include #include -#include -#include +#include -#include -#include -#include +#include #include -#include -#include -#include - #include -using namespace osgSim; +#include +#include +#include +#include -class MyNodeCallback: public osg::NodeCallback +// for the grid data.. +#include "../osghangglide/terrain_coords.h" + +osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) { - void operator()(osg::Node*,osg::NodeVisitor*); -}; - -// void MyNodeCallback::operator()(osg::Node* n,osg::NodeVisitor* nv) -// { -// if(osgSim::SphereSegment* ss=dynamic_cast(n)) -// { -// osg::Vec3 vec; -// float azRange, elevRange; -// ss->getArea(vec,azRange,elevRange); -// -// float azRangeDeg = osg::RadiansToDegrees(azRange); -// -// static bool azAscending = false; -// -// if(azAscending){ -// azRangeDeg += 1.0f; -// if(azRangeDeg>89.0f) azAscending = false; -// }else{ -// azRangeDeg -= 1.0f; -// if(azRangeDeg<2.0f) azAscending = true; -// } -// -// ss->setArea(vec,osg::DegreesToRadians(azRangeDeg),elevRange); -// -// } -// traverse(n,nv); -// } - -void MyNodeCallback::operator()(osg::Node* n,osg::NodeVisitor* nv) -{ - if(osgSim::SphereSegment* ss=dynamic_cast(n)) + // 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;igetArea(vec,azRange,elevRange); + osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f)); + osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0))); + + animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation)); - static float angle = 0.0f; - if(++angle > 359.0f) angle = 0.0f; - vec.set(sin(osg::DegreesToRadians(angle)),cos(osg::DegreesToRadians(angle)),0.0f); + yaw += yaw_delta; + time += time_delta; - std::cout<<"angle "<setArea(vec,azRange,elevRange); } - traverse(n,nv); + return animationPath; } -osg::Node* createSphereSegment() +osg::Node* createMovingModel(const osg::Vec3& center, float radius) { - SphereSegment* ss = new SphereSegment(osg::Vec3(0.0f,0.0f,0.0f), 1.0f, - osg::Vec3(0.0f,1.0f,0.0f), - osg::DegreesToRadians(90.0f), - osg::DegreesToRadians(45.0f), - 60); - ss->setAllColors(osg::Vec4(1.0f,1.0f,1.0f,0.5f)); - ss->setSideColor(osg::Vec4(0.0f,0.0f,1.0f,0.5f)); - //ss->setDrawMask(SphereSegment::DrawMask(SphereSegment::SPOKES | SphereSegment::EDGELINE)); + float animationLength = 10.0f; - //ss->setUpdateCallback(new MyNodeCallback); + osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); - return ss; + osg::Group* model = new osg::Group; + + osg::Node* glider = osgDB::readNodeFile("glider.osg"); + if (glider) + { + const osg::BoundingSphere& bs = glider->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(-90.0f),0.0f,0.0f,1.0f)); + + positioned->addChild(glider); + + osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform; + xform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); + if (cessna) + { + const osg::BoundingSphere& bs = cessna->getBound(); + + osgText::Text* text = new osgText::Text; + float size = radius/bs.radius()*0.3f; + + text->setPosition(bs.center()); + text->setText("Cessna"); + text->setAlignment(osgText::Text::CENTER_CENTER); + text->setAxisAlignment(osgText::Text::SCREEN); + text->setCharacterSize(40.0f); + text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + + osg::LOD* lod = new osg::LOD; + lod->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN); + lod->addChild(geode,0.0f,100.0f); + lod->addChild(cessna,100.0f,10000.0f); + + + osg::MatrixTransform* positioned = new osg::MatrixTransform; + positioned->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + 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,1.0f)); + + //positioned->addChild(cessna); + positioned->addChild(lod); + + osg::MatrixTransform* xform = new osg::MatrixTransform; + xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + return model; } -int main( int argc, char **argv ) + +osg::Vec3 computeTerrainIntersection(osg::Node* subgraph,float x,float y) +{ + osgUtil::IntersectVisitor iv; + osg::ref_ptr segDown = new osg::LineSegment; + + const osg::BoundingSphere& bs = subgraph->getBound(); + float zMax = bs.center().z()+bs.radius(); + float zMin = bs.center().z()-bs.radius(); + + segDown->set(osg::Vec3(x,y,zMin),osg::Vec3(x,y,zMax)); + iv.addLineSegment(segDown.get()); + + subgraph->accept(iv); + + if (iv.hits()) + { + osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get()); + if (!hitList.empty()) + { + osg::Vec3 ip = hitList.front().getWorldIntersectPoint(); + return ip; + } + } + + return osg::Vec3(x,y,0.0f); +} + + +////////////////////////////////////////////////////////////////////////////// +// MAIN SCENE GRAPH BUILDING FUNCTION +////////////////////////////////////////////////////////////////////////////// + +void build_world(osg::Group *root) +{ + + osg::Geode* terrainGeode = new osg::Geode; + // create terrain + { + 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); + } + + terrainGeode->setStateSet( stateset ); + + float size = 1000; // 10km; + float scale = size/39.0f; // 10km; + float z_scale = scale*3.0f; + + osg::HeightField* grid = new osg::HeightField; + grid->allocateGrid(38,39); + grid->setXInterval(scale); + grid->setYInterval(scale); + + for(unsigned int r=0;r<39;++r) + { + for(unsigned int c=0;c<38;++c) + { + grid->setHeight(c,r,z_scale*vertex[r+c*39][2]); + } + } + terrainGeode->addDrawable(new osg::ShapeDrawable(grid)); + + root->addChild(terrainGeode); + } + + // create sphere segment + { + osgSim::SphereSegment* ss = new osgSim::SphereSegment( + computeTerrainIntersection(terrainGeode,550.0f,780.0f), // center + 500.0f, // radius + osg::DegreesToRadians(135.0f), + osg::DegreesToRadians(245.0f), + osg::DegreesToRadians(-10.0f), + osg::DegreesToRadians(30.0f), + 60); + ss->setAllColors(osg::Vec4(1.0f,1.0f,1.0f,0.5f)); + ss->setSideColor(osg::Vec4(0.0f,1.0f,1.0f,0.1f)); + + root->addChild(ss); + } + + + // create particle effects + { + osg::PositionAttitudeTransform* positionEffects = new osg::PositionAttitudeTransform; + positionEffects->setPosition(computeTerrainIntersection(terrainGeode,100.0f,100.0f)); + root->addChild(positionEffects); + + osgParticle::ExplosionEffect* explosion = new osgParticle::ExplosionEffect; + osgParticle::SmokeEffect* smoke = new osgParticle::SmokeEffect; + osgParticle::FireEffect* fire = new osgParticle::FireEffect; + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),10.0f))); + positionEffects->addChild(geode); + + positionEffects->addChild(explosion); + positionEffects->addChild(smoke); + positionEffects->addChild(fire); + + osgParticle::ParticleSystemUpdater *psu = new osgParticle::ParticleSystemUpdater; + + psu->addParticleSystem(explosion->getParticleSystem()); + psu->addParticleSystem(smoke->getParticleSystem()); + psu->addParticleSystem(fire->getParticleSystem()); + + // add the updater node to the scene graph + root->addChild(psu); + } + + + // create the moving models. + { + root->addChild(createMovingModel(osg::Vec3(500.0f,500.0f,500.0f),100.0f)); + } +} + + +////////////////////////////////////////////////////////////////////////////// +// main() +////////////////////////////////////////////////////////////////////////////// + + +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 both text, animation and billboard via custom transform to create the OpenSceneGraph logo.."); - arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of particle systems."); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye"); 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); @@ -127,12 +287,13 @@ int main( int argc, char **argv ) arguments.writeErrorMessages(std::cout); return 1; } - - osg::Node* node = createSphereSegment(); - - // add model to viewer. - viewer.setSceneData( node ); - + + osg::Group *root = new osg::Group; + build_world(root); + + // add a viewport to the viewer and attach the scene graph. + viewer.setSceneData(root); + // create the windows and run the threads. viewer.realize(); @@ -144,11 +305,12 @@ int main( int argc, char **argv ) // 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();