3
* Copyright (C) 2002 Fabien Chereau
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
#include "SolarSystem.hpp"
25
#include "STexture.hpp"
26
#include "stellplanet.h"
28
#include "InitParser.hpp"
29
#include "Navigator.hpp"
30
#include "Projector.hpp"
31
#include "StelApp.hpp"
32
#include "StelCore.hpp"
33
#include "StelTextureMgr.hpp"
34
#include "StelObjectMgr.hpp"
35
#include "StelFontMgr.hpp"
36
#include "StelLocaleMgr.hpp"
37
#include "StelSkyCultureMgr.hpp"
38
#include "StelFileMgr.hpp"
39
#include "StelModuleMgr.hpp"
41
#include <QTextStream>
45
SolarSystem::SolarSystem()
46
:sun(NULL),moon(NULL),earth(NULL),selected(NULL),
47
moonScale(1.), fontSize(14.),
48
planet_name_font(StelApp::getInstance().getFontManager().getStandardFont(StelApp::getInstance().getLocaleMgr().getAppLanguage(), fontSize)),
49
flagOrbits(false),flag_light_travel_time(false), lastHomePlanet(NULL)
51
setObjectName("SolarSystem");
54
void SolarSystem::setFontSize(float newFontSize)
56
planet_name_font = StelApp::getInstance().getFontManager().getStandardFont(StelApp::getInstance().getLocaleMgr().getSkyLanguage(), fontSize);
59
SolarSystem::~SolarSystem()
63
for(vector<Planet*>::iterator iter = system_planets.begin(); iter != system_planets.end(); ++iter)
65
if (*iter) delete *iter;
68
for(vector<Orbit*>::iterator iter = orbits.begin(); iter != orbits.end(); ++iter)
70
if (*iter) delete *iter;
78
/*************************************************************************
79
Reimplementation of the getCallOrder method
80
*************************************************************************/
81
double SolarSystem::getCallOrder(StelModuleActionName actionName) const
83
if (actionName==StelModule::ACTION_DRAW)
84
return StelApp::getInstance().getModuleMgr().getModule("StarMgr")->getCallOrder(actionName)+10;
88
// Init and load the solar system data
89
void SolarSystem::init(const InitParser& conf)
91
loadPlanets(); // Load planets data
93
// Compute position and matrix of sun and all the satellites (ie planets)
94
// for the first initialization assert that center is sun center (only impacts on light speed correction)
95
computePositions(StelUtils::getJDFromSystem());
96
setSelected(""); // Fix a bug on macosX! Thanks Fumio!
97
setScale(conf.get_double ("stars:star_scale")); // if reload config
98
setFlagMoonScale(conf.get_boolean("viewing", "flag_moon_scaled", conf.get_boolean("viewing", "flag_init_moon_scaled", false))); // name change
99
setMoonScale(conf.get_double ("viewing","moon_scale",5.));
100
setFlagPlanets(conf.get_boolean("astro:flag_planets"));
101
setFlagHints(conf.get_boolean("astro:flag_planets_hints"));
102
setFlagOrbits(conf.get_boolean("astro:flag_planets_orbits"));
103
setFlagLightTravelTime(conf.get_boolean("astro:flag_light_travel_time"));
104
setFlagTrails(conf.get_boolean("astro", "flag_object_trails", false));
105
startTrails(conf.get_boolean("astro", "flag_object_trails", false));
107
StelApp::getInstance().getStelObjectMgr().registerStelObjectMgr(this);
108
texPointer = StelApp::getInstance().getTextureManager().createTexture("pointeur4.png");
111
void SolarSystem::drawPointer(const Projector* prj, const Navigator * nav)
113
const std::vector<StelObjectP> newSelected = StelApp::getInstance().getStelObjectMgr().getSelectedObject("Planet");
114
if (!newSelected.empty())
116
const StelObjectP obj = newSelected[0];
117
Vec3d pos=obj->getObsJ2000Pos(nav);
119
prj->setCurrentFrame(Projector::FRAME_J2000);
120
// Compute 2D pos and return if outside screen
121
if (!prj->project(pos, screenpos)) return;
123
glColor3f(1.0f,0.3f,0.3f);
125
float size = obj->getOnScreenSize(prj, nav);
126
size+=26.f + 10.f*std::sin(2.f * StelApp::getInstance().getTotalRunTime());
130
glEnable(GL_TEXTURE_2D);
132
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode
135
glTranslatef(screenpos[0], screenpos[1], 0.0f);
136
glRotatef(StelApp::getInstance().getTotalRunTime()*10.,0,0,-1);
138
glTranslatef(-size/2, -size/2,0.0f);
141
glTexCoord2f(0.0f,0.0f); glVertex3f(-10,-10,0); //Bas Gauche
142
glTexCoord2f(1.0f,0.0f); glVertex3f(10,-10,0); //Bas Droite
143
glTexCoord2f(1.0f,1.0f); glVertex3f(10,10,0); //Haut Droit
144
glTexCoord2f(0.0f,1.0f); glVertex3f(-10,10,0); //Haut Gauche
147
glRotatef(-90,0,0,1);
148
glTranslatef(0,size,0.0f);
150
glTexCoord2f(0.0f,0.0f); glVertex3f(-10,-10,0); //Bas Gauche
151
glTexCoord2f(1.0f,0.0f); glVertex3f(10,-10,0); //Bas Droite
152
glTexCoord2f(1.0f,1.0f); glVertex3f(10,10,0); //Haut Droit
153
glTexCoord2f(0.0f,1.0f); glVertex3f(-10,10,0); //Haut Gauche
156
glRotatef(-90,0,0,1);
157
glTranslatef(0, size,0.0f);
159
glTexCoord2f(0.0f,0.0f); glVertex3f(-10,-10,0); //Bas Gauche
160
glTexCoord2f(1.0f,0.0f); glVertex3f(10,-10,0); //Bas Droite
161
glTexCoord2f(1.0f,1.0f); glVertex3f(10,10,0); //Haut Droit
162
glTexCoord2f(0.0f,1.0f); glVertex3f(-10,10,0); //Haut Gauche
165
glRotatef(-90,0,0,1);
166
glTranslatef(0,size,0);
168
glTexCoord2f(0.0f,0.0f); glVertex3f(-10,-10,0); //Bas Gauche
169
glTexCoord2f(1.0f,0.0f); glVertex3f(10,-10,0); //Bas Droite
170
glTexCoord2f(1.0f,1.0f); glVertex3f(10,10,0); //Haut Droit
171
glTexCoord2f(0.0f,1.0f); glVertex3f(-10,10,0); //Haut Gauche
177
// Init and load the solar system data
178
void SolarSystem::loadPlanets()
180
cout << "Loading Solar System data...";
181
InitParser pd; // The Planet data ini file parser
184
pd.load(StelApp::getInstance().getFileMgr().findFile("data/ssystem.ini"));
188
cerr << "ERROR while loading ssysyem.ini: " << e.what() << endl;
192
int nbSections = pd.get_nsec();
193
for (int i = 0;i<nbSections;++i)
195
const string secname = pd.get_secname(i);
196
const string englishName = pd.get_str(secname, "name");
198
const string str_parent = pd.get_str(secname, "parent");
199
Planet *parent = NULL;
201
if (str_parent!="none")
203
// Look in the other planets the one named with str_parent
204
vector<Planet*>::iterator iter = system_planets.begin();
205
while (iter != system_planets.end())
207
if ((*iter)->getEnglishName()==str_parent)
215
cout << "ERROR : can't find parent for " << englishName << endl;
220
const string funcname = pd.get_str(secname, "coord_func");
221
pos_func_type posfunc;
222
OsulatingFunctType *osculating_func = 0;
223
bool close_orbit = pd.get_boolean(secname, "close_orbit", 1);
225
if (funcname=="ell_orbit")
227
// Read the orbital elements
228
const double epoch = pd.get_double(secname, "orbit_Epoch",J2000);
229
const double eccentricity = pd.get_double(secname, "orbit_Eccentricity");
230
if (eccentricity >= 1.0) close_orbit = false;
231
double pericenter_distance = pd.get_double(secname,"orbit_PericenterDistance",-1e100);
232
double semi_major_axis;
233
if (pericenter_distance <= 0.0) {
234
semi_major_axis = pd.get_double(secname,"orbit_SemiMajorAxis",-1e100);
235
if (semi_major_axis <= -1e100) {
236
cerr << "ERROR: " << englishName
237
<< ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis"
241
semi_major_axis /= AU;
242
assert(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
243
pericenter_distance = semi_major_axis * (1.0-eccentricity);
246
pericenter_distance /= AU;
247
semi_major_axis = (eccentricity == 1.0)
248
? 0.0 // parabolic orbits have no semi_major_axis
249
: pericenter_distance / (1.0-eccentricity);
251
double mean_motion = pd.get_double(secname,"orbit_MeanMotion",-1e100);
253
if (mean_motion <= -1e100) {
254
period = pd.get_double(secname,"orbit_Period",-1e100);
255
if (period <= -1e100) {
256
mean_motion = (eccentricity == 1.0)
257
? 0.01720209895 * (1.5/pericenter_distance)
258
* sqrt(0.5/pericenter_distance)
259
: (semi_major_axis > 0.0)
260
? 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis))
261
: 0.01720209895 / (-semi_major_axis*sqrt(-semi_major_axis));
262
period = 2.0*M_PI/mean_motion;
264
mean_motion = 2.0*M_PI/period;
267
period = 2.0*M_PI/mean_motion;
269
const double inclination = pd.get_double(secname, "orbit_Inclination")*(M_PI/180.0);
270
const double ascending_node = pd.get_double(secname, "orbit_AscendingNode")*(M_PI/180.0);
271
double arg_of_pericenter = pd.get_double(secname,"orbit_ArgOfPericenter",-1e100);
272
double long_of_pericenter;
273
if (arg_of_pericenter <= -1e100) {
274
long_of_pericenter = pd.get_double(secname,"orbit_LongOfPericenter")*(M_PI/180.0);
275
arg_of_pericenter = long_of_pericenter - ascending_node;
277
arg_of_pericenter *= (M_PI/180.0);
278
long_of_pericenter = arg_of_pericenter + ascending_node;
280
double mean_anomaly = pd.get_double(secname,"orbit_MeanAnomaly",-1e100);
281
double mean_longitude;
282
if (mean_anomaly <= -1e100) {
283
mean_longitude = pd.get_double(secname, "orbit_MeanLongitude")*(M_PI/180.0);
284
mean_anomaly = mean_longitude - long_of_pericenter;
286
mean_anomaly *= (M_PI/180.0);
287
mean_longitude = mean_anomaly + long_of_pericenter;
290
// when the parent is the sun use ecliptic rathe than sun equator:
291
const double parent_rot_obliquity = parent->get_parent()
292
? parent->getRotObliquity()
294
const double parent_rot_asc_node = parent->get_parent()
295
? parent->getRotAscendingnode()
297
// Create an elliptical orbit
298
EllipticalOrbit *orb = new EllipticalOrbit(pericenter_distance,
306
parent_rot_obliquity,
307
parent_rot_asc_node);
308
orbits.push_back(orb);
310
posfunc = pos_func_type(orb, &EllipticalOrbit::positionAtTimevInVSOP87Coordinates);
312
if (funcname=="comet_orbit")
314
// Read the orbital elements
315
const double eccentricity = pd.get_double(secname,"orbit_Eccentricity",0.0);
316
if (eccentricity >= 1.0) close_orbit = false;
317
double pericenter_distance = pd.get_double(secname,"orbit_PericenterDistance",-1e100);
318
double semi_major_axis;
319
if (pericenter_distance <= 0.0) {
320
semi_major_axis = pd.get_double(secname,"orbit_SemiMajorAxis",-1e100);
321
if (semi_major_axis <= -1e100) {
322
cerr << "ERROR: " << englishName
323
<< ": you must provide orbit_PericenterDistance or orbit_SemiMajorAxis"
327
assert(eccentricity != 1.0); // parabolic orbits have no semi_major_axis
328
pericenter_distance = semi_major_axis * (1.0-eccentricity);
331
semi_major_axis = (eccentricity == 1.0)
332
? 0.0 // parabolic orbits have no semi_major_axis
333
: pericenter_distance / (1.0-eccentricity);
335
double mean_motion = pd.get_double(secname,"orbit_MeanMotion",-1e100);
337
if (mean_motion <= -1e100) {
338
period = pd.get_double(secname,"orbit_Period",-1e100);
339
if (period <= -1e100) {
340
mean_motion = (eccentricity == 1.0)
341
? 0.01720209895 * (1.5/pericenter_distance)
342
* sqrt(0.5/pericenter_distance)
343
: (semi_major_axis > 0.0)
344
? 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis))
345
: 0.01720209895 / (-semi_major_axis*sqrt(-semi_major_axis));
346
period = 2.0*M_PI/mean_motion;
348
mean_motion = 2.0*M_PI/period;
351
period = 2.0*M_PI/mean_motion;
353
double time_at_pericenter = pd.get_double(secname,"orbit_TimeAtPericenter",-1e100);
354
if (time_at_pericenter <= -1e100) {
355
const double epoch = pd.get_double(secname,"orbit_Epoch",-1e100);
356
double mean_anomaly = pd.get_double(secname,"orbit_MeanAnomaly",-1e100);
357
if (epoch <= -1e100 || mean_anomaly <= -1e100) {
358
cerr << "ERROR: " << englishName
359
<< ": when you do not provide orbit_TimeAtPericenter, you must provide both "
360
"orbit_Epoch and orbit_MeanAnomaly"
364
mean_anomaly *= (M_PI/180.0);
365
const double mean_motion = 0.01720209895 / (semi_major_axis*sqrt(semi_major_axis));
366
time_at_pericenter = epoch - mean_anomaly / mean_motion;
369
const double inclination = pd.get_double(secname,"orbit_Inclination")*(M_PI/180.0);
370
const double ascending_node = pd.get_double(secname,"orbit_AscendingNode")*(M_PI/180.0);
371
const double arg_of_pericenter = pd.get_double(secname,"orbit_ArgOfPericenter")*(M_PI/180.0);
372
CometOrbit *orb = new CometOrbit(pericenter_distance,
379
orbits.push_back(orb);
381
posfunc = pos_func_type(orb,&CometOrbit::positionAtTimevInVSOP87Coordinates);
384
if (funcname=="sun_special")
385
posfunc = pos_func_type(get_sun_helio_coordsv);
387
if (funcname=="mercury_special") {
388
posfunc = pos_func_type(get_mercury_helio_coordsv);
389
osculating_func = &get_mercury_helio_osculating_coords;
392
if (funcname=="venus_special") {
393
posfunc = pos_func_type(get_venus_helio_coordsv);
394
osculating_func = &get_venus_helio_osculating_coords;
397
if (funcname=="earth_special") {
398
posfunc = pos_func_type(get_earth_helio_coordsv);
399
osculating_func = &get_earth_helio_osculating_coords;
402
if (funcname=="lunar_special")
403
posfunc = pos_func_type(get_lunar_parent_coordsv);
405
if (funcname=="mars_special") {
406
posfunc = pos_func_type(get_mars_helio_coordsv);
407
osculating_func = &get_mars_helio_osculating_coords;
410
if (funcname=="phobos_special")
411
posfunc = pos_func_type(get_phobos_parent_coordsv);
413
if (funcname=="deimos_special")
414
posfunc = pos_func_type(get_deimos_parent_coordsv);
416
if (funcname=="jupiter_special") {
417
posfunc = pos_func_type(get_jupiter_helio_coordsv);
418
osculating_func = &get_jupiter_helio_osculating_coords;
421
if (funcname=="europa_special")
422
posfunc = pos_func_type(get_europa_parent_coordsv);
424
if (funcname=="calisto_special")
425
posfunc = pos_func_type(get_callisto_parent_coordsv);
427
if (funcname=="io_special")
428
posfunc = pos_func_type(get_io_parent_coordsv);
430
if (funcname=="ganymede_special")
431
posfunc = pos_func_type(get_ganymede_parent_coordsv);
433
if (funcname=="saturn_special") {
434
posfunc = pos_func_type(get_saturn_helio_coordsv);
435
osculating_func = &get_saturn_helio_osculating_coords;
438
if (funcname=="mimas_special")
439
posfunc = pos_func_type(get_mimas_parent_coordsv);
441
if (funcname=="enceladus_special")
442
posfunc = pos_func_type(get_enceladus_parent_coordsv);
444
if (funcname=="tethys_special")
445
posfunc = pos_func_type(get_tethys_parent_coordsv);
447
if (funcname=="dione_special")
448
posfunc = pos_func_type(get_dione_parent_coordsv);
450
if (funcname=="rhea_special")
451
posfunc = pos_func_type(get_rhea_parent_coordsv);
453
if (funcname=="titan_special")
454
posfunc = pos_func_type(get_titan_parent_coordsv);
456
if (funcname=="iapetus_special")
457
posfunc = pos_func_type(get_iapetus_parent_coordsv);
459
if (funcname=="hyperion_special")
460
posfunc = pos_func_type(get_hyperion_parent_coordsv);
462
if (funcname=="uranus_special") {
463
posfunc = pos_func_type(get_uranus_helio_coordsv);
464
osculating_func = &get_uranus_helio_osculating_coords;
467
if (funcname=="miranda_special")
468
posfunc = pos_func_type(get_miranda_parent_coordsv);
470
if (funcname=="ariel_special")
471
posfunc = pos_func_type(get_ariel_parent_coordsv);
473
if (funcname=="umbriel_special")
474
posfunc = pos_func_type(get_umbriel_parent_coordsv);
476
if (funcname=="titania_special")
477
posfunc = pos_func_type(get_titania_parent_coordsv);
479
if (funcname=="oberon_special")
480
posfunc = pos_func_type(get_oberon_parent_coordsv);
482
if (funcname=="neptune_special") {
483
posfunc = pos_func_type(get_neptune_helio_coordsv);
484
osculating_func = &get_neptune_helio_osculating_coords;
487
if (funcname=="pluto_special")
488
posfunc = pos_func_type(get_pluto_helio_coordsv);
493
cout << "ERROR : can't find posfunc " << funcname << " for " << englishName << endl;
497
// Create the Planet and add it to the list
498
Planet* p = new Planet(parent,
500
pd.get_boolean(secname, "halo"),
501
pd.get_boolean(secname, "lighting"),
502
pd.get_double(secname, "radius")/AU,
503
pd.get_double(secname, "oblateness", 0.0),
504
StelUtils::str_to_vec3f(pd.get_str(secname, "color").c_str()),
505
pd.get_double(secname, "albedo"),
506
pd.get_str(secname, "tex_map").c_str(),
507
pd.get_str(secname, "tex_halo").c_str(),
508
posfunc,osculating_func,
510
pd.get_boolean(secname, "hidden", 0));
512
if (secname=="earth") earth = p;
513
if (secname=="sun") sun = p;
514
if (secname=="moon") moon = p;
516
p->set_rotation_elements(
517
pd.get_double(secname, "rot_periode", pd.get_double(secname, "orbit_Period", 24.))/24.,
518
pd.get_double(secname, "rot_rotation_offset",0.),
519
pd.get_double(secname, "rot_epoch", J2000),
520
pd.get_double(secname, "rot_obliquity",0.)*(M_PI/180.0),
521
pd.get_double(secname, "rot_equator_ascending_node",0.)*(M_PI/180.0),
522
pd.get_double(secname, "rot_precession_rate",0.)*M_PI/(180*36525),
523
pd.get_double(secname, "sidereal_period",0.) );
526
if (pd.get_boolean(secname, "rings", 0)) {
527
const double r_min = pd.get_double(secname, "ring_inner_size")/AU;
528
const double r_max = pd.get_double(secname, "ring_outer_size")/AU;
529
Ring *r = new Ring(r_min,r_max,pd.get_str(secname, "tex_ring").c_str());
533
QString bighalotexfile = pd.get_str(secname, "tex_big_halo", "").c_str();
534
if (!bighalotexfile.isEmpty())
536
p->set_big_halo(bighalotexfile);
537
p->set_halo_size(pd.get_double(secname, "big_halo_size", 50.f));
540
system_planets.push_back(p);
543
// special case: load earth shadow texture
544
StelApp::getInstance().getTextureManager().setDefaultParams();
545
tex_earth_shadow = StelApp::getInstance().getTextureManager().createTexture("earth-shadow.png");
547
cout << "(loaded)" << endl;
550
// Compute the position for every elements of the solar system.
551
// The order is not important since the position is computed relatively to the mother body
552
void SolarSystem::computePositions(double date, const Vec3d& observerPos) {
553
if (flag_light_travel_time) {
554
for (vector<Planet*>::const_iterator iter(system_planets.begin());
555
iter!=system_planets.end();iter++) {
556
(*iter)->computePositionWithoutOrbits(date);
558
for (vector<Planet*>::const_iterator iter(system_planets.begin());
559
iter!=system_planets.end();iter++) {
560
const double light_speed_correction =
561
((*iter)->get_heliocentric_ecliptic_pos()-observerPos).length()
562
* (AU / (SPEED_OF_LIGHT * 86400));
563
(*iter)->compute_position(date-light_speed_correction);
566
for (vector<Planet*>::const_iterator iter(system_planets.begin());
567
iter!=system_planets.end();iter++) {
568
(*iter)->compute_position(date);
572
computeTransMatrices(date, observerPos);
575
// Compute the transformation matrix for every elements of the solar system.
576
// The elements have to be ordered hierarchically, eg. it's important to compute earth before moon.
577
void SolarSystem::computeTransMatrices(double date, const Vec3d& observerPos) {
578
if (flag_light_travel_time) {
579
for (vector<Planet*>::const_iterator iter(system_planets.begin());
580
iter!=system_planets.end();iter++) {
581
const double light_speed_correction =
582
((*iter)->get_heliocentric_ecliptic_pos()-observerPos).length()
583
* (AU / (SPEED_OF_LIGHT * 86400));
584
(*iter)->compute_trans_matrix(date-light_speed_correction);
587
for (vector<Planet*>::const_iterator iter(system_planets.begin());
588
iter!=system_planets.end();iter++) {
589
(*iter)->compute_trans_matrix(date);
594
// Draw all the elements of the solar system
595
// We are supposed to be in heliocentric coordinate
596
double SolarSystem::draw(StelCore* core)
598
if(!Planet::getflagShow())
601
Navigator* nav = core->getNavigation();
602
Projector* prj = core->getProjection();
603
ToneReproducer* eye = core->getToneReproducer();
605
Planet::set_font(&planet_name_font);
607
// Set the light parameters taking sun as the light source
608
const float zero[4] = {0,0,0,0};
609
const float ambient[4] = {0.02,0.02,0.02,0.02};
610
const float diffuse[4] = {1,1,1,1};
611
glLightfv(GL_LIGHT0,GL_AMBIENT, ambient);
612
glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse);
613
glLightfv(GL_LIGHT0,GL_SPECULAR,zero);
615
glMaterialfv(GL_FRONT,GL_AMBIENT, ambient);
616
glMaterialfv(GL_FRONT,GL_DIFFUSE, diffuse);
617
glMaterialfv(GL_FRONT,GL_EMISSION, zero);
618
glMaterialfv(GL_FRONT,GL_SHININESS,zero);
619
glMaterialfv(GL_FRONT,GL_SPECULAR, zero);
621
// Light pos in zero (sun)
622
//nav->switchToHeliocentric();
623
glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(0.f,0.f,0.f,1.f));
626
// Compute each Planet distance to the observer
627
Vec3d obs_helio_pos = nav->getObserverHelioPos();
629
vector<Planet*>::iterator iter;
630
iter = system_planets.begin();
631
while (iter != system_planets.end())
633
(*iter)->compute_distance(obs_helio_pos);
637
// And sort them from the furthest to the closest
638
sort(system_planets.begin(),system_planets.end(),bigger_distance());
641
double maxSquaredDistance = 0;
642
iter = system_planets.begin();
643
while (iter != system_planets.end())
645
double squaredDistance = 0;
646
if(*iter==moon && near_lunar_eclipse(nav, prj))
648
// TODO: moon magnitude label during eclipse isn't accurate...
650
// special case to update stencil buffer for drawing lunar eclipses
651
glClear(GL_STENCIL_BUFFER_BIT);
654
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
655
glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
657
squaredDistance = (*iter)->draw(prj, nav, eye, 1);
661
squaredDistance = (*iter)->draw(prj, nav, eye, 0);
663
if (squaredDistance > maxSquaredDistance)
664
maxSquaredDistance = squaredDistance;
669
glDisable(GL_LIGHT0);
672
// special case: draw earth shadow over moon if appropriate
673
// stencil buffer is set up in moon drawing above
674
// This effect curently only looks right from earth viewpoint
675
if(nav->getHomePlanet()->getEnglishName() == "Earth")
676
draw_earth_shadow(nav, prj);
678
drawPointer(prj, nav);
680
return maxSquaredDistance;
683
void SolarSystem::setColorScheme(const InitParser& conf, const QString& section)
685
// Load colors from config file
686
string defaultColor = conf.get_str(section.toStdString(),"default_color");
687
setNamesColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"planet_names_color", defaultColor)));
688
setOrbitsColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"planet_orbits_color", defaultColor)));
689
setTrailsColor(StelUtils::str_to_vec3f(conf.get_str(section.toStdString(),"object_trails_color", defaultColor)));
692
Planet* SolarSystem::searchByEnglishName(string planetEnglishName) const
694
//printf("SolarSystem::searchByEnglishName(\"%s\"): start\n",
695
// planetEnglishName.c_str());
696
// side effect - bad?
697
// transform(planetEnglishName.begin(), planetEnglishName.end(), planetEnglishName.begin(), ::tolower);
699
vector<Planet*>::const_iterator iter = system_planets.begin();
700
while (iter != system_planets.end())
702
//printf("SolarSystem::searchByEnglishName(\"%s\"): %s\n",
703
// planetEnglishName.c_str(),
704
// (*iter)->getEnglishName().c_str());
705
if( (*iter)->getEnglishName() == planetEnglishName ) return (*iter); // also check standard ini file names
708
//printf("SolarSystem::searchByEnglishName(\"%s\"): not found\n",
709
// planetEnglishName.c_str());
713
StelObjectP SolarSystem::searchByNameI18n(const wstring& planetNameI18) const
715
vector<Planet*>::const_iterator iter = system_planets.begin();
716
while (iter != system_planets.end())
718
if( (*iter)->getNameI18n() == planetNameI18 ) return (*iter); // also check standard ini file names
725
StelObjectP SolarSystem::searchByName(const string& name) const
727
vector<Planet*>::const_iterator iter = system_planets.begin();
728
while (iter != system_planets.end())
730
if( (*iter)->getEnglishName() == name ) return (*iter);
736
// Search if any Planet is close to position given in earth equatorial position and return the distance
737
StelObject* SolarSystem::search(Vec3d pos, const StelCore* core) const
740
Planet * closest = NULL;
741
double cos_angle_closest = 0.;
744
vector<Planet*>::const_iterator iter = system_planets.begin();
745
while (iter != system_planets.end())
747
equPos = (*iter)->getEarthEquatorialPos(core->getNavigation());
749
double cos_ang_dist = equPos[0]*pos[0] + equPos[1]*pos[1] + equPos[2]*pos[2];
750
if (cos_ang_dist>cos_angle_closest)
753
cos_angle_closest = cos_ang_dist;
758
if (cos_angle_closest>0.999)
765
// Return a stl vector containing the planets located inside the lim_fov circle around position v
766
vector<StelObjectP> SolarSystem::searchAround(const Vec3d& vv, double limitFov, const StelCore* core) const
768
vector<StelObjectP> result;
769
if (!getFlagPlanets())
772
Vec3d v = core->getNavigation()->j2000_to_earth_equ(vv);
774
double cos_lim_fov = cos(limitFov * M_PI/180.);
777
vector<Planet*>::const_iterator iter = system_planets.begin();
778
while (iter != system_planets.end())
780
equPos = (*iter)->getEarthEquatorialPos(core->getNavigation());
782
if (equPos[0]*v[0] + equPos[1]*v[1] + equPos[2]*v[2]>=cos_lim_fov)
784
result.push_back(*iter);
791
// Update i18 names from english names according to passed translator
792
void SolarSystem::updateI18n()
794
Translator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
795
vector<Planet*>::iterator iter;
796
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
798
(*iter)->translateName(trans);
800
planet_name_font = StelApp::getInstance().getFontManager().getStandardFont(trans.getTrueLocaleName(), fontSize);
803
vector<wstring> SolarSystem::getNamesI18(void)
805
vector<wstring> names;
806
vector < Planet * >::iterator iter;
808
for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
809
names.push_back((*iter)->getNameI18n());
813
wstring SolarSystem::getPlanetHashString(void)
816
QTextStream oss(&str);
818
vector <Planet *>::iterator iter;
819
for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
821
if((*iter)->get_parent() != NULL && (*iter)->get_parent()->getEnglishName() != "Sun")
823
oss << q_((*iter)->get_parent()->getEnglishName().c_str()) << " : ";
826
oss << q_((*iter)->getEnglishName().c_str()) << endl;
827
oss << (*iter)->getEnglishName().c_str() << endl;
829
return str.toStdWString();
832
void SolarSystem::startTrails(bool b)
834
vector<Planet*>::iterator iter;
835
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
837
(*iter)->startTrail(b);
841
void SolarSystem::setFlagTrails(bool b)
843
vector<Planet*>::iterator iter;
844
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
846
(*iter)->setFlagTrail(b);
850
bool SolarSystem::getFlagTrails(void) const
852
for (vector<Planet*>::const_iterator iter = system_planets.begin();
853
iter != system_planets.end(); iter++ ) {
854
if ((*iter)->getFlagTrail()) return true;
859
void SolarSystem::setFlagHints(bool b)
861
vector<Planet*>::iterator iter;
862
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
864
(*iter)->setFlagHints(b);
868
bool SolarSystem::getFlagHints(void) const
870
for (vector<Planet*>::const_iterator iter = system_planets.begin();
871
iter != system_planets.end(); iter++ ) {
872
if ((*iter)->getFlagHints()) return true;
877
void SolarSystem::setFlagOrbits(bool b)
880
if (!b || !selected || selected == sun)
882
vector<Planet*>::iterator iter;
883
for( iter = system_planets.begin(); iter < system_planets.end(); iter++ )
885
(*iter)->setFlagOrbits(b);
890
// if a Planet is selected and orbits are on,
891
// fade out non-selected ones
892
vector<Planet*>::iterator iter;
893
for (iter = system_planets.begin();
894
iter != system_planets.end(); iter++ )
896
if (selected == (*iter)) (*iter)->setFlagOrbits(b);
897
else (*iter)->setFlagOrbits(false);
903
void SolarSystem::setSelected(StelObject* obj)
905
if (obj && obj->getType() == "Planet")
909
// Undraw other objects hints, orbit, trails etc..
910
setFlagHints(getFlagHints());
911
setFlagOrbits(getFlagOrbits());
912
setFlagTrails(getFlagTrails());
915
// draws earth shadow overlapping the moon using stencil buffer
916
// umbra and penumbra are sized separately for accuracy
917
void SolarSystem::draw_earth_shadow(const Navigator * nav, Projector * prj)
920
Vec3d e = getEarth()->get_ecliptic_pos();
921
Vec3d m = getMoon()->get_ecliptic_pos(); // relative to earth
922
Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos(); // relative to sun
923
float mscale = getMoon()->get_sphere_scale();
925
// shadow location at earth + moon distance along earth vector from sun
928
Vec3d shadow = en * (e.length() + m.length());
931
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
934
// find shadow radii in AU
935
double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
936
double r_umbra = 6378.1/AU - m.length()*(689621.9/AU/e.length());
938
// find vector orthogonal to sun-earth vector using cross product with
939
// a non-parallel vector
940
Vec3d rpt = shadow^Vec3d(0,0,1);
942
Vec3d upt = rpt*r_umbra*mscale*1.02; // point on umbra edge
943
rpt *= r_penumbra*mscale; // point on penumbra edge
945
// modify shadow location for scaled moon
946
Vec3d mdist = shadow - mh;
947
if(mdist.length() > r_penumbra + 2000/AU) return; // not visible so don't bother drawing
949
shadow = mh + mdist*mscale;
950
r_penumbra *= mscale;
952
//nav->switchToHeliocentric();
953
glEnable(GL_STENCIL_TEST);
954
glStencilFunc(GL_EQUAL, 0x1, 0x1);
955
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
957
prj->setCurrentFrame(Projector::FRAME_HELIO);
958
// shadow radial texture
959
tex_earth_shadow->bind();
964
glBegin(GL_TRIANGLE_FAN);
965
// johannes: work-around for nasty ATI rendering bug:
966
// use y-texture coordinate of 0.5 instead of 0.0
967
glTexCoord2f(0.f,0.5f);
968
prj->drawVertex3v(shadow);
970
for (int i=0; i<=100; i++)
972
r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
975
glTexCoord2f(0.6f,0.5f); // position in texture of umbra edge
976
prj->drawVertex3v(s);
983
glBegin(GL_TRIANGLE_STRIP);
984
for (int i=0; i<=100; i++)
986
r = Mat4d::rotation(shadow, 2*M_PI*i/100.) * rpt;
987
u = Mat4d::rotation(shadow, 2*M_PI*i/100.) * upt;
991
glTexCoord2f(0.6f,0.5f);
992
prj->drawVertex3v(sp);
994
glTexCoord2f(1.f,0.5f); // position in texture of umbra edge
995
prj->drawVertex3v(s);
999
glDisable(GL_STENCIL_TEST);
1004
void SolarSystem::update(double delta_time)
1006
bool restartTrails = false;
1007
Navigator* nav = StelApp::getInstance().getCore()->getNavigation();
1009
// Determine if home planet has changed, and restart planet trails
1010
// since the data is no longer useful
1011
if(nav->getHomePlanet() != lastHomePlanet) {
1012
lastHomePlanet = nav->getHomePlanet();
1013
restartTrails = true;
1016
vector<Planet*>::iterator iter = system_planets.begin();
1017
while (iter != system_planets.end())
1019
if(restartTrails) (*iter)->startTrail(true);
1020
(*iter)->update_trail(nav);
1021
(*iter)->update((int)(delta_time*1000));
1027
// is a lunar eclipse close at hand?
1028
bool SolarSystem::near_lunar_eclipse(const Navigator * nav, Projector *prj)
1030
// TODO: could replace with simpler test
1032
Vec3d e = getEarth()->get_ecliptic_pos();
1033
Vec3d m = getMoon()->get_ecliptic_pos(); // relative to earth
1034
Vec3d mh = getMoon()->get_heliocentric_ecliptic_pos(); // relative to sun
1036
// shadow location at earth + moon distance along earth vector from sun
1039
Vec3d shadow = en * (e.length() + m.length());
1041
// find shadow radii in AU
1042
double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000/AU;
1044
// modify shadow location for scaled moon
1045
Vec3d mdist = shadow - mh;
1046
if(mdist.length() > r_penumbra + 2000/AU) return 0; // not visible so don't bother drawing
1051
//! Find and return the list of at most maxNbItem objects auto-completing the passed object I18n name
1052
vector<wstring> SolarSystem::listMatchingObjectsI18n(const wstring& objPrefix, unsigned int maxNbItem) const
1054
vector<wstring> result;
1055
if (maxNbItem==0) return result;
1057
wstring objw = objPrefix;
1058
transform(objw.begin(), objw.end(), objw.begin(), ::toupper);
1060
vector < Planet * >::const_iterator iter;
1061
for (iter = system_planets.begin(); iter != system_planets.end(); ++iter)
1063
wstring constw = (*iter)->getNameI18n().substr(0, objw.size());
1064
transform(constw.begin(), constw.end(), constw.begin(), ::toupper);
1067
result.push_back((*iter)->getNameI18n());
1068
if (result.size()==maxNbItem)
1075
void SolarSystem::selectedObjectChangeCallBack(StelModuleSelectAction action)
1077
const std::vector<StelObjectP> newSelected = StelApp::getInstance().getStelObjectMgr().getSelectedObject("Planet");
1078
if (!newSelected.empty())
1079
setSelected(newSelected[0].get());
1080
// // potentially record this action
1081
// if (!recordActionCallback.empty())
1082
// recordActionCallback("select planet " + selected_object.getEnglishName());
1085
// Activate/Deactivate planets display
1086
void SolarSystem::setFlagPlanets(bool b) {Planet::setflagShow(b);}
1087
bool SolarSystem::getFlagPlanets(void) const {return Planet::getflagShow();}
1089
// Set/Get planets names color
1090
void SolarSystem::setNamesColor(const Vec3f& c) {Planet::set_label_color(c);}
1091
const Vec3f& SolarSystem::getNamesColor(void) const {return Planet::getLabelColor();}
1093
// Set/Get orbits lines color
1094
void SolarSystem::setOrbitsColor(const Vec3f& c) {Planet::set_orbit_color(c);}
1095
Vec3f SolarSystem::getOrbitsColor(void) const {return Planet::getOrbitColor();}
1097
// Set/Get planets trails color
1098
void SolarSystem::setTrailsColor(const Vec3f& c) {Planet::set_trail_color(c);}
1099
Vec3f SolarSystem::getTrailsColor(void) const {return Planet::getTrailColor();}
1101
// Set/Get base planets display scaling factor
1102
void SolarSystem::setScale(float scale) {Planet::setScale(scale);}
1103
float SolarSystem::getScale(void) const {return Planet::getScale();}
1105
// Set/Get if Moon display is scaled
1106
void SolarSystem::setFlagMoonScale(bool b)
1108
if (!b) getMoon()->set_sphere_scale(1);
1109
else getMoon()->set_sphere_scale(moonScale);
1113
// Set/Get Moon display scaling factor
1114
void SolarSystem::setMoonScale(float f)
1118
getMoon()->set_sphere_scale(moonScale);
1121
// Set selected planets by englishName
1122
void SolarSystem::setSelected(const string& englishName)
1124
setSelected(searchByEnglishName(englishName));
1127
bool SolarSystem::bigger_distance::operator()(Planet* p1, Planet* p2)
1129
return p1->get_distance() > p2->get_distance();