root/OpenSceneGraph/trunk/examples/osgplanets/osgplanets.cpp @ 3558

Revision 3558, 20.3 kB (checked in by robert, 10 years ago)

Fixed support for NodeTrackerManipulator?.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <iostream>
2
3#include <osg/Notify>
4#include <osg/MatrixTransform>
5#include <osg/PositionAttitudeTransform>
6#include <osg/Geometry>
7#include <osg/Geode>
8#include <osg/ShapeDrawable>
9#include <osg/Texture2D>
10#include <osg/Material>
11#include <osg/Light>
12#include <osg/LightSource>
13#include <osg/LightModel>
14
15
16#include <osgUtil/Optimizer>
17
18#include <osgDB/Registry>
19#include <osgDB/ReadFile>
20
21#include <osgGA/NodeTrackerManipulator>
22#include <osgGA/TrackballManipulator>
23#include <osgGA/FlightManipulator>
24#include <osgGA/DriveManipulator>
25
26#include <osgProducer/Viewer>
27
28
29static osg::Vec3 defaultPos( 0.0f, 0.0f, 0.0f );
30static osg::Vec3 centerScope(0.0f, 0.0f, 0.0f);
31   
32
33
34
35
36osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
37{
38    // set up the animation path
39    osg::AnimationPath* animationPath = new osg::AnimationPath;
40    animationPath->setLoopMode(osg::AnimationPath::LOOP);
41   
42    int numSamples = 40;
43    float yaw = 0.0f;
44    float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
45    float roll = osg::inDegrees(30.0f);
46   
47    double time=0.0f;
48    double time_delta = looptime/(double)numSamples;
49    for(int i=0;i<numSamples;++i)
50    {
51        osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
52        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)));
53       
54        animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
55
56        yaw += yaw_delta;
57        time += time_delta;
58
59    }
60    return animationPath;   
61}// end createAnimationPath
62
63
64
65class SolarSystem
66{
67
68public:
69    double _radiusSun;
70    double _radiusEarth;
71    double _RorbitEarth;
72    double _tiltEarth;
73    double _rotateSpeedEarthAndMoon;
74    double _rotateSpeedEarth;
75    double _radiusMoon;
76    double _RorbitMoon;
77    double _rotateSpeedMoon;
78    double _radiusSpace;
79   
80    SolarSystem()
81    {
82        _radiusSun = 5.0;
83        _radiusEarth = 2.0;
84        _RorbitEarth = 10.0;
85        _tiltEarth = 18.0;
86        _rotateSpeedEarthAndMoon = 1.0;
87        _rotateSpeedEarth = 1.0;
88        _radiusMoon = 0.5;
89        _RorbitMoon = 2.0;
90        _rotateSpeedMoon = 1.0;
91        _radiusSpace = 300.0;
92    }
93   
94    osg::MatrixTransform* createEarthTranslationAndTilt();
95    osg::MatrixTransform* createRotation( double orbit, double speed );
96    osg::MatrixTransform* createMoonTranslation();
97    osg::Geode* createSpace( const std::string& name, const std::string& textureName );
98    osg::Geode* createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName );
99    osg::Group* createSunLight();
100    osg::Group* built();
101   
102    void printParameters()
103    {
104        std::cout << "radiusSun\t= " << _radiusSun << std::endl;
105        std::cout << "radiusEarth\t= " << _radiusEarth << std::endl;
106        std::cout << "RorbitEarth\t= " << _RorbitEarth << std::endl;
107        std::cout << "tiltEarth\t= " << _tiltEarth << std::endl;
108        std::cout << "rotateSpeedEarthAndMoon= " << _rotateSpeedEarthAndMoon     << std::endl;
109        std::cout << "rotateSpeedEarth= " << _rotateSpeedEarth << std::endl;
110        std::cout << "radiusMoon\t= " << _radiusMoon << std::endl;
111        std::cout << "RorbitMoon\t= " << _RorbitMoon << std::endl;
112        std::cout << "rotateSpeedMoon\t= " << _rotateSpeedMoon << std::endl;
113        std::cout << "radiusSpace\t= " << _radiusSpace << std::endl;
114       
115    }
116   
117};  // end SolarSystem
118
119class FindNamedNodeVisitor : public osg::NodeVisitor
120{
121public:
122    FindNamedNodeVisitor(const std::string& name):
123        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
124        _name(name) {}
125   
126    virtual void apply(osg::Node& node)
127    {
128        if (node.getName()==_name)
129        {
130            _foundNodes.push_back(&node);
131        }
132        traverse(node);
133    }
134   
135    typedef std::vector< osg::ref_ptr<osg::Node> > NodeList;
136
137    std::string _name;
138    NodeList _foundNodes;
139};
140
141int main( int argc, char **argv )
142{
143    // use an ArgumentParser object to manage the program arguments.
144    osg::ArgumentParser arguments(&argc,argv);
145
146    // set up the usage document, in case we need to print out how to use this program.
147    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of osg::AnimationPath and UpdateCallbacks for adding animation to your scenes.");
148    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
149    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
150
151    // initialize the viewer.
152    osgProducer::Viewer viewer(arguments);
153
154    // set up the value with sensible default event handlers.
155    viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE | osgProducer::Viewer::VIEWER_MANIPULATOR | osgProducer::Viewer::STATE_MANIPULATOR);
156
157    // get details on keyboard and mouse bindings used by the viewer.
158    viewer.getUsage(*arguments.getApplicationUsage());
159
160    SolarSystem solarSystem;
161
162    while (arguments.read("--radiusSun",solarSystem._radiusSun)) { }
163    while (arguments.read("--radiusEarth",solarSystem._radiusEarth)) { }
164    while (arguments.read("--RorbitEarth",solarSystem._RorbitEarth)) { }
165    while (arguments.read("--tiltEarth",solarSystem._tiltEarth)) { }
166    while (arguments.read("--rotateSpeedEarthAndMoon",solarSystem._rotateSpeedEarthAndMoon)) { }
167    while (arguments.read("--rotateSpeedEarth",solarSystem._rotateSpeedEarth)) { }
168    while (arguments.read("--radiusMoon",solarSystem._radiusMoon)) { }
169    while (arguments.read("--RorbitMoon",solarSystem._RorbitMoon)) { }
170    while (arguments.read("--rotateSpeedMoon",solarSystem._rotateSpeedMoon)) { }
171    while (arguments.read("--radiusSpace",solarSystem._radiusSpace)) { }
172   
173   
174    osgGA::NodeTrackerManipulator::TrackerMode trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
175    std::string mode;
176    while (arguments.read("--tracker-mode",mode))
177    {
178        if (mode=="NODE_CENTER_AND_ROTATION") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
179        else if (mode=="NODE_CENTER_AND_AZIM") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_AZIM;
180        else if (mode=="NODE_CENTER") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER;
181        else
182        {
183            std::cout<<"Unrecognized --tracker-mode option "<<mode<<", valid options are:"<<std::endl;
184            std::cout<<"    NODE_CENTER_AND_ROTATION"<<std::endl;
185            std::cout<<"    NODE_CENTER_AND_AZIM"<<std::endl;
186            std::cout<<"    NODE_CENTER"<<std::endl;
187            return 1;
188        }
189    }
190   
191   
192    osgGA::NodeTrackerManipulator::RotationMode rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
193    while (arguments.read("--rotation-mode",mode))
194    {
195        if (mode=="TRACKBALL") rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
196        else if (mode=="ELEVATION_AZIM") rotationMode = osgGA::NodeTrackerManipulator::ELEVATION_AZIM;
197        else
198        {
199            std::cout<<"Unrecognized --rotation-mode option "<<mode<<", valid options are:"<<std::endl;
200            std::cout<<"    TRACKBALL"<<std::endl;
201            std::cout<<"    ELEVATION_AZIM"<<std::endl;
202            return 1;
203        }
204    }
205   
206
207    solarSystem.printParameters();
208
209    // if user request help write it out to cout.
210    if (arguments.read("-h") || arguments.read("--help"))
211    {
212        std::cout << "setup the following arguments: " << std::endl;
213        std::cout << "--radiusSun: double" << std::endl;
214        std::cout << "--radiusEarth: double" << std::endl;
215        std::cout << "--RorbitEarth: double" << std::endl;
216        std::cout << "--tiltEarth: double" << std::endl;
217        std::cout << "--rotateSpeedEarthAndMoon: double" << std::endl;
218        std::cout << "--rotateSpeedEarth: double" << std::endl;
219        std::cout << "--radiusMoon: double" << std::endl;
220        std::cout << "--RorbitMoon: double" << std::endl;
221        std::cout << "--rotateSpeedMoon: double" << std::endl;
222        std::cout << "--radiusSpace: double" << std::endl;
223       
224               
225        return 1;
226    }
227
228    // any option left unread are converted into errors to write out later.
229    arguments.reportRemainingOptionsAsUnrecognized();
230
231    // report any errors if they have occured when parsing the program aguments.
232    if (arguments.errors())
233    {
234        arguments.writeErrorMessages(std::cout);
235        return 1;
236    }
237   
238   
239    osg::Group* root = new osg::Group;
240
241    osg::Group* sunLight = solarSystem.createSunLight();
242    root->addChild(sunLight);
243
244    // create the sun
245    osg::Node* sun = solarSystem.createPlanet( solarSystem._radiusSun, "Sun", osg::Vec4( 1.0, 1.0, 0, 1.0f), "" );
246    osg::StateSet* sunStateSet = sun->getOrCreateStateSet();
247    osg::Material* material = new osg::Material;
248    material->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 0.0f, 0.0f ) );
249    sunStateSet->setAttributeAndModes( material, osg::StateAttribute::ON );
250
251    // stick sun right under root, no transformations for the sun
252    sunLight->addChild( sun );
253
254    // create light source in the sun
255
256    // create earth and moon
257    osg::Node* earth = solarSystem.createPlanet( solarSystem._radiusEarth, "Earth", osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), "Images/land_shallow_topo_2048.jpg" );
258    osg::Node* moon = solarSystem.createPlanet( solarSystem._radiusMoon, "Moon", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), "Images/moon256128.TGA" );
259
260    // create transformations for the earthMoonGroup
261    osg::MatrixTransform* aroundSunRotation = solarSystem.createRotation( solarSystem._RorbitEarth, solarSystem._rotateSpeedEarthAndMoon );
262    osg::MatrixTransform* earthPosition = solarSystem.createEarthTranslationAndTilt();
263
264
265    //Group with earth and moon under it
266    osg::Group* earthMoonGroup = new osg::Group;
267   
268
269    //transformation to rotate the earth around itself
270    osg::MatrixTransform* earthRotationAroundItself = solarSystem.createRotation ( 0.0, solarSystem._rotateSpeedEarth );
271
272    //transformations for the moon
273    osg::MatrixTransform* moonAroundEarthXform = solarSystem.createRotation( solarSystem._RorbitMoon, solarSystem._rotateSpeedMoon );
274    osg::MatrixTransform* moonTranslation = solarSystem.createMoonTranslation();
275
276
277    moonTranslation->addChild( moon );
278    moonAroundEarthXform->addChild( moonTranslation );
279    earthMoonGroup->addChild( moonAroundEarthXform );
280
281    earthRotationAroundItself->addChild( earth );
282
283    earthMoonGroup->addChild( earthRotationAroundItself );
284
285    earthPosition->addChild( earthMoonGroup );
286
287    aroundSunRotation->addChild( earthPosition );
288
289    sunLight->addChild( aroundSunRotation );
290
291#if 0
292    // add space, but don't light it, as its not illuminated by our sun
293    osg::Node* space = solarSystem.createSpace( "Space", "Images/spacemap.jpg" );
294    space->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
295    root->addChild( space );
296#endif
297   
298    // run optimization over the scene graph
299    osgUtil::Optimizer optimzer;
300    //optimzer.optimize( dynamic_cast<osg::CoordinateSystemNode*>( root.get() ) );
301    optimzer.optimize( root );
302     
303    // set the scene to render
304    viewer.setSceneData( root );
305
306
307    // set up tracker manipulators, once for each astral body
308    {
309        FindNamedNodeVisitor fnnv("Sun");
310        root->accept(fnnv);
311
312        if (!fnnv._foundNodes.empty())
313        {
314            // set up the node tracker.
315            osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
316            tm->setTrackerMode( trackerMode );
317            tm->setRotationMode( rotationMode );
318            tm->setTrackNode( fnnv._foundNodes.front().get() );
319
320            unsigned int num = viewer.addCameraManipulator( tm );
321            viewer.selectCameraManipulator( num );
322        }
323    }   
324
325    {
326        FindNamedNodeVisitor fnnv("Moon");
327        root->accept(fnnv);
328
329        if (!fnnv._foundNodes.empty())
330        {
331            // set up the node tracker.
332            osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
333            tm->setTrackerMode( trackerMode );
334            tm->setRotationMode( rotationMode );
335            tm->setTrackNode( fnnv._foundNodes.front().get() );
336
337            unsigned int num = viewer.addCameraManipulator( tm );
338            viewer.selectCameraManipulator( num );
339        }
340    }   
341
342    {
343        FindNamedNodeVisitor fnnv("Earth");
344        root->accept(fnnv);
345
346        if (!fnnv._foundNodes.empty())
347        {
348            // set up the node tracker.
349            osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
350            tm->setTrackerMode( trackerMode );
351            tm->setRotationMode( rotationMode );
352            tm->setTrackNode( fnnv._foundNodes.front().get() );
353
354            unsigned int num = viewer.addCameraManipulator( tm );
355            viewer.selectCameraManipulator( num );
356        }
357    }   
358   
359    // create the windows and run the threads.
360    viewer.realize();
361   
362    viewer.setClearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
363
364    while( !viewer.done() )
365    {
366        // wait for all cull and draw threads to complete.
367        viewer.sync();
368
369        // update the scene by traversing it with the the update visitor which will
370        // call all node update callbacks and animations.
371        viewer.update();
372         
373        // fire off the cull and draw traversals of the scene.
374        viewer.frame();
375       
376    }
377   
378    // wait for all cull and draw threads to complete before exit.
379    viewer.sync();
380
381    return 0;
382}// end main
383
384
385osg::MatrixTransform* SolarSystem::createEarthTranslationAndTilt()
386{
387        osg::MatrixTransform* earthPositioned = new osg::MatrixTransform;
388        earthPositioned->setMatrix(osg::Matrix::translate(osg::Vec3( 0.0, _RorbitEarth, 0.0 ) )*
389                                     osg::Matrix::scale(1.0, 1.0, 1.0)*
390                                     osg::Matrix::rotate(osg::inDegrees( _tiltEarth ),0.0f,0.0f,1.0f));
391
392        return earthPositioned;
393}// end SolarSystem::createEarthTranslationAndTilt
394
395
396osg::MatrixTransform* SolarSystem::createRotation( double orbit, double speed )
397{
398    osg::Vec3 center( 0.0, 0.0, 0.0 );
399    float animationLength = 10.0f;
400    osg::AnimationPath* animationPath = createAnimationPath( center, orbit, animationLength );
401
402    osg::MatrixTransform* rotation = new osg::MatrixTransform;
403    rotation->setUpdateCallback( new osg::AnimationPathCallback( animationPath, 0.0f, speed ) );
404
405    return rotation;
406}// end SolarSystem::createEarthRotation
407
408
409osg::MatrixTransform* SolarSystem::createMoonTranslation()
410{
411    osg::MatrixTransform* moonPositioned = new osg::MatrixTransform;
412    moonPositioned->setMatrix(osg::Matrix::translate(osg::Vec3( 0.0, _RorbitMoon, 0.0 ) )*
413                                 osg::Matrix::scale(1.0, 1.0, 1.0)*
414                                 osg::Matrix::rotate(osg::inDegrees(0.0f),0.0f,0.0f,1.0f));
415
416    return moonPositioned;
417}// end SolarSystem::createMoonTranslation
418   
419   
420osg::Geode* SolarSystem::createSpace( const std::string& name, const std::string& textureName )
421{
422    osg::Sphere *spaceSphere = new osg::Sphere( osg::Vec3( 0.0, 0.0, 0.0 ), _radiusSpace );
423
424    osg::ShapeDrawable *sSpaceSphere = new osg::ShapeDrawable( spaceSphere );
425
426    if( !textureName.empty() )
427    {
428        osg::Image* image = osgDB::readImageFile( textureName );
429        if ( image )
430        {
431            sSpaceSphere->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D( image ), osg::StateAttribute::ON );
432
433            // reset the object color to white to allow the texture to set the colour.
434            sSpaceSphere->setColor( osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
435        }
436    }
437
438    osg::Geode* geodeSpace = new osg::Geode();
439    geodeSpace->setName( name );
440
441    geodeSpace->addDrawable( sSpaceSphere );
442
443    return( geodeSpace );
444
445}// end SolarSystem::createSpace
446
447   
448osg::Geode* SolarSystem::createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName )
449{
450    // create a cube shape
451    osg::Sphere *planetSphere = new osg::Sphere( osg::Vec3( 0.0, 0.0, 0.0 ), radius );
452
453    // create a container that makes the sphere drawable
454    osg::ShapeDrawable *sPlanetSphere = new osg::ShapeDrawable( planetSphere );
455
456    // set the object color
457    sPlanetSphere->setColor( color );
458
459    if( !textureName.empty() )
460    {
461        osg::Image* image = osgDB::readImageFile( textureName );
462        if ( image )
463        {
464            sPlanetSphere->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D( image ), osg::StateAttribute::ON );
465
466            // reset the object color to white to allow the texture to set the colour.
467            sPlanetSphere->setColor( osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
468        }
469    }
470
471
472    // create a geode object to as a container for our drawable sphere object
473    osg::Geode* geodePlanet = new osg::Geode();
474    geodePlanet->setName( name );
475
476    // add our drawable sphere to the geode container
477    geodePlanet->addDrawable( sPlanetSphere );
478
479    return( geodePlanet );
480
481}// end SolarSystem::createPlanet
482   
483osg::Group* SolarSystem::createSunLight()
484{
485
486    osg::LightSource* sunLightSource = new osg::LightSource;
487
488    osg::Light* sunLight = sunLightSource->getLight();
489    sunLight->setPosition( osg::Vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
490    sunLight->setAmbient( osg::Vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
491
492    sunLightSource->setLight( sunLight );
493    sunLightSource->setLocalStateSetModes( osg::StateAttribute::ON );
494    sunLightSource->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
495
496    osg::LightModel* lightModel = new osg::LightModel;
497    lightModel->setAmbientIntensity(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
498    sunLightSource->getOrCreateStateSet()->setAttribute(lightModel);
499
500
501    return sunLightSource;
502}// end SolarSystem::createSunLight
503   
504
505/*
506osg::Group* SolarSystem::built()
507{
508    osg::Group* thisSystem = new osg::Group;
509
510    // create light source in the sun
511    osg::Group* sunLight = createSunLight();
512    thisSystem->addChild( sunLight );
513
514
515    // create the sun
516    osg::Node* sun = createPlanet( _radiusSun, "Sun", osg::Vec4( 0, 0, 0, 1.0f), "" );
517    osg::StateSet* sunStateSet = sun->getOrCreateStateSet();
518    osg::Material* material = new osg::Material;
519    material->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 0.0f, 0.0f ) );
520    sunStateSet->setAttributeAndModes( material, osg::StateAttribute::ON );
521
522    if( !sun )
523    {
524        std::cout << "Sonne konnte nicht erstellt werden!" << std::endl;
525        exit(0);
526    }
527    sun->setStateSet( sunStateSet );
528
529    // stick sun right under root, no transformations for the sun
530    sunLight->addChild(sun);
531
532
533    //creating right side of the graph with earth and moon and the rotations above it
534
535    // create earth and moon
536    osg::Node* earth = createPlanet( _radiusEarth, "Earth", osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), "Images/land_shallow_topo_2048.jpg" );
537    osg::Node* moon = createPlanet( _radiusMoon, "Moon", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), "Images/moon256128.TGA" );
538
539    // create transformations for the earthMoonGroup
540    osg::MatrixTransform* aroundSunRotation = createRotation( _RorbitEarth, _rotateSpeedEarthAndMoon );
541    osg::MatrixTransform* earthPosition = createEarthTranslationAndTilt( _RorbitEarth, _tiltEarth );
542
543    //Group with earth and moon under it
544    osg::Group* earthMoonGroup = new osg::Group;
545
546    //transformation to rotate the earth around itself
547    osg::MatrixTransform* earthRotationAroundItself = createRotation ( 0.0, _rotateSpeedEarth );
548
549    //transformations for the moon
550    osg::MatrixTransform* moonAroundEarthXform = createRotation( _RorbitMoon, _rotateSpeedMoon );
551    osg::MatrixTransform* moonTranslation = createMoonTranslation( _RorbitMoon );
552
553
554    moonTranslation->addChild( moon );
555    moonAroundEarthXform->addChild( moonTranslation );
556    earthMoonGroup->addChild( moonAroundEarthXform );
557
558    earthRotationAroundItself->addChild( earth );
559
560    earthMoonGroup->addChild( earthRotationAroundItself );
561
562    earthPosition->addChild( earthMoonGroup );
563
564
565    aroundSunRotation->addChild( earthPosition );
566
567    sunLight->addChild( aroundSunRotation );
568
569    // add space, but don't light it, as its not illuminated by our sun
570    osg::Node* space = createSpace( _radiusSpace, "Space", "Images/spacemap.jpg" );
571    space->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
572    thisSystem->addChild( space );
573
574    return( thisSystem );
575}// end SolarSystem::built()
576*/
Note: See TracBrowser for help on using the browser.