1 /* OpenSceneGraph example, osgplanets.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 * THE SOFTWARE.
17 */
18
19 /* details about distances and rotation on http://www.solarviews.com/eng/solarsys.htm */
20
21 #include <iostream>
22
23 #include <osg/Notify>
24 #include <osg/MatrixTransform>
25 #include <osg/PositionAttitudeTransform>
26 #include <osg/Geometry>
27 #include <osg/Geode>
28 #include <osg/ShapeDrawable>
29 #include <osg/Texture2D>
30 #include <osg/Material>
31 #include <osg/Light>
32 #include <osg/LightSource>
33 #include <osg/LightModel>
34 #include <osg/Billboard>
35 #include <osg/LineWidth>
36 #include <osg/TexEnv>
37 #include <osg/TexEnvCombine>
38 #include <osg/ClearNode>
39
40
41 #include <osgUtil/Optimizer>
42
43 #include <osgDB/Registry>
44 #include <osgDB/ReadFile>
45 #include <osgDB/WriteFile>
46
47
48 #include <osgGA/NodeTrackerManipulator>
49 #include <osgGA/TrackballManipulator>
50 #include <osgGA/FlightManipulator>
51 #include <osgGA/DriveManipulator>
52 #include <osgGA/KeySwitchMatrixManipulator>
53
54 #include <osgViewer/Viewer>
55
56
57 static osg::Vec3 defaultPos( 0.0f, 0.0f, 0.0f );
58 static osg::Vec3 centerScope(0.0f, 0.0f, 0.0f);
59
60
61 /** create quad at specified position. */
createSquare(const osg::Vec3 & corner,const osg::Vec3 & width,const osg::Vec3 & height,osg::Image * image=NULL)62 osg::Drawable* createSquare(const osg::Vec3& corner,const osg::Vec3& width,const osg::Vec3& height, osg::Image* image=NULL)
63 {
64 // set up the Geometry.
65 osg::Geometry* geom = new osg::Geometry;
66
67 osg::Vec3Array* coords = new osg::Vec3Array(4);
68 (*coords)[0] = corner;
69 (*coords)[1] = corner+width;
70 (*coords)[2] = corner+width+height;
71 (*coords)[3] = corner+height;
72
73
74 geom->setVertexArray(coords);
75
76 osg::Vec3Array* norms = new osg::Vec3Array(1);
77 (*norms)[0] = width^height;
78 (*norms)[0].normalize();
79
80 geom->setNormalArray(norms, osg::Array::BIND_OVERALL);
81
82 osg::Vec2Array* tcoords = new osg::Vec2Array(4);
83 (*tcoords)[0].set(0.0f,0.0f);
84 (*tcoords)[1].set(1.0f,0.0f);
85 (*tcoords)[2].set(1.0f,1.0f);
86 (*tcoords)[3].set(0.0f,1.0f);
87 geom->setTexCoordArray(0,tcoords);
88
89 osg::Vec4Array* colours = new osg::Vec4Array(1);
90 (*colours)[0].set(1.0f,1.0f,1.0f,1.0f);
91 geom->setColorArray(colours, osg::Array::BIND_OVERALL);
92
93
94 geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
95
96 if (image)
97 {
98 osg::StateSet* stateset = new osg::StateSet;
99 osg::Texture2D* texture = new osg::Texture2D;
100 texture->setImage(image);
101 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
102 stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
103 stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
104 stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
105 geom->setStateSet(stateset);
106 }
107
108 return geom;
109 }
110
createBillboardImage(const osg::Vec4 & centerColour,unsigned int size,float power)111 osg::Image* createBillboardImage(const osg::Vec4& centerColour, unsigned int size, float power)
112 {
113 osg::Vec4 backgroundColour = centerColour;
114 backgroundColour[3] = 0.0f;
115
116 osg::Image* image = new osg::Image;
117 image->allocateImage(size,size,1,
118 GL_RGBA,GL_UNSIGNED_BYTE);
119
120
121 float mid = (float(size)-1)*0.5f;
122 float div = 2.0f/float(size);
123 for(unsigned int r=0;r<size;++r)
124 {
125 unsigned char* ptr = image->data(0,r,0);
126 for(unsigned int c=0;c<size;++c)
127 {
128 float dx = (float(c) - mid)*div;
129 float dy = (float(r) - mid)*div;
130 float r = powf(1.0f-sqrtf(dx*dx+dy*dy),power);
131 if (r<0.0f) r=0.0f;
132 osg::Vec4 color = centerColour*r+backgroundColour*(1.0f-r);
133 // color.set(1.0f,1.0f,1.0f,0.5f);
134 *ptr++ = (unsigned char)((color[0])*255.0f);
135 *ptr++ = (unsigned char)((color[1])*255.0f);
136 *ptr++ = (unsigned char)((color[2])*255.0f);
137 *ptr++ = (unsigned char)((color[3])*255.0f);
138 }
139 }
140 return image;
141
142 //return osgDB::readImageFile("spot.dds");
143 }
144
createAnimationPath(const osg::Vec3 & center,float radius,double looptime)145 osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
146 {
147 // set up the animation path
148 osg::AnimationPath* animationPath = new osg::AnimationPath;
149 animationPath->setLoopMode(osg::AnimationPath::LOOP);
150
151 int numSamples = 1000;
152 float yaw = 0.0f;
153 float yaw_delta = -2.0f*osg::PI/((float)numSamples-1.0f);
154 float roll = osg::inDegrees(30.0f);
155
156 double time=0.0f;
157 double time_delta = looptime/(double)numSamples;
158 for(int i=0;i<numSamples;++i)
159 {
160 osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
161 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)));
162
163 animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
164
165 yaw += yaw_delta;
166 time += time_delta;
167
168 }
169 return animationPath;
170 }// end createAnimationPath
171
172
173 class SolarSystem
174 {
175
176 public:
177 double _radiusSpace;
178 double _radiusSun;
179 double _radiusMercury;
180 double _radiusVenus;
181 double _radiusEarth;
182 double _radiusMoon;
183 double _radiusMars;
184 double _radiusJupiter;
185
186 double _RorbitMercury;
187 double _RorbitVenus;
188 double _RorbitEarth;
189 double _RorbitMoon;
190 double _RorbitMars;
191 double _RorbitJupiter;
192
193 double _rotateSpeedSun;
194 double _rotateSpeedMercury;
195 double _rotateSpeedVenus;
196 double _rotateSpeedEarthAndMoon;
197 double _rotateSpeedEarth;
198 double _rotateSpeedMoon;
199 double _rotateSpeedMars;
200 double _rotateSpeedJupiter;
201
202 double _tiltEarth;
203
204 std::string _mapSpace;
205 std::string _mapSun;
206 std::string _mapVenus;
207 std::string _mapMercury;
208 std::string _mapEarth;
209 std::string _mapEarthNight;
210 std::string _mapMoon;
211 std::string _mapMars;
212 std::string _mapJupiter;
213
214 double _rotateSpeedFactor;
215 double _RorbitFactor;
216 double _radiusFactor;
217
SolarSystem()218 SolarSystem()
219 {
220 _radiusSpace = 500.0;
221 _radiusSun = 109.0;
222 _radiusMercury = 0.38;
223 _radiusVenus = 0.95;
224 _radiusEarth = 1.0;
225 _radiusMoon = 0.1;
226 _radiusMars = 0.53;
227 _radiusJupiter = 5.0;
228
229 _RorbitMercury = 11.7;
230 _RorbitVenus = 21.6;
231 _RorbitEarth = 30.0;
232 _RorbitMoon = 1.0;
233 _RorbitMars = 45.0;
234 _RorbitJupiter = 156.0;
235
236 // orbital period in days
237 _rotateSpeedSun = 0.0; // should be 11.97; // 30.5 average
238 _rotateSpeedMercury = 4.15; // 87.96
239 _rotateSpeedVenus = 1.62; // 224.70
240 _rotateSpeedEarthAndMoon = 1.0; // 365.25
241 _rotateSpeedEarth = 1.0; //
242 _rotateSpeedMoon = 0.95; //
243 _rotateSpeedMars = 0.53; // 686.98
244 _rotateSpeedJupiter = 0.08; // 4332.71
245
246 _tiltEarth = 23.45; // degrees
247
248 _mapSpace = "Images/spacemap2.jpg";
249 _mapSun = "SolarSystem/sun256128.jpg";
250 _mapMercury = "SolarSystem/mercury256128.jpg";
251 _mapVenus = "SolarSystem/venus256128.jpg";
252 _mapEarth = "Images/land_shallow_topo_2048.jpg";
253 _mapEarthNight = "Images/land_ocean_ice_lights_2048.jpg";
254 _mapMoon = "SolarSystem/moon256128.jpg";
255 _mapMars = "SolarSystem/mars256128.jpg";
256 _mapJupiter = "SolarSystem/jupiter256128.jpg";
257
258 _rotateSpeedFactor = 0.5;
259 _RorbitFactor = 15.0;
260 _radiusFactor = 10.0;
261 }
262
263 osg::MatrixTransform* createTranslationAndTilt( double translation, double tilt );
264 osg::MatrixTransform* createRotation( double orbit, double speed );
265
266 osg::Geode* createSpace( const std::string& name, const std::string& textureName );
267 osg::Geode* createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName );
268 osg::Geode* createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName1, const std::string& textureName2);
269 osg::Group* createSunLight();
270
rotateSpeedCorrection()271 void rotateSpeedCorrection()
272 {
273 _rotateSpeedSun *= _rotateSpeedFactor;
274 _rotateSpeedMercury *= _rotateSpeedFactor;
275 _rotateSpeedVenus *= _rotateSpeedFactor;
276 _rotateSpeedEarthAndMoon *= _rotateSpeedFactor;
277 _rotateSpeedEarth *= _rotateSpeedFactor;
278 _rotateSpeedMoon *= _rotateSpeedFactor;
279 _rotateSpeedMars *= _rotateSpeedFactor;
280 _rotateSpeedJupiter *= _rotateSpeedFactor;
281
282 std::cout << "rotateSpeed corrected by factor " << _rotateSpeedFactor << std::endl;
283 }
284
RorbitCorrection()285 void RorbitCorrection()
286 {
287 _RorbitMercury *= _RorbitFactor;
288 _RorbitVenus *= _RorbitFactor;
289 _RorbitEarth *= _RorbitFactor;
290 _RorbitMoon *= _RorbitFactor;
291 _RorbitMars *= _RorbitFactor;
292 _RorbitJupiter *= _RorbitFactor;
293
294 std::cout << "Rorbits corrected by factor " << _RorbitFactor << std::endl;
295 }
296
radiusCorrection()297 void radiusCorrection()
298 {
299 _radiusSpace *= _radiusFactor;
300 //_radiusSun *= _radiusFactor;
301 _radiusMercury *= _radiusFactor;
302 _radiusVenus *= _radiusFactor;
303 _radiusEarth *= _radiusFactor;
304 _radiusMoon *= _radiusFactor;
305 _radiusMars *= _radiusFactor;
306 _radiusJupiter *= _radiusFactor;
307
308 std::cout << "Radius corrected by factor " << _radiusFactor << std::endl;
309 }
310 void printParameters();
311
312 }; // end SolarSystem
313
314 class FindNamedNodeVisitor : public osg::NodeVisitor
315 {
316 public:
FindNamedNodeVisitor(const std::string & name)317 FindNamedNodeVisitor(const std::string& name):
318 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
319 _name(name) {}
320
apply(osg::Node & node)321 virtual void apply(osg::Node& node)
322 {
323 if (node.getName()==_name)
324 {
325 _foundNodes.push_back(&node);
326 }
327 traverse(node);
328 }
329
330 typedef std::vector< osg::ref_ptr<osg::Node> > NodeList;
331
332 std::string _name;
333 NodeList _foundNodes;
334 };
335
336
createRotation(double orbit,double speed)337 osg::MatrixTransform* SolarSystem::createRotation( double orbit, double speed )
338 {
339 osg::Vec3 center( 0.0, 0.0, 0.0 );
340 float animationLength = 10.0f;
341 osg::AnimationPath* animationPath = createAnimationPath( center, orbit, animationLength );
342
343 osg::MatrixTransform* rotation = new osg::MatrixTransform;
344 rotation->setUpdateCallback( new osg::AnimationPathCallback( animationPath, 0.0f, speed ) );
345
346 return rotation;
347 }// end SolarSystem::createEarthRotation
348
349
createTranslationAndTilt(double,double tilt)350 osg::MatrixTransform* SolarSystem::createTranslationAndTilt( double /*translation*/, double tilt )
351 {
352 osg::MatrixTransform* moonPositioned = new osg::MatrixTransform;
353 moonPositioned->setMatrix(osg::Matrix::translate(osg::Vec3( 0.0, _RorbitMoon, 0.0 ) )*
354 osg::Matrix::scale(1.0, 1.0, 1.0)*
355 osg::Matrix::rotate(osg::inDegrees( tilt ),0.0f,0.0f,1.0f));
356
357 return moonPositioned;
358 }// end SolarSystem::createTranslationAndTilt
359
360
createSpace(const std::string & name,const std::string & textureName)361 osg::Geode* SolarSystem::createSpace( const std::string& name, const std::string& textureName )
362 {
363 osg::Sphere *spaceSphere = new osg::Sphere( osg::Vec3( 0.0, 0.0, 0.0 ), _radiusSpace );
364
365 osg::ShapeDrawable *sSpaceSphere = new osg::ShapeDrawable( spaceSphere );
366
367 if( !textureName.empty() )
368 {
369 osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( textureName );
370 if ( image )
371 {
372 sSpaceSphere->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D( image ), osg::StateAttribute::ON );
373
374 // reset the object color to white to allow the texture to set the colour.
375 sSpaceSphere->setColor( osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
376 }
377 }
378
379 osg::Geode* geodeSpace = new osg::Geode();
380 geodeSpace->setName( name );
381
382 geodeSpace->addDrawable( sSpaceSphere );
383
384 return( geodeSpace );
385
386 }// end SolarSystem::createSpace
387
388
createPlanet(double radius,const std::string & name,const osg::Vec4 & color,const std::string & textureName)389 osg::Geode* SolarSystem::createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName)
390 {
391 // create a container that makes the sphere drawable
392 osg::Geometry *sPlanetSphere = new osg::Geometry();
393
394 {
395 // set the single colour so bind overall
396 osg::Vec4Array* colours = new osg::Vec4Array(1);
397 (*colours)[0] = color;
398 sPlanetSphere->setColorArray(colours, osg::Array::BIND_OVERALL);
399
400
401 // now set up the coords, normals and texcoords for geometry
402 unsigned int numX = 100;
403 unsigned int numY = 50;
404 unsigned int numVertices = numX*numY;
405
406 osg::Vec3Array* coords = new osg::Vec3Array(numVertices);
407 sPlanetSphere->setVertexArray(coords);
408
409 osg::Vec3Array* normals = new osg::Vec3Array(numVertices);
410 sPlanetSphere->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
411
412 osg::Vec2Array* texcoords = new osg::Vec2Array(numVertices);
413 sPlanetSphere->setTexCoordArray(0,texcoords);
414 sPlanetSphere->setTexCoordArray(1,texcoords);
415
416 double delta_elevation = osg::PI / (double)(numY-1);
417 double delta_azim = 2.0*osg::PI / (double)(numX-1);
418 float delta_tx = 1.0 / (float)(numX-1);
419 float delta_ty = 1.0 / (float)(numY-1);
420
421 double elevation = -osg::PI*0.5;
422 float ty = 0.0;
423 unsigned int vert = 0;
424 unsigned j;
425 for(j=0;
426 j<numY;
427 ++j, elevation+=delta_elevation, ty+=delta_ty )
428 {
429 double azim = 0.0;
430 float tx = 0.0;
431 for(unsigned int i=0;
432 i<numX;
433 ++i, ++vert, azim+=delta_azim, tx+=delta_tx)
434 {
435 osg::Vec3 direction(cos(azim)*cos(elevation), sin(azim)*cos(elevation), sin(elevation));
436 (*coords)[vert].set(direction*radius);
437 (*normals)[vert].set(direction);
438 (*texcoords)[vert].set(tx,ty);
439 }
440 }
441
442 for(j=0;
443 j<numY-1;
444 ++j)
445 {
446 unsigned int curr_row = j*numX;
447 unsigned int next_row = curr_row+numX;
448 osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
449 for(unsigned int i=0;
450 i<numX;
451 ++i)
452 {
453 elements->push_back(next_row + i);
454 elements->push_back(curr_row + i);
455 }
456 sPlanetSphere->addPrimitiveSet(elements);
457 }
458 }
459
460
461 // set the object color
462 //sPlanetSphere->setColor( color );
463
464 // create a geode object to as a container for our drawable sphere object
465 osg::Geode* geodePlanet = new osg::Geode();
466 geodePlanet->setName( name );
467
468 if( !textureName.empty() )
469 {
470 osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( textureName );
471 if ( image )
472 {
473 osg::Texture2D* tex2d = new osg::Texture2D( image );
474 tex2d->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
475 tex2d->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
476 geodePlanet->getOrCreateStateSet()->setTextureAttributeAndModes( 0, tex2d, osg::StateAttribute::ON );
477
478 // reset the object color to white to allow the texture to set the colour.
479 //sPlanetSphere->setColor( osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
480 }
481 }
482
483 // add our drawable sphere to the geode container
484 geodePlanet->addDrawable( sPlanetSphere );
485
486 return( geodePlanet );
487
488 }// end SolarSystem::createPlanet
489
createPlanet(double radius,const std::string & name,const osg::Vec4 & color,const std::string & textureName1,const std::string & textureName2)490 osg::Geode* SolarSystem::createPlanet( double radius, const std::string& name, const osg::Vec4& color , const std::string& textureName1, const std::string& textureName2)
491 {
492 osg::Geode* geodePlanet = createPlanet( radius, name, color , textureName1);
493
494 if( !textureName2.empty() )
495 {
496 osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( textureName2 );
497 if ( image )
498 {
499 osg::StateSet* stateset = geodePlanet->getOrCreateStateSet();
500
501 osg::TexEnvCombine* texenv = new osg::TexEnvCombine;
502
503 texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
504 texenv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
505 texenv->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
506 texenv->setSource1_RGB(osg::TexEnvCombine::TEXTURE);
507 texenv->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
508 texenv->setSource2_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
509 texenv->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
510
511 stateset->setTextureAttribute( 1, texenv );
512 osg::Texture2D* tex2d = new osg::Texture2D( image );
513 tex2d->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
514 tex2d->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
515 stateset->setTextureAttributeAndModes( 1, tex2d, osg::StateAttribute::ON );
516 }
517 }
518
519 return( geodePlanet );
520
521 }// end SolarSystem::createPlanet
522
createSunLight()523 osg::Group* SolarSystem::createSunLight()
524 {
525
526 osg::LightSource* sunLightSource = new osg::LightSource;
527
528 osg::Light* sunLight = sunLightSource->getLight();
529 sunLight->setPosition( osg::Vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
530 sunLight->setAmbient( osg::Vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
531
532 sunLightSource->setLight( sunLight );
533 sunLightSource->setLocalStateSetModes( osg::StateAttribute::ON );
534 sunLightSource->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
535
536 osg::LightModel* lightModel = new osg::LightModel;
537 lightModel->setAmbientIntensity(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
538 sunLightSource->getOrCreateStateSet()->setAttribute(lightModel);
539
540
541 return sunLightSource;
542 }// end SolarSystem::createSunLight
543
printParameters()544 void SolarSystem::printParameters()
545 {
546 std::cout << "radiusSpace(" << _radiusSpace << ")" << std::endl;
547 std::cout << "radiusSun(" << _radiusSun << ")" << std::endl;
548 std::cout << "radiusMercury(" << _radiusMercury << ")" << std::endl;
549 std::cout << "radiusVenus(" << _radiusVenus << ")" << std::endl;
550 std::cout << "radiusEarth(" << _radiusEarth << ")" << std::endl;
551 std::cout << "radiusMoon(" << _radiusMoon << ")" << std::endl;
552 std::cout << "radiusMars(" << _radiusMars << ")" << std::endl;
553 std::cout << "radiusJupiter(" << _radiusJupiter << ")" << std::endl;
554
555 std::cout << "RorbitMercury(" << _RorbitMercury << ")" << std::endl;
556 std::cout << "RorbitVenus(" << _RorbitVenus << ")" << std::endl;
557 std::cout << "RorbitEarth(" << _RorbitEarth << ")" << std::endl;
558 std::cout << "RorbitMoon(" << _RorbitMoon << ")" << std::endl;
559 std::cout << "RorbitMars(" << _RorbitMars << ")" << std::endl;
560 std::cout << "RorbitJupiter(" << _RorbitJupiter << ")" << std::endl;
561
562 std::cout << "rotateSpeedMercury(" << _rotateSpeedMercury << ")" << std::endl;
563 std::cout << "rotateSpeedVenus(" << _rotateSpeedVenus << ")" << std::endl;
564 std::cout << "rotateSpeedEarthAndMoon(" << _rotateSpeedEarthAndMoon << ")" << std::endl;
565 std::cout << "rotateSpeedEarth(" << _rotateSpeedEarth << ")" << std::endl;
566 std::cout << "rotateSpeedMoon(" << _rotateSpeedMoon << ")" << std::endl;
567 std::cout << "rotateSpeedMars(" << _rotateSpeedMars << ")" << std::endl;
568 std::cout << "rotateSpeedJupiter(" << _rotateSpeedJupiter << ")" << std::endl;
569
570 std::cout << "tiltEarth(" << _tiltEarth << ")" << std::endl;
571
572 std::cout << "mapSpace(" << _mapSpace << ")" << std::endl;
573 std::cout << "mapSun(" << _mapSun << ")" << std::endl;
574 std::cout << "mapMercury(" << _mapMercury << ")" << std::endl;
575 std::cout << "mapVenus(" << _mapVenus << ")" << std::endl;
576 std::cout << "mapEarth(" << _mapEarth << ")" << std::endl;
577 std::cout << "mapEarthNight(" << _mapEarthNight << ")" << std::endl;
578 std::cout << "mapMoon(" << _mapMoon << ")" << std::endl;
579 std::cout << "mapMars(" << _mapMars << ")" << std::endl;
580 std::cout << "mapJupiter(" << _mapJupiter << ")" << std::endl;
581
582 std::cout << "rotateSpeedFactor(" << _rotateSpeedFactor << ")" << std::endl;
583 std::cout << "RorbitFactor(" << _RorbitFactor << ")" << std::endl;
584 std::cout << "radiusFactor(" << _radiusFactor << ")" << std::endl;
585 }
586
587
main(int argc,char ** argv)588 int main( int argc, char **argv )
589 {
590 // use an ArgumentParser object to manage the program arguments.
591 osg::ArgumentParser arguments(&argc,argv);
592
593 // set up the usage document, in case we need to print out how to use this program.
594 arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of osg::AnimationPath and UpdateCallbacks for adding animation to your scenes.");
595 arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
596 arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
597 arguments.getApplicationUsage()->addCommandLineOption("-o <filename>","Write created model to file");
598
599 // initialize the viewer.
600 osgViewer::Viewer viewer;
601
602 osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
603 viewer.setCameraManipulator( keyswitchManipulator.get() );
604
605 SolarSystem solarSystem;
606
607 while (arguments.read("--radiusSpace",solarSystem._radiusSpace)) { }
608 while (arguments.read("--radiusSun",solarSystem._radiusSun)) { }
609 while (arguments.read("--radiusMercury",solarSystem._radiusMercury)) { }
610 while (arguments.read("--radiusVenus",solarSystem._radiusVenus)) { }
611 while (arguments.read("--radiusEarth",solarSystem._radiusEarth)) { }
612 while (arguments.read("--radiusMoon",solarSystem._radiusMoon)) { }
613 while (arguments.read("--radiusMars",solarSystem._radiusMars)) { }
614 while (arguments.read("--radiusJupiter",solarSystem._radiusJupiter)) { }
615
616 while (arguments.read("--RorbitEarth",solarSystem._RorbitEarth)) { }
617 while (arguments.read("--RorbitMoon",solarSystem._RorbitMoon)) { }
618
619 while (arguments.read("--rotateSpeedEarthAndMoon",solarSystem._rotateSpeedEarthAndMoon)) { }
620 while (arguments.read("--rotateSpeedEarth",solarSystem._rotateSpeedEarth)) { }
621 while (arguments.read("--rotateSpeedMoon",solarSystem._rotateSpeedMoon)) { }
622 while (arguments.read("--tiltEarth",solarSystem._tiltEarth)) { }
623
624 while (arguments.read("--mapSpace",solarSystem._mapSpace)) { }
625 while (arguments.read("--mapEarth",solarSystem._mapEarth)) { }
626 while (arguments.read("--mapEarthNight",solarSystem._mapEarthNight)) { }
627 while (arguments.read("--mapMoon",solarSystem._mapMoon)) { }
628
629 while (arguments.read("--rotateSpeedFactor",solarSystem._rotateSpeedFactor)) { }
630 while (arguments.read("--RorbitFactor",solarSystem._RorbitFactor)) { }
631 while (arguments.read("--radiusFactor",solarSystem._radiusFactor)) { }
632
633 solarSystem.rotateSpeedCorrection();
634 solarSystem.RorbitCorrection();
635 solarSystem.radiusCorrection();
636
637 std::string writeFileName;
638 while (arguments.read("-o",writeFileName)) { }
639
640
641 osgGA::NodeTrackerManipulator::TrackerMode trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
642 std::string mode;
643 while (arguments.read("--tracker-mode",mode))
644 {
645 if (mode=="NODE_CENTER_AND_ROTATION") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
646 else if (mode=="NODE_CENTER_AND_AZIM") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_AZIM;
647 else if (mode=="NODE_CENTER") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER;
648 else
649 {
650 std::cout<<"Unrecognized --tracker-mode option "<<mode<<", valid options are:"<<std::endl;
651 std::cout<<" NODE_CENTER_AND_ROTATION"<<std::endl;
652 std::cout<<" NODE_CENTER_AND_AZIM"<<std::endl;
653 std::cout<<" NODE_CENTER"<<std::endl;
654 return 1;
655 }
656 }
657
658
659 osgGA::NodeTrackerManipulator::RotationMode rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
660 while (arguments.read("--rotation-mode",mode))
661 {
662 if (mode=="TRACKBALL") rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
663 else if (mode=="ELEVATION_AZIM") rotationMode = osgGA::NodeTrackerManipulator::ELEVATION_AZIM;
664 else
665 {
666 std::cout<<"Unrecognized --rotation-mode option "<<mode<<", valid options are:"<<std::endl;
667 std::cout<<" TRACKBALL"<<std::endl;
668 std::cout<<" ELEVATION_AZIM"<<std::endl;
669 return 1;
670 }
671 }
672
673
674 // solarSystem.printParameters();
675
676 // if user request help write it out to cout.
677 if (arguments.read("-h") || arguments.read("--help"))
678 {
679 std::cout << "setup the following arguments: " << std::endl;
680 std::cout << "\t--radiusSpace: double" << std::endl;
681 std::cout << "\t--radiusSun: double" << std::endl;
682 std::cout << "\t--radiusMercury: double" << std::endl;
683 std::cout << "\t--radiusVenus: double" << std::endl;
684 std::cout << "\t--radiusEarth: double" << std::endl;
685 std::cout << "\t--radiusMoon: double" << std::endl;
686 std::cout << "\t--radiusMars: double" << std::endl;
687 std::cout << "\t--radiusJupiter: double" << std::endl;
688
689 std::cout << "\t--RorbitMercury: double" << std::endl;
690 std::cout << "\t--RorbitVenus: double" << std::endl;
691 std::cout << "\t--RorbitEarth: double" << std::endl;
692 std::cout << "\t--RorbitMoon: double" << std::endl;
693 std::cout << "\t--RorbitMars: double" << std::endl;
694 std::cout << "\t--RorbitJupiter: double" << std::endl;
695
696 std::cout << "\t--rotateSpeedMercury: double" << std::endl;
697 std::cout << "\t--rotateSpeedVenus: double" << std::endl;
698 std::cout << "\t--rotateSpeedEarthAndMoon: double" << std::endl;
699 std::cout << "\t--rotateSpeedEarth: double" << std::endl;
700 std::cout << "\t--rotateSpeedMoon: double" << std::endl;
701 std::cout << "\t--rotateSpeedMars: double" << std::endl;
702 std::cout << "\t--rotateSpeedJupiter: double" << std::endl;
703
704 std::cout << "\t--tiltEarth: double" << std::endl;
705
706 std::cout << "\t--mapSpace: string" << std::endl;
707 std::cout << "\t--mapSun: string" << std::endl;
708 std::cout << "\t--mapMercury: string" << std::endl;
709 std::cout << "\t--mapVenus: string" << std::endl;
710 std::cout << "\t--mapEarth: string" << std::endl;
711 std::cout << "\t--mapEarthNight: string" << std::endl;
712 std::cout << "\t--mapMoon: string" << std::endl;
713 std::cout << "\t--mapMars: string" << std::endl;
714 std::cout << "\t--mapJupiter: string" << std::endl;
715
716 std::cout << "\t--rotateSpeedFactor: string" << std::endl;
717 std::cout << "\t--RorbitFactor: string" << std::endl;
718 std::cout << "\t--radiusFactor: string" << std::endl;
719
720 return 1;
721 }
722
723 // any option left unread are converted into errors to write out later.
724 arguments.reportRemainingOptionsAsUnrecognized();
725
726 // report any errors if they have occurred when parsing the program arguments.
727 if (arguments.errors())
728 {
729 arguments.writeErrorMessages(std::cout);
730 return 1;
731 }
732
733
734 osg::Group* root = new osg::Group;
735
736 osg::ClearNode* clearNode = new osg::ClearNode;
737 clearNode->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
738 root->addChild(clearNode);
739
740 osg::Group* sunLight = solarSystem.createSunLight();
741 root->addChild(sunLight);
742
743 // create the sun
744 osg::Node* solarSun = solarSystem.createPlanet( solarSystem._radiusSun, "Sun", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), solarSystem._mapSun );
745 osg::StateSet* sunStateSet = solarSun->getOrCreateStateSet();
746 osg::Material* material = new osg::Material;
747 material->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 0.0f, 0.0f ) );
748 sunStateSet->setAttributeAndModes( material, osg::StateAttribute::ON );
749
750 osg::Billboard* sunBillboard = new osg::Billboard();
751 sunBillboard->setMode(osg::Billboard::POINT_ROT_EYE);
752 sunBillboard->addDrawable(
753 createSquare(osg::Vec3(-150.0f,0.0f,-150.0f),osg::Vec3(300.0f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,300.0f),createBillboardImage( osg::Vec4( 1.0, 1.0, 0, 1.0f), 64, 1.0) ),
754 osg::Vec3(0.0f,0.0f,0.0f));
755
756 sunLight->addChild( sunBillboard );
757
758
759 // stick sun right under root, no transformations for the sun
760 sunLight->addChild( solarSun );
761
762 // create light source in the sun
763
764 /*
765 *********************************************
766 ** earthMoonGroup and Transformations
767 *********************************************
768 */
769 // create earth and moon
770 osg::Node* earth = solarSystem.createPlanet( solarSystem._radiusEarth, "Earth", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), solarSystem._mapEarth, solarSystem._mapEarthNight );
771 osg::Node* moon = solarSystem.createPlanet( solarSystem._radiusMoon, "Moon", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), solarSystem._mapMoon );
772
773 // create transformations for the earthMoonGroup
774 osg::MatrixTransform* aroundSunRotationEarthMoonGroup = solarSystem.createRotation( solarSystem._RorbitEarth, solarSystem._rotateSpeedEarthAndMoon );
775 // osg::MatrixTransform* earthMoonGroupPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitEarth, solarSystem._tiltEarth );
776 osg::MatrixTransform* earthMoonGroupPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitEarth, 0.0 );
777
778
779 //Group with earth and moon under it
780 osg::Group* earthMoonGroup = new osg::Group;
781
782 //transformation to rotate the earth around itself
783 osg::MatrixTransform* earthAroundItselfRotation = solarSystem.createRotation ( 0.0, solarSystem._rotateSpeedEarth );
784
785 //transformations for the moon
786 osg::MatrixTransform* moonAroundEarthRotation = solarSystem.createRotation( solarSystem._RorbitMoon, solarSystem._rotateSpeedMoon );
787 osg::MatrixTransform* moonTranslation = solarSystem.createTranslationAndTilt( solarSystem._RorbitMoon, 0.0 );
788
789
790 moonTranslation->addChild( moon );
791 moonAroundEarthRotation->addChild( moonTranslation );
792 earthMoonGroup->addChild( moonAroundEarthRotation );
793
794 earthAroundItselfRotation->addChild( earth );
795 earthMoonGroup->addChild( earthAroundItselfRotation );
796
797 earthMoonGroupPosition->addChild( earthMoonGroup );
798
799 aroundSunRotationEarthMoonGroup->addChild( earthMoonGroupPosition );
800
801 sunLight->addChild( aroundSunRotationEarthMoonGroup );
802 /*
803 *********************************************
804 ** end earthMoonGroup and Transformations
805 *********************************************
806 */
807
808 /*
809 *********************************************
810 ** Mercury and Transformations
811 *********************************************
812 */
813 osg::Node* mercury = solarSystem.createPlanet( solarSystem._radiusMercury, "Mercury", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ), solarSystem._mapMercury, "" );
814
815 osg::MatrixTransform* aroundSunRotationMercury = solarSystem.createRotation( solarSystem._RorbitMercury, solarSystem._rotateSpeedMercury );
816 osg::MatrixTransform* mercuryPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitMercury, 0.0f );
817
818 mercuryPosition->addChild( mercury );
819 aroundSunRotationMercury->addChild( mercuryPosition );
820
821 sunLight->addChild( aroundSunRotationMercury );
822 /*
823 *********************************************
824 ** end Mercury and Transformations
825 *********************************************
826 */
827
828 /*
829 *********************************************
830 ** Venus and Transformations
831 *********************************************
832 */
833 osg::Node* venus = solarSystem.createPlanet( solarSystem._radiusVenus, "Venus", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ), solarSystem._mapVenus, "" );
834
835 osg::MatrixTransform* aroundSunRotationVenus = solarSystem.createRotation( solarSystem._RorbitVenus, solarSystem._rotateSpeedVenus );
836 osg::MatrixTransform* venusPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitVenus, 0.0f );
837
838 venusPosition->addChild( venus );
839 aroundSunRotationVenus->addChild( venusPosition );
840
841 sunLight->addChild( aroundSunRotationVenus );
842 /*
843 *********************************************
844 ** end Venus and Transformations
845 *********************************************
846 */
847
848 /*
849 *********************************************
850 ** Mars and Transformations
851 *********************************************
852 */
853 osg::Node* mars = solarSystem.createPlanet( solarSystem._radiusMars, "Mars", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ), solarSystem._mapMars, "" );
854
855 osg::MatrixTransform* aroundSunRotationMars = solarSystem.createRotation( solarSystem._RorbitMars, solarSystem._rotateSpeedMars );
856 osg::MatrixTransform* marsPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitMars, 0.0f );
857
858 marsPosition->addChild( mars );
859 aroundSunRotationMars->addChild( marsPosition );
860
861 sunLight->addChild( aroundSunRotationMars );
862 /*
863 *********************************************
864 ** end Mars and Transformations
865 *********************************************
866 */
867
868 /*
869 *********************************************
870 ** Jupiter and Transformations
871 *********************************************
872 */
873 osg::Node* jupiter = solarSystem.createPlanet( solarSystem._radiusJupiter, "Jupiter", osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ), solarSystem._mapJupiter, "" );
874
875 osg::MatrixTransform* aroundSunRotationJupiter = solarSystem.createRotation( solarSystem._RorbitJupiter, solarSystem._rotateSpeedJupiter );
876 osg::MatrixTransform* jupiterPosition = solarSystem.createTranslationAndTilt( solarSystem._RorbitJupiter, 0.0f );
877
878 jupiterPosition->addChild( jupiter );
879 aroundSunRotationJupiter->addChild( jupiterPosition );
880
881 sunLight->addChild( aroundSunRotationJupiter );
882 /*
883 *********************************************
884 ** end Jupiter and Transformations
885 *********************************************
886 */
887
888 /*
889 // add space, but don't light it, as its not illuminated by our sun
890 osg::Node* space = solarSystem.createSpace( "Space", solarSystem._mapSpace );
891 space->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
892 root->addChild( space );
893 */
894
895 if (!writeFileName.empty())
896 {
897 osgDB::writeNodeFile(*root, writeFileName);
898 std::cout<<"Written solar system to \""<<writeFileName<<"\""<<std::endl;
899 return 0;
900 }
901
902
903 // run optimization over the scene graph
904 osgUtil::Optimizer optimzer;
905 optimzer.optimize( root );
906
907 // set the scene to render
908 viewer.setSceneData( root );
909
910
911 // set up tracker manipulators, once for each astral body
912 {
913 FindNamedNodeVisitor fnnv("Moon");
914 root->accept(fnnv);
915
916 if (!fnnv._foundNodes.empty())
917 {
918 // set up the node tracker.
919 osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
920 tm->setTrackerMode( trackerMode );
921 tm->setRotationMode( rotationMode );
922 tm->setTrackNode( fnnv._foundNodes.front().get() );
923
924 unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
925 keyswitchManipulator->addMatrixManipulator( 'm', "moon", tm );
926 keyswitchManipulator->selectMatrixManipulator( num );
927 }
928 }
929
930 {
931 FindNamedNodeVisitor fnnv("Earth");
932 root->accept(fnnv);
933
934 if (!fnnv._foundNodes.empty())
935 {
936 // set up the node tracker.
937 osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
938 tm->setTrackerMode( trackerMode );
939 tm->setRotationMode( rotationMode );
940 tm->setTrackNode( fnnv._foundNodes.front().get() );
941
942 unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
943 keyswitchManipulator->addMatrixManipulator( 'e', "earth", tm);
944 keyswitchManipulator->selectMatrixManipulator( num );
945 }
946 }
947
948 {
949 FindNamedNodeVisitor fnnv("Sun");
950 root->accept(fnnv);
951
952 if (!fnnv._foundNodes.empty())
953 {
954 // set up the node tracker.
955 osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
956 tm->setTrackerMode( trackerMode );
957 tm->setRotationMode( rotationMode );
958 tm->setTrackNode( fnnv._foundNodes.front().get() );
959
960 unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
961 keyswitchManipulator->addMatrixManipulator( 's', "sun", tm);
962 keyswitchManipulator->selectMatrixManipulator( num );
963 }
964 }
965
966 return viewer.run();
967
968 }// end main
969
970