1 /*
2  * Stellarium
3  * Copyright (C) 2002 Fabien Chereau
4  *
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.
9  *
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.
14  *
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., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #ifndef PLANET_HPP
21 #define PLANET_HPP
22 
23 #include "StelObject.hpp"
24 #include "StelProjector.hpp"
25 #include "StelPropertyMgr.hpp"
26 #include "VecMath.hpp"
27 #include "GeomMath.hpp"
28 #include "StelFader.hpp"
29 #include "StelTextureTypes.hpp"
30 #include "StelProjectorType.hpp"
31 #include "RotationElements.hpp"
32 
33 #include <QCache>
34 #include <QString>
35 
36 // The callback type for the external position computation function
37 // arguments are JDE, position[3], velocity[3].
38 // The last variable is the userData pointer, which is Q_NULLPTR for Planets, but used in derived classes. E.g. points to the KeplerOrbit for Comets.
39 typedef void (*posFuncType)(double, double*, double*, void*);
40 
41 typedef void (OsculatingFunctType)(double jde0,double jde,double xyz[3], double xyzdot[3]);
42 
43 // epoch J2000: 12 UT on 1 Jan 2000
44 #define J2000 2451545.0
45 #define ORBIT_SEGMENTS 360
46 
47 class Orbit;
48 class KeplerOrbit;
49 class StelFont;
50 class StelPainter;
51 class StelTranslator;
52 class StelOBJ;
53 class StelOpenGLArray;
54 class HipsSurvey;
55 template <class T> class QFuture;
56 class QOpenGLBuffer;
57 class QOpenGLFunctions;
58 class QOpenGLShaderProgram;
59 class QOpenGLTexture;
60 #ifdef DEBUG_SHADOWMAP
61 class QOpenGLFramebufferObject;
62 #endif
63 
64 typedef QSharedPointer<class HipsSurvey> HipsSurveyP;
65 
66 // Class to manage rings for planets like Saturn
67 class Ring
68 {
69 public:
70 	Ring(float radiusMin, float radiusMax,const QString &texname);
getSize(void) const71 	double getSize(void) const {return static_cast<double>(radiusMax);}
72 	const float radiusMin;
73 	const float radiusMax;
74 	StelTextureSP tex;
75 };
76 
77 
78 class Planet : public StelObject
79 {
80 public:
81 	static const QString PLANET_TYPE;
82 	friend class SolarSystem;
83 
84 	//! numeric typecodes for the type descriptions in ssystem.ini
85 	// Until 0.13 QStrings were used for types.
86 	// Enums are slightly faster than string comparisons in time-critical comparisons.
87 	// If other types are introduced, add here and the string in init().
88 	// TBD for 0.19 or later: Preferably convert this into a bitfield and allow several bits set:
89 	// Cubewanos, SDO, OCO, Sednoids are Asteroids, Pluto is a Plutino and DwarfPlanet, Ceres is Asteroid and DwarfPlanet etc.!
90 	// Maybe even add queries like Planet::isAsteroid() { return (planetType & Planet::isAsteroid);}
91 	enum PlanetType
92 	{
93 		isStar,         // ssystem.ini: type="star"
94 		isPlanet,       // ssystem.ini: type="planet"
95 		isMoon,         // ssystem.ini: type="moon"
96 		isObserver,     // ssystem.ini: type="observer"
97 		isArtificial,   // Used in transitions from planet to planet.
98 		isAsteroid,     // ssystem.ini: type="asteroid". all types >= isAsteroid are "Minor Bodies".
99 				// Put other things (spacecraft etc) before isAsteroid.
100 		isPlutino,      // ssystem.ini: type="plutino"
101 		isComet,        // ssystem.ini: type="comet"
102 		isDwarfPlanet,  // ssystem.ini: type="dwarf planet"
103 		isCubewano,     // ssystem.ini: type="cubewano"
104 		isSDO,          // ssystem.ini: type="scattered disc object"
105 		isOCO,          // ssystem.ini: type="oco"
106 		isSednoid,      // ssystem.ini: type="sednoid"
107 		isInterstellar, // ssystem.ini: type="interstellar object"
108 		isUNDEFINED     // ssystem.ini: type=<anything else>. THIS IS ONLY IN CASE OF ERROR!
109 	};
110 	Q_ENUM(PlanetType)
111 
112 	enum PlanetOrbitColorStyle
113 	{
114 		ocsOneColor,		// One color for all orbits
115 		ocsGroups,		// Separate colors for each group of Solar system bodies
116 		ocsMajorPlanets		// Separate colors for each of major planets of Solar system
117 	};
118 	Q_ENUM(PlanetOrbitColorStyle)
119 
120 	enum ApparentMagnitudeAlgorithm
121 	{
122 		Mueller_1893,               // G. Mueller, based on visual observations 1877-91. [Explanatory Supplement to the Astronomical Almanac, 1961]
123 		AstronomicalAlmanac_1984,   // Astronomical Almanac 1984 and later. These give V (instrumental) magnitudes (allegedly from D.L. Harris, but this is wrong!)
124 		ExplanatorySupplement_1992, // Algorithm provided by Pere Planesas (Observatorio Astronomico Nacional) (Was called "Planesas")
125 		ExplanatorySupplement_2013, // Explanatory Supplement to the Astronomical Almanac, 3rd edition 2013
126 		MallamaHilton_2018,         // A. Mallama, J. L. Hilton: Computing apparent planetary magnitudes for the Astronomical Almanac. Astron.&Computing 25 (2018) 10-24
127 		UndefinedAlgorithm,
128 		Generic                     // Visual magnitude based on phase angle and albedo. The formula source for this is totally unknown!
129 	};
130 	Q_ENUM(ApparentMagnitudeAlgorithm)
131 
132 	//! enums to indicate for which purpose we check positional quality.
133 	//! Objects on KeplerOrbits may be too far from their epoch to provide useful data.
134 	enum PositionQuality
135 	{
136 		Position,                   // Good enough for positions.
137 		OrbitPlotting		    // Good enough for orbitplotting?
138 	};
139 	Q_ENUM(PositionQuality)
140 
141 public:
142 	Planet(const QString& englishName,
143 	       double equatorialRadius,
144 	       double oblateness,
145 	       Vec3f halocolor,
146 	       float albedo,
147 	       float roughness,
148 	       const QString& texMapName,
149 	       const QString& normalMapName,
150 	       const QString& objModelName,
151 	       posFuncType _coordFunc,
152 	       Orbit *anOrbitPtr,
153 	       OsculatingFunctType *osculatingFunc,
154 	       bool closeOrbit,
155 	       bool hidden,
156 	       bool hasAtmosphere,
157 	       bool hasHalo,
158 	       const QString &pTypeStr);
159 
160 	virtual ~Planet() Q_DECL_OVERRIDE;
161 
162 	//! Initializes static vars. Must be called before creating first planet.
163 	// Currently ensured by SolarSystem::init()
164 	static void init();
165 
166 	///////////////////////////////////////////////////////////////////////////
167 	// Methods inherited from StelObject
168 	//! Get a string with data about the Planet.
169 	//! Planets support the following InfoStringGroup flags:
170 	//! - Name
171 	//! - Magnitude
172 	//! - RaDec
173 	//! - AltAzi
174 	//! - Distance
175 	//! - Size
176 	//! - PlainText
177 	//! - Extra: Heliocentric Ecliptical Coordinates & Observer-planetocentric Ecliptical Coordinates, Phase, illumination, phase angle & elongation from the Sun
178 	//! @note subclasses should prefer to override only the component infostrings getInfoString...(), not this method!
179 	//! @param core the StelCore object
180 	//! @param flags a set of InfoStringGroup items to include in the return value.
181 	//! @return a QString containing an HMTL encoded description of the Planet.
182 	virtual QString getInfoString(const StelCore *core, const InfoStringGroup& flags) const Q_DECL_OVERRIDE;
183 	//! In addition to the entries from StelObject::getInfoMap(), Planet objects provide
184 	//! - distance
185 	//! - phase (result of getPhase)
186 	//! - illumination (=100*phase)
187 	//! - phase-angle
188 	//! - phase-angle-dms (formatted string)
189 	//! - phase-angle-deg (formatted string)
190 	//! - elongation
191 	//! - elongation-dms (formatted string)
192 	//! - elongation-deg (formatted string)
193 	//! - type (object type description)
194 	//! - velocity (formatted string)
195 	//! - heliocentric-velocity (formatted string)
196 	//! - scale
197 	//! - eclipse-obscuration (for Sun only)
198 	//! - eclipse-magnitude (for Sun only)
199 	//! - central_l (on Earth only; degrees)
200 	//! - central_b (on Earth only; degrees)
201 	//! - pa_axis (on Earth only; degrees)
202 	//! - subsolar_l (on Earth only; degrees)
203 	//! - subsolar_b (on Earth only; degrees)
204 	//! - libration_l (on Earth for Moon only; degrees)
205 	//! - libration_b (on Earth for Moon only; degrees)
206 	//! - colongitude (on Earth for Moon only; degrees)
207 	//! - penumbral-eclipse-magnitude (on Earth for Moon only)
208 	//! - umbral-eclipse-magnitude (on Earth for Moon only)
209 	virtual QVariantMap getInfoMap(const StelCore *core) const  Q_DECL_OVERRIDE;
210 	virtual double getCloseViewFov(const StelCore* core) const Q_DECL_OVERRIDE;
211 	virtual double getSatellitesFov(const StelCore* core) const Q_DECL_OVERRIDE;
212 	virtual double getParentSatellitesFov(const StelCore* core) const Q_DECL_OVERRIDE;
213 	virtual float getVMagnitude(const StelCore* core) const Q_DECL_OVERRIDE;
214 	virtual float getSelectPriority(const StelCore* core) const Q_DECL_OVERRIDE;
215 	virtual Vec3f getInfoColor(void) const Q_DECL_OVERRIDE;
getType(void) const216 	virtual QString getType(void) const Q_DECL_OVERRIDE {return PLANET_TYPE;}
getID(void) const217 	virtual QString getID(void) const Q_DECL_OVERRIDE { return englishName; }
218 	//! A Planet's own eclipticPos is in VSOP87 ref. frame (practically equal to ecliptic of J2000 for us) coordinates relative to the parent body (sun, planet).
219 	//! To get J2000 equatorial coordinates, we require heliocentric ecliptical positions (adding up parent positions) of observer and Planet.
220 	//! Then we use the matrix rotation multiplication with an existing matrix in StelCore to orient from eclipticalJ2000 to equatorialJ2000.
221 	//! The end result is a non-normalized 3D vector which allows retrieving distances etc.
222 	//! The positional computation is called by SolarSystem. If the core's aberration setting is active, the J2000 position will then include it.
223 	virtual Vec3d getJ2000EquatorialPos(const StelCore *core) const Q_DECL_OVERRIDE;
224 	virtual QString getEnglishName(void) const Q_DECL_OVERRIDE;
225 	virtual QString getNameI18n(void) const Q_DECL_OVERRIDE;
getNativeName(void) const226 	QString getNativeName(void) const { return nativeName; }
getNativeNameI18n(void) const227 	QString getNativeNameI18n(void) const { return nativeNameMeaningI18n; }
getCommonEnglishName(void) const228 	QString getCommonEnglishName(void) const {return englishName;}
getCommonNameI18n(void) const229 	QString getCommonNameI18n(void) const {return nameI18;}
230 	//! Get angular semidiameter, degrees. If planet display is artificially enlarged (e.g. Moon upscale), value will also be increased.
231 	virtual double getAngularSize(const StelCore* core) const Q_DECL_OVERRIDE;
hasAtmosphere(void)232 	virtual bool hasAtmosphere(void) {return atmosphere;}
hasHalo(void)233 	virtual bool hasHalo(void) {return halo;}
234 	//! Returns whether planet positions are valid and useful for the current simulation time.
235 	//! E.g. outdated orbital elements for Kepler orbits (beyond their orbit_good .ini file entries)
236 	//! may lead to invalid positions which should better not be used.
237 	//! @param purpose signal whether result should be good enough for observation of just for plotting orbit data.
238 	//! For observation, date should be within the orbit_good value, or within 1 year from epoch of the orbital elements.
239 	//! @note for major planets and moons this method will always return true
240 	bool hasValidPositionalData(const double JDE, const PositionQuality purpose) const;
241 	//! Returns JDE dates of presumably valid data for positional calculation or acceptable range for graphics.
242 	//! For the major planets and moons, this is always (std::numeric_limits<double>::min(), std::numeric_limits<double>::max())
243 	//! For planets with Keplerian orbits, this is [epoch-orbit_good, epoch+orbit_good] or,
244 	//! if purpose=Position, [epoch-min(orbit_good, 365), epoch+min(orbit_good, 365)].
245 	//! This should help to detect and avoid using outdated orbital elements.
246 	Vec2d getValidPositionalDataRange(const PositionQuality purpose) const;
getAxisRotation(void)247 	float getAxisRotation(void) { return axisRotation;} //! return axisRotation last computed in computeTransMatrix(). [degrees]
248 
249 	///////////////////////////////////////////////////////////////////////////
250 	// Methods of SolarSystem object
251 	//! Translate planet name using the passed translator
252 	virtual void translateName(const StelTranslator &trans);
253 
254 	// Draw the Planet
255 	// GZ Made that virtual to allow comets having their own draw().
256 	virtual void draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont);
257 
258 	///////////////////////////////////////////////////////////////////////////
259 	// Methods specific to Planet
260 	//! Get the equator radius of the planet in AU.
261 	//! @return the equator radius of the planet in astronomical units.
getEquatorialRadius(void) const262 	double getEquatorialRadius(void) const {return equatorialRadius;}
263 	//! Get the value (1-f) for oblateness f=polarRadius/equatorialRadius.
getOneMinusOblateness(void) const264 	double getOneMinusOblateness(void) const {return oneMinusOblateness;}
265 	//! Get the polar radius of the planet in AU.
266 	//! @return the polar radius of the planet in astronomical units.
getPolarRadius(void) const267 	double getPolarRadius(void) const {return equatorialRadius*oneMinusOblateness;}
268 	//! Get duration of sidereal day (earth days, may come from rot_periode or orbit_period (for moons) from ssystem_*.ini)
getSiderealDay(void) const269 	double getSiderealDay(void) const { if (re.W1!=0.) return 360.0/re.W1; else return static_cast<double>(re.period);} // I assume the more modern values are better.
270 	//! Get duration of sidereal year
271 	// must be virtual for Comets.
getSiderealPeriod(void) const272 	virtual double getSiderealPeriod(void) const { return siderealPeriod; }
273 	//! set duration of sidereal year. Also sets deltaOrbitJDE and may set closeOrbit for Planet objects which have KeplerOrbits.
274 	//! siderealPeriod [earth days] orbital duration.
275 	void setSiderealPeriod(const double siderealPeriod);
276 	//! Get duration of mean solar day, in earth days.
277 	double getMeanSolarDay(void) const;
278 	//! Get albedo
getAlbedo(void) const279 	double getAlbedo(void) const { return static_cast<double>(albedo); }
280 
getTextMapName() const281 	const QString& getTextMapName() const {return texMapName;}
getPlanetTypeString() const282 	const QString getPlanetTypeString() const {return pTypeMap.value(pType);}
getPlanetType() const283 	PlanetType getPlanetType() const {return pType;}
getOrbit() const284 	Orbit* getOrbit() const {return orbitPtr;}
285 
setNativeName(QString planet)286 	void setNativeName(QString planet) { nativeName = planet; }
setNativeNameMeaning(QString planet)287 	void setNativeNameMeaning(QString planet) { nativeNameMeaning = planet; }
288 
289 	//! set the IAU moon number (designation of the moon), if any.
290 	void setIAUMoonNumber(QString designation);
291 
292 	//! Return the absolute magnitude (read from file ssystem.ini)
getAbsoluteMagnitude() const293 	float getAbsoluteMagnitude() const {return absoluteMagnitude;}
294 	//! Return the mean opposition magnitude, defined as V(1,0)+5log10(a(a-1))
295 	//! A return value of 100 signals invalid result.
296 	float getMeanOppositionMagnitude() const;
297 	//
getApparentMagnitudeAlgorithm()298 	static ApparentMagnitudeAlgorithm getApparentMagnitudeAlgorithm()  { return vMagAlgorithm; }
getApparentMagnitudeAlgorithmString()299 	static const QString getApparentMagnitudeAlgorithmString()  { return vMagAlgorithmMap.value(vMagAlgorithm); }
300 	static void setApparentMagnitudeAlgorithm(QString algorithm);
setApparentMagnitudeAlgorithm(ApparentMagnitudeAlgorithm algorithm)301 	static void setApparentMagnitudeAlgorithm(ApparentMagnitudeAlgorithm algorithm){ vMagAlgorithm=algorithm; }
302 
303 	//! Compute the axial z rotation (daily rotation around the polar axis) [degrees] to use from equatorial to hour angle based coordinates.
304 	//! On Earth, sidereal time on the other hand is the angle along the planet equator from RA0 to the meridian, i.e. hour angle of the first point of Aries.
305 	//! For Earth (of course) it is sidereal time at Greenwich.
306 	//! V0.21+ update:
307 	//! For planets and Moons, in this context this is the rotation angle W of the Prime meridian from the ascending node of the planet equator on the ICRF equator.
308 	//! The usual WGCCRE model is W=W0+d*W1. Some planets/moons have more complicated rotations though, these are also handled in here.
309 	//! The planet objects with old-style data are computed like in earlier versions of Stellarium. Their computational model is however questionable.
310 	//! For general applicability we need both time flavours:
311 	//! @param JD is JD(UT) for Earth
312 	//! @param JDE is used for other locations
313 	double getSiderealTime(double JD, double JDE) const;
314 
315 	//! return a rotation matrix from the planet's equatorial coordinate frame to the VSOP87 (ecliptical J2000) frame.
316 	//! For planets/moons with WGCCRE rotation elements, this is just a single matrix.
317 	//! For objects with traditional elements, this builds up the matrix from the parents.
318 	Mat4d getRotEquatorialToVsop87(void) const;
319 	//! set a rotation matrix from the planet's equatorial coordinate frame to the VSOP87 (ecliptical J2000) frame.
320 	//! For planets/moons with WGCCRE rotation elements, this just sets this matrix.
321 	//! For objects with traditional elements, this builds up the matrix from the parents.
322 	void setRotEquatorialToVsop87(const Mat4d &m);
323 
getRotationElements(void) const324 	const RotationElements &getRotationElements(void) const {return re;}
325 
326 	//! Set the rotational elements.
327 	//! Given two data models, we must support both: the traditional elements relative to the parent object:
328 	//! name: English name of the object. A corrective function may be attached which depends on the name.
329 	//! _period: duration of sidereal rotation [Julian days]
330 	//! _offset: [angle at _epoch. ]
331 	//! _epoch: [JDE]
332 	//! _obliquity [rad]
333 	//! _ascendingNode of equator on ecliptic[rad]
334 	//! The more modern way to specify these elements are relative to the ICRF:
335 	//! ra_pole=_ra0 + T*_ra1. ra_pole and de_pole must be computed more than for initialisation for J2000
336 	//! de_pole=_de0 + T*_de1. ra and de values to be stored in [rad]
337 	//! _w0, _w1 to be given in degrees!
338 	//! If _ra0 is not zero, we understand WGCCRE data ra0, ra1, de0, de1, w0, w1 are used.
339 	void setRotationElements(const QString name, const double _period, const double _offset, const double _epoch,
340 				 const double _obliquity, const double _ascendingNode,
341 				 const double _ra0, const double _ra1,
342 				 const double _de0, const double _de1,
343 				 const double _w0,  const double _w1);
344 
345 	//! Note: The only place where this is used is to build up orbits for planet moons w.r.t. the parent planet orientation.
getRotAscendingNode(void) const346 	double getRotAscendingNode(void) const {return re.ascendingNode; }
347 	//! return angle between axis and normal of ecliptic plane (or, for a moon, equatorial/reference plane defined by parent).
348 	//! For Earth, this is the angle between axis and normal to current ecliptic of date, i.e. the ecliptic obliquity of date JDE.
349 	//! Note: The only place where this is not used for Earth is to build up orbits for planet moons w.r.t. the parent planet orientation.
350 	double getRotObliquity(double JDE) const;
351 
352 	//! Compute the position and orbital velocity in the parent Planet coordinate system
353 	//! You can add the aberrationPush value according to Edot*lightTime in Explanatory Supplement (2013) formula 7.55.
354 	virtual void computePosition(const double dateJDE, const Vec3d &aberrationPush);
355 	//! Compute the position and orbital velocity in the parent Planet coordinate system, and return them in eclPosition and eclVelocity
356 	//! These may be preferred when we want to avoid setting the actual position (e.g., RTS computation)
357 	virtual void computePosition(const double dateJDE, Vec3d &eclPosition, Vec3d &eclVelocity) const;
358 
359 
360 	//! Compute the transformation matrix from the local Planet coordinate to the parent Planet coordinate.
361 	//! This requires both flavours of JD in cases involving Earth.
362 	void computeTransMatrix(double JD, double JDE);
363 
364 	//! Retrieve planetocentric rectangular coordinates of a location on the ellipsoid surface, or with altitude altMetres above the ellipsoid surface.
365 	//! Meeus, Astr. Alg. 2nd ed, Ch.11.
366 	//! @param longDeg longitude of location, degrees. (currently unused. Set to 0.)
367 	//! @param latDeg planetographic latitude, degrees.
368 	//! @param altMetres altitude above ellipsoid surface (metres)
369 	//! @return [rhoCosPhiPrime*a, rhoSinPhiPrime*a, phiPrime, rho*a] where a=equatorial radius
370 	Vec4d getRectangularCoordinates(const double longDeg, const double latDeg, const double altMetres=0.) const;
371 
372 	//! Get the phase angle (radians) for an observer at pos obsPos in heliocentric coordinates (in AU)
373 	double getPhaseAngle(const Vec3d& obsPos) const;
374 	//! Get the elongation angle (radians) for an observer at pos obsPos in heliocentric coordinates (in AU)
375 	double getElongation(const Vec3d& obsPos) const;
376 	//! Get the angular radius (degrees) of the planet spheroid (i.e. without the rings)
377 	double getSpheroidAngularSize(const StelCore* core) const;
378 	//! Get the planet phase (illuminated fraction of the planet disk, [0=dark..1=full]) for an observer at pos obsPos in heliocentric coordinates (in AU)
379 	float getPhase(const Vec3d& obsPos) const;
380 	//! Get the position angle of the illuminated limb of a planet
381 	//! The result depends on the arguments' coordinate system which must be identical.
382 	//! E.g. if both are equatorial for equinox of date or J2000, the angle is zero when the bright limb is towards the north of the disk.
383 	//! An angle of 90° indicates a bright limb on the eastern limb, like an old moon.
384 	//! Source: Meeus, Astr.Algorithms (2nd ed.), 48.5.
385 	static float getPAsun(const Vec3d &sunPos, const Vec3d &objPos);
386 
387 	//! Get planetographic coordinates of subsolar and sub-observer points.
388 	//! Only meaningful for earth-bound observers.
389 	//! Source: Explanatory Supplement 2013, 10.4.1
390 	//! @param jupiterGraphical Jupiter requires special treatment because its LII coordinate system does not
391 	//!                         stay in sync with the texture. (GRS is moving). Set this to true to return the
392 	//!                         incorrect, graphics-only longitude.
393 	//! first[0]  = 10.26 phi_e     [rad] Planetocentric latitude of sub-earth point
394 	//! first[1]  = 10.26 phi'_e	[rad] Planetographic latitude of sub-earth point
395 	//! first[2]  = 10.26 lambda'_e	[rad] Planetographic longitude of sub-earth point (0..2pi)
396 	//! first[3]  = 10.29 P_n	[rad] Position angle of axis north pole in equatorial coordinates of date
397 	//! second[0] = 10.26 phi_s	[rad] Planetocentric latitude of sub-solar point
398 	//! second[1] = 10.26 phi'_s	[rad] Planetographic latitude of sub-solar point
399 	//! second[2] = 10.26 lambda'_s	[rad] Planetographic longitude of sub-solar point (0..2pi)
400 	//! Note: For the Moon, it is more common to give Libration angles, where L=-lambda'_e, B=phi'_e.
401 	//! Note: For Jupiter, this returns central meridian in L_II.
402 	//! Note: For Saturn, this returns central meridian in L_III (rotation of magnetic field).
403 	QPair<Vec4d, Vec3d> getSubSolarObserverPoints(const StelCore *core, bool jupiterGraphical=false) const;
404 
405 	//! returns if planet has retrograde rotation
isRotatingRetrograde() const406 	bool isRotatingRetrograde() const { return re.W1<0.; }
407 
408 	//! Get the Planet position in the parent Planet ecliptic coordinate in AU
409 	Vec3d getEclipticPos(double dateJDE) const;
410 	//! Get the last computed Planet position in the parent Planet ecliptic coordinate in AU
getEclipticPos() const411 	Vec3d getEclipticPos() const {return getEclipticPos(lastJDE);}
412 
413 	//! Return the heliocentric ecliptical position
getHeliocentricEclipticPos() const414 	Vec3d getHeliocentricEclipticPos() const {return getHeliocentricPos(eclipticPos);}
415 	Vec3d getHeliocentricEclipticPos(double dateJDE) const;
416 
417 	//! Return the heliocentric transformation for local (parentocentric) coordinate
418 	//! @arg p planetocentric rectangular ecliptical coordinate (J2000)
419 	//! @return heliocentric rectangular ecliptical coordinates (J2000)
420 	Vec3d getHeliocentricPos(Vec3d p) const;
421 	//! Propagate the heliocentric coordinates to parentocentric coordinates
422 	//! @arg pos heliocentric rectangular ecliptical coordinate (J2000)
423 	void setHeliocentricEclipticPos(const Vec3d &pos);
424 
425 	//! Get the planet velocity around the parent planet in ecliptical coordinates in AU/d
getEclipticVelocity() const426 	Vec3d getEclipticVelocity() const {return eclipticVelocity;}
427 
428 	//! Get the planet's heliocentric velocity in the solar system in ecliptical coordinates in AU/d. Required for aberration!
429 	Vec3d getHeliocentricEclipticVelocity() const;
430 
431 	//! Compute and return the distance to the given position in heliocentric ecliptical (J2000) coordinates (in AU)
432 	//! Preserves result for later retrieval by getDistance()
433 	//! As side effect, improve fps by juggling update frequency (deltaJDE) for asteroids and other minor bodies. They must be fast if close to observer, but can be slow if further away.
434 	double computeDistance(const Vec3d& obsHelioPos);
435 	//! Return the last computed distance to the given position in heliocentric ecliptical (J2000) coordinates (in AU)
getDistance(void) const436 	double getDistance(void) const {return distance;}
437 
setRings(Ring * r)438 	void setRings(Ring* r) {rings = r;}
439 
setSphereScale(double s)440 	void setSphereScale(double s) { if(!fuzzyEquals(s, sphereScale)) { sphereScale = s; if(objModel) objModel->needsRescale=true; } }
getSphereScale() const441 	double getSphereScale() const { return sphereScale; }
442 
getParent(void) const443 	const QSharedPointer<Planet> getParent(void) const {return parent;}
444 
setLabelColor(const Vec3f & lc)445 	static void setLabelColor(const Vec3f& lc) {labelColor = lc;}
getLabelColor(void)446 	static const Vec3f& getLabelColor(void) {return labelColor;}
447 
448 	// update displayed elements. @param deltaTime: ms (since last call)
449 	virtual void update(int deltaTime);
450 
setFlagHints(bool b)451 	void setFlagHints(bool b){hintFader = b;}
getFlagHints(void) const452 	bool getFlagHints(void) const {return hintFader;}
453 
setFlagLabels(bool b)454 	void setFlagLabels(bool b){flagLabels = b;}
getFlagLabels(void) const455 	bool getFlagLabels(void) const {return flagLabels;}
456 
457 	bool flagNativeName;
setFlagNativeName(bool b)458 	void setFlagNativeName(bool b) { flagNativeName = b; }
getFlagNativeName(void) const459 	bool getFlagNativeName(void) const { return flagNativeName; }
460 
461 	///////////////////////////////////////////////////////////////////////////
462 	///// Orbit related code
463 	// Should move to an OrbitPath class which works on a SolarSystemObject, not a Planet
setFlagOrbits(bool b)464 	void setFlagOrbits(bool b){orbitFader = b;}
getFlagOrbits(void) const465 	bool getFlagOrbits(void) const {return orbitFader;}
466 	LinearFader orbitFader;
467 	// draw orbital path of Planet
468 	void drawOrbit(const StelCore*);
469 	Vec3d orbit[ORBIT_SEGMENTS+1];  // store heliocentric coordinates for drawing the orbit
470 	double deltaJDE;                // time difference between positional updates.
471 	double deltaOrbitJDE;
472 	bool closeOrbit;                // whether to connect the beginning of the orbit line to
473 					// the end: good for elliptical orbits, bad for parabolic
474 					// and hyperbolic orbits
475 
476 	static Vec3f orbitColor;
setOrbitColor(const Vec3f & oc)477 	static void setOrbitColor(const Vec3f& oc) {orbitColor = oc;}
getOrbitColor()478 	static const Vec3f& getOrbitColor() {return orbitColor;}
479 
480 	static Vec3f orbitMajorPlanetsColor;
setMajorPlanetOrbitColor(const Vec3f & oc)481 	static void setMajorPlanetOrbitColor(const Vec3f& oc) { orbitMajorPlanetsColor = oc;}
getMajorPlanetOrbitColor()482 	static const Vec3f& getMajorPlanetOrbitColor() {return orbitMajorPlanetsColor;}
483 
484 	static Vec3f orbitMoonsColor;
setMoonOrbitColor(const Vec3f & oc)485 	static void setMoonOrbitColor(const Vec3f& oc) { orbitMoonsColor = oc;}
getMoonOrbitColor()486 	static const Vec3f& getMoonOrbitColor() {return orbitMoonsColor;}
487 
488 	static Vec3f orbitMinorPlanetsColor;
setMinorPlanetOrbitColor(const Vec3f & oc)489 	static void setMinorPlanetOrbitColor(const Vec3f& oc) { orbitMinorPlanetsColor = oc;}
getMinorPlanetOrbitColor()490 	static const Vec3f& getMinorPlanetOrbitColor() {return orbitMinorPlanetsColor;}
491 
492 	static Vec3f orbitDwarfPlanetsColor;
setDwarfPlanetOrbitColor(const Vec3f & oc)493 	static void setDwarfPlanetOrbitColor(const Vec3f& oc) { orbitDwarfPlanetsColor = oc;}
getDwarfPlanetOrbitColor()494 	static const Vec3f& getDwarfPlanetOrbitColor() {return orbitDwarfPlanetsColor;}
495 
496 	static Vec3f orbitCubewanosColor;
setCubewanoOrbitColor(const Vec3f & oc)497 	static void setCubewanoOrbitColor(const Vec3f& oc) { orbitCubewanosColor = oc;}
getCubewanoOrbitColor()498 	static const Vec3f& getCubewanoOrbitColor() {return orbitCubewanosColor;}
499 
500 	static Vec3f orbitPlutinosColor;
setPlutinoOrbitColor(const Vec3f & oc)501 	static void setPlutinoOrbitColor(const Vec3f& oc) { orbitPlutinosColor = oc;}
getPlutinoOrbitColor()502 	static const Vec3f& getPlutinoOrbitColor() {return orbitPlutinosColor;}
503 
504 	static Vec3f orbitScatteredDiscObjectsColor;
setScatteredDiscObjectOrbitColor(const Vec3f & oc)505 	static void setScatteredDiscObjectOrbitColor(const Vec3f& oc) { orbitScatteredDiscObjectsColor = oc;}
getScatteredDiscObjectOrbitColor()506 	static const Vec3f& getScatteredDiscObjectOrbitColor() {return orbitScatteredDiscObjectsColor;}
507 
508 	static Vec3f orbitOortCloudObjectsColor;
setOortCloudObjectOrbitColor(const Vec3f & oc)509 	static void setOortCloudObjectOrbitColor(const Vec3f& oc) { orbitOortCloudObjectsColor = oc;}
getOortCloudObjectOrbitColor()510 	static const Vec3f& getOortCloudObjectOrbitColor() {return orbitOortCloudObjectsColor;}
511 
512 	static Vec3f orbitCometsColor;
setCometOrbitColor(const Vec3f & oc)513 	static void setCometOrbitColor(const Vec3f& oc) { orbitCometsColor = oc;}
getCometOrbitColor()514 	static const Vec3f& getCometOrbitColor() {return orbitCometsColor;}
515 
516 	static Vec3f orbitSednoidsColor;
setSednoidOrbitColor(const Vec3f & oc)517 	static void setSednoidOrbitColor(const Vec3f& oc) { orbitSednoidsColor = oc;}
getSednoidOrbitColor()518 	static const Vec3f& getSednoidOrbitColor() {return orbitSednoidsColor;}
519 
520 	static Vec3f orbitInterstellarColor;
setInterstellarOrbitColor(const Vec3f & oc)521 	static void setInterstellarOrbitColor(const Vec3f& oc) { orbitInterstellarColor = oc;}
getInterstellarOrbitColor()522 	static const Vec3f& getInterstellarOrbitColor() {return orbitInterstellarColor;}
523 
524 	static Vec3f orbitMercuryColor;
setMercuryOrbitColor(const Vec3f & oc)525 	static void setMercuryOrbitColor(const Vec3f& oc) { orbitMercuryColor = oc;}
getMercuryOrbitColor()526 	static const Vec3f& getMercuryOrbitColor() {return orbitMercuryColor;}
527 
528 	static Vec3f orbitVenusColor;
setVenusOrbitColor(const Vec3f & oc)529 	static void setVenusOrbitColor(const Vec3f& oc) { orbitVenusColor = oc;}
getVenusOrbitColor()530 	static const Vec3f& getVenusOrbitColor() {return orbitVenusColor;}
531 
532 	static Vec3f orbitEarthColor;
setEarthOrbitColor(const Vec3f & oc)533 	static void setEarthOrbitColor(const Vec3f& oc) { orbitEarthColor = oc;}
getEarthOrbitColor()534 	static const Vec3f& getEarthOrbitColor() {return orbitEarthColor;}
535 
536 	static Vec3f orbitMarsColor;
setMarsOrbitColor(const Vec3f & oc)537 	static void setMarsOrbitColor(const Vec3f& oc) { orbitMarsColor = oc;}
getMarsOrbitColor()538 	static const Vec3f& getMarsOrbitColor() {return orbitMarsColor;}
539 
540 	static Vec3f orbitJupiterColor;
setJupiterOrbitColor(const Vec3f & oc)541 	static void setJupiterOrbitColor(const Vec3f& oc) { orbitJupiterColor = oc;}
getJupiterOrbitColor()542 	static const Vec3f& getJupiterOrbitColor() {return orbitJupiterColor;}
543 
544 	static Vec3f orbitSaturnColor;
setSaturnOrbitColor(const Vec3f & oc)545 	static void setSaturnOrbitColor(const Vec3f& oc) { orbitSaturnColor = oc;}
getSaturnOrbitColor()546 	static const Vec3f& getSaturnOrbitColor() {return orbitSaturnColor;}
547 
548 	static Vec3f orbitUranusColor;
setUranusOrbitColor(const Vec3f & oc)549 	static void setUranusOrbitColor(const Vec3f& oc) { orbitUranusColor = oc;}
getUranusOrbitColor()550 	static const Vec3f& getUranusOrbitColor() {return orbitUranusColor;}
551 
552 	static Vec3f orbitNeptuneColor;
setNeptuneOrbitColor(const Vec3f & oc)553 	static void setNeptuneOrbitColor(const Vec3f& oc) { orbitNeptuneColor = oc;}
getNeptuneOrbitColor()554 	static const Vec3f& getNeptuneOrbitColor() {return orbitNeptuneColor;}
555 
556 	static PlanetOrbitColorStyle orbitColorStyle;
557 
558 	//! Return the list of planets which project some shadow on this planet
559 	QVector<const Planet*> getCandidatesForShadow() const;
560 
getAberrationPush() const561 	Vec3d getAberrationPush() const {return aberrationPush; }
562 
563 	//! Compute times of nearest rise, transit and set for a solar system object for current location.
564 	//! @param core the currently active StelCore object
565 	//! @param altitude (optional; default=0) altitude of the object, degrees.
566 	//!        Setting this to -6. for the Sun will find begin and end for civil twilight.
567 	//! @return Vec4d - time of rise, transit and set closest to current time; JD.
568 	//! @note The fourth element flags particular conditions:
569 	//!       *  +100. for circumpolar objects. Rise and set give lower culmination times.
570 	//!       *  -100. for objects never rising. Rise and set give transit times.
571 	//!       * -1000. is used as "invalid" value. The result should then not be used.
572 	//! @note This is based on Meeus, Astronomical Algorithms (2nd ed.), but deviates in details.
573 	//! @note Limitation for efficiency: If this is a planet moon from another planet, we compute RTS for the parent planet instead!
574 	virtual Vec4d getRTSTime(const StelCore* core, const double altitude=0.) const Q_DECL_OVERRIDE;
575 
576 	void resetTextures();
577 	void replaceTexture(const QString& texName);
578 
579 protected:
580 	// These components for getInfoString() can be overridden in subclasses
581 	virtual QString getInfoStringName(const StelCore *core, const InfoStringGroup& flags) const;
582 	virtual QString getInfoStringAbsoluteMagnitude(const StelCore *core, const InfoStringGroup& flags) const;
583 	//! Any flag=Extra information to be displayed after the magnitude strings
584 	virtual QString getInfoStringExtraMag(const StelCore *core, const InfoStringGroup& flags) const;
585 	//! Any flag=Size information to be displayed
586 	virtual QString getInfoStringSize(const StelCore *core, const InfoStringGroup& flags) const;
587 	//! Return elongation and phase angle when flags=Elongation
588 	virtual QString getInfoStringEloPhase(const StelCore *core, const InfoStringGroup& flags, const bool withIllum) const;
589 	//! Return sidereal and synodic periods when flags=Extra
590 	virtual QString getInfoStringPeriods(const StelCore *core, const InfoStringGroup& flags) const;
591 	//! Any flag=Extra information to be displayed at the end
592 	virtual QString getInfoStringExtra(const StelCore *core, const InfoStringGroup& flags) const;
593 
594 protected:
595 	struct PlanetOBJModel
596 	{
597 		PlanetOBJModel();
598 		~PlanetOBJModel();
599 
600 		//! Loads the data from the StelOBJ into the StelOpenGLArray
601 		bool loadGL();
602 
603 		void performScaling(double scale);
604 
605 		//! The BBox of the original model before any transformations
606 		AABBox bbox;
607 		//! Contains the original positions in model space in km, they need scaling and projection
608 		QVector<Vec3f> posArray;
609 		//! True when the positions need to be rescaled before drawing
610 		bool needsRescale;
611 		//! Contains the scaled positions (sphere scale in AU), need StelProjector transformation for display
612 		QVector<Vec3f> scaledArray;
613 		//! Used to store the projected array data, avoids re-allocation each frame
614 		QVector<Vec3f> projectedPosArray;
615 		//! An OpenGL buffer for the projected positions
616 		QOpenGLBuffer* projPosBuffer;
617 		//! The single texture to use
618 		StelTextureSP texture;
619 		//! The original StelOBJ data, deleted after loading to GL
620 		StelOBJ* obj;
621 		//! The opengl array, created by loadObjModel() but filled later in main thread
622 		StelOpenGLArray* arr;
623 	};
624 
625 	static StelTextureSP texEarthShadow;     // for lunar eclipses
626 
627 	// Used in drawSphere() to compute shadows, and inside a function to derive eclipse sizes.
628 	// For reasons currently unknown we must handle solar eclipses as special case.
629 	void computeModelMatrix(Mat4d &result, bool solarEclipseCase) const;
630 
631 	//! Update the orbit position values.
632 	void computeOrbit();
633 
634 	Vec3f getCurrentOrbitColor() const;
635 
636 	// Return the information string "ready to print" :)
637 	QString getPlanetLabel() const;
638 
639 	// Draw the 3d model. Call the proper functions if there are rings etc..
640 	void draw3dModel(StelCore* core, StelProjector::ModelViewTranformP transfo, float screenSz, bool drawOnlyRing=false);
641 
642 	// Draws the OBJ model, assuming it is available
643 	// @return false if the model can currently not be drawn (not loaded)
644 	bool drawObjModel(StelPainter* painter, float screenSz);
645 
646 	bool drawObjShadowMap(StelPainter* painter, QMatrix4x4 &shadowMatrix);
647 
648 	//! Starts the OBJ loading process, if it has not been done yet.
649 	//! Returns true when the OBJ is ready to draw
650 	bool ensureObjLoaded();
651 
652 	// Draw the 3D sphere
653 	void drawSphere(StelPainter* painter, float screenSz, bool drawOnlyRing=false);
654 
655 	// Draw the Hips survey.
656 	void drawSurvey(StelCore* core, StelPainter* painter);
657 
658 	// Draw the circle and name of the Planet
659 	void drawHints(const StelCore* core, const QFont& planetNameFont);
660 
661 	PlanetOBJModel* loadObjModel() const;
662 
663 	QString englishName;             // english planet name
664 	QString nameI18;                 // International translated name
665 	QString nativeName;              // Can be used in a skyculture
666 	QString nativeNameMeaning;       // Can be used in a skyculture
667 	QString nativeNameMeaningI18n;   // Can be used in a skyculture
668 	QString texMapName;              // Texture file path
669 	QString normalMapName;           // Texture file path
670 	RotationElements re;             // Rotation and axis orientation parameters
671 	double siderealPeriod;           // sidereal period (Planet year or a moon's sidereal month) [earth days]
672 	double equatorialRadius;         // Planet's equatorial radius in AU
673 	double oneMinusOblateness;       // OneMinusOblateness=(polar radius)/(equatorial radius). Geometric flattening f=1-oneMinusOblateness (ExplanSup2013 10.1)
674 	Vec3d eclipticPos;               // Position in AU in the rectangular ecliptic coordinate system (J2000) centered on the parent body.
675 					 // To get heliocentric coordinates, use getHeliocentricEclipticPos()
676 	Vec3d eclipticVelocity;          // Speed in AU/d in the rectangular ecliptic coordinate system (J2000) around the parent body.
677 					 // NEW FEATURE in late 2017. For now, this may be 0/0/0 when we are not yet able to compute it.
678 					 // to get velocity, preferrably read getEclipticVelocity() and getHeliocentricEclipticVelocity()
679 					 // The "State Vector" [Heafner 1999] can be formed from (JDE, eclipticPos, eclipticVelocity)
680 	Vec3d aberrationPush;            // 0.21.2+: a small displacement to be applied if aberred positions are requested.
681 	Vec3d screenPos;                 // Used to store temporarily the 2D position on screen. We need double for moons. Observe Styx from Pluto w/o atmosphere to see that.
682 	Vec3f haloColor;                 // used for drawing the planet halo. Also, when non-spherical (OBJ) model without texture is used, its color is derived from haloColour*albedo.
683 
684 	float absoluteMagnitude;         // since 2017 this moved to the Planet class: V(1,0) from Explanatory Supplement or WGCCRE2009 paper for the planets, H in the H,G magnitude system for Minor planets, H10 for comets.
685 					 // This is the apparent visual magnitude when 1AU from sun and observer, with zero phase angle.
686 	float albedo;                    // Planet albedo. Used for magnitude computation when no other formula in use. Also, when non-spherical (OBJ) model without texture is used, its color is derived from haloColour*albedo.
687 	float roughness;                 // Oren-Nayar roughness for Moon and OBJ-based models
688 	float outgas_intensity;          // The intensity of a pseudo-outgas effect, based on an inverse exponential Lambert shading, with the light at the viewing position
689 					 // Non-null only for Comets, but we use one shader for all Planets and derivatives, so we need a placeholder here.
690 	float outgas_falloff;            // Exponent for falloff of outgas effect, should probably be < 1
691 					 // Non-null only for Comets, but we use one shader for all Planets and derivatives, so we need a placeholder here.
692 	Mat4d rotLocalToParent;          // retro-documented:
693 					 // rotation matrix of axis orientation with respect to the rotation axes of the parent body.
694 					 // For planets, this is the axis orientation w.r.t. VSOP87A/J2000 ecliptical system.
695 					 // For planets' satellites, this used to be a rotation into the planet's equatorial system.
696 					 // 0.21+: if rot_pole... data available in ssystem_*.ini (and therefore re.method==WGCCRE), this is not the rotation from planet axes over ICRF to the VSOP frame on which Stellarium is defined.
697 					 //
698 	float axisRotation;              // Rotation angle of the Planet on its axis, degrees.
699 					 // For Earth, this should be Greenwich Mean Sidereal Time GMST.
700 					 // For V0.21+, and for planets computed after the IAU2009/WGCCRE papers this is angle W (rotDeg),
701 					 // i.e. angle between ascending node of body equator w.r.t. ICRF equator and its prime meridian.
702 	StelTextureSP texMap;            // Planet map texture
703 	StelTextureSP normalMap;         // Planet normal map texture
704 
705 	PlanetOBJModel* objModel;               // Planet model (when it has been loaded)
706 	QFuture<PlanetOBJModel*>* objModelLoader;// For async loading of the OBJ file
707 	QString objModelPath;
708 
709 	HipsSurveyP survey;
710 
711 	Ring* rings;                     // Planet rings
712 	double distance;                 // Temporary variable used to store the distance to a given point
713 					 // it is used for sorting while drawing
714 	double sphereScale;              // Artificial scaling for better viewing.
715 	double lastJDE;                  // caches JDE of last positional computation
716 
717 	posFuncType coordFunc;		// callback for the calculation of the equatorial rectangular heliocentric position at time JDE.
718 	Orbit* orbitPtr;		// Usually a KeplerOrbit for positional computations of Minor Planets, Comets and Moons.
719 					// For an "observer", it is GimbalOrbit.
720 					// For the major planets, it is Q_NULLPTR.
721 
722 	OsculatingFunctType *const osculatingFunc;
723 	QSharedPointer<Planet> parent;           // Planet parent i.e. sun for earth
724 	QList<QSharedPointer<Planet> > satellites;      // satellites of the Planet
725 	LinearFader hintFader;
726 	LinearFader labelsFader;         // Store the current state of the label for this planet
727 	bool flagLabels;                 // Define whether labels should be displayed
728 	bool hidden;                     // useful for fake planets used as observation positions - not drawn or labeled
729 	bool atmosphere;                 // Does the planet have an atmosphere?
730 	bool halo;                       // Does the planet have a halo?
731 	PlanetType pType;                // Type of body
732 	bool multisamplingEnabled_;
733 
734 	static ApparentMagnitudeAlgorithm vMagAlgorithm;
735 
736 	QOpenGLFunctions* gl;
737 
738 	static Vec3f labelColor;
739 	static StelTextureSP hintCircleTex;
740 	static const QMap<PlanetType, QString> pTypeMap; // Maps fast type to english name.
741 	static const QMap<ApparentMagnitudeAlgorithm, QString> vMagAlgorithmMap;
742 	static bool drawMoonHalo;
743 	static bool drawSunHalo;
744 	//! If true, planet orbits will be drawn even if planet is off screen.
745 	static bool permanentDrawingOrbits;
746 	static int orbitsThickness;
747 
748 private:
749 	class StelPropertyMgr* propMgr;
750 	QString iauMoonNumber;
751 	// File path for texture and normal map; both variables used for saving original names of files
752 	QString texMapFileOrig;
753 	QString normalMapFileOrig;
754 
755 	const QString getContextString() const;
756 	QPair<double, double> getLunarEclipseMagnitudes() const;
757 
758 	// Shader-related variables
759 	struct PlanetShaderVars {
760 		// Vertex attributes
761 		int texCoord;
762 		int unprojectedVertex;
763 		int vertex;
764 		int normalIn;
765 
766 		// Common uniforms
767 		int projectionMatrix;
768 		int tex;
769 		int lightDirection;
770 		int eyeDirection;
771 		int diffuseLight;
772 		int ambientLight;
773 		int shadowCount;
774 		int shadowData;
775 		int sunInfo;
776 		int skyBrightness;
777 		int orenNayarParameters;
778 		int outgasParameters;
779 
780 		// Moon-specific variables
781 		int earthShadow;
782 		int eclipsePush; // apparent brightness push for partial Lunar Eclipse (make bright rim overbright)
783 		int normalMap;
784 
785 		// Rings-specific variables
786 		int isRing;
787 		int ring;
788 		int outerRadius;
789 		int innerRadius;
790 		int ringS;
791 
792 		// Shadowmap variables
793 		int shadowMatrix;
794 		int shadowTex;
795 		int poissonDisk;
796 
797 		void initLocations(QOpenGLShaderProgram*);
798 	};
799 
800 	//! Encapsulates some calculated information used for rendering
801 	struct RenderData
802 	{
803 		Mat4d modelMatrix;
804 		Mat4d mTarget;
805 		QVector<const Planet*> shadowCandidates;
806 		QMatrix4x4 shadowCandidatesData;
807 		Vec3d eyePos;
808 	};
809 
810 	//! Calculates and uploads the common shader uniforms (projection matrix, texture, lighting&shadow data)
811 	RenderData setCommonShaderUniforms(const StelPainter &painter, QOpenGLShaderProgram* shader, const PlanetShaderVars& shaderVars); // const;
812 
813 	static PlanetShaderVars planetShaderVars;
814 	static QOpenGLShaderProgram* planetShaderProgram;
815 
816 	static PlanetShaderVars ringPlanetShaderVars;
817 	static QOpenGLShaderProgram* ringPlanetShaderProgram;
818 
819 	static PlanetShaderVars moonShaderVars;
820 	static QOpenGLShaderProgram* moonShaderProgram;
821 
822 	static PlanetShaderVars objShaderVars;
823 	static QOpenGLShaderProgram* objShaderProgram;
824 
825 	static PlanetShaderVars objShadowShaderVars;
826 	static QOpenGLShaderProgram* objShadowShaderProgram;
827 
828 	static PlanetShaderVars transformShaderVars;
829 	static QOpenGLShaderProgram* transformShaderProgram;
830 
831 	static bool shaderError;		// True if loading shaders caused errors
832 
833 	static bool shadowInitialized;
834 	static Vec2f shadowPolyOffset;
835 #ifdef DEBUG_SHADOWMAP
836 	static QOpenGLFramebufferObject* shadowFBO;
837 #else
838 	static unsigned int shadowFBO;
839 #endif
840 	static unsigned int shadowTex;
841 
842 
843 	static bool initShader();
844 	static void deinitShader();
845 	static bool initFBO();
846 	static void deinitFBO();
847 
848 	static QOpenGLShaderProgram* createShader(const QString& name,
849 						  PlanetShaderVars& vars,
850 						  const QByteArray& vSrc,
851 						  const QByteArray& fSrc,
852 						  const QByteArray& prefix=QByteArray(),
853 						  const QMap<QByteArray,int>& fixedAttributeLocations=QMap<QByteArray,int>());
854 
855 	// Cache of positions in the parent ecliptic coordinates in AU.
856 	// Used only for orbit plotting
857 	mutable QCache<double, Vec3d> orbitPositionsCache;
858 };
859 
860 #endif // PLANET_HPP
861