Planet.cpp   Planet.cpp 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA.
*/ */
#include <iomanip> #include <iomanip>
#include <QTextStream> #include <QTextStream>
#include <QString> #include <QString>
#include <QDebug> #include <QDebug>
#include <QVarLengthArray>
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelSkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "SolarSystem.hpp" #include "SolarSystem.hpp"
#include "StelTexture.hpp" #include "StelTexture.hpp"
#include "Planet.hpp" #include "Planet.hpp"
#include "StelNavigator.hpp" #include "StelNavigator.hpp"
#include "StelProjector.hpp" #include "StelProjector.hpp"
#include "StelFont.hpp"
#include "sideral_time.h" #include "sideral_time.h"
#include "StelTextureMgr.hpp" #include "StelTextureMgr.hpp"
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "StarMgr.hpp" #include "StarMgr.hpp"
#include "StelMovementMgr.hpp" #include "StelMovementMgr.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "StelTranslator.hpp"
StelFont* Planet::planetNameFont = NULL;
Vec3f Planet::labelColor = Vec3f(0.4,0.4,0.8); Vec3f Planet::labelColor = Vec3f(0.4,0.4,0.8);
Vec3f Planet::orbitColor = Vec3f(1,0.6,1); Vec3f Planet::orbitColor = Vec3f(1,0.6,1);
Vec3f Planet::trailColor = Vec3f(1,0.7,0.7); Vec3f Planet::trailColor = Vec3f(1,0.7,0.7);
StelTextureSP Planet::hintCircleTex; StelTextureSP Planet::hintCircleTex;
StelTextureSP Planet::texEarthShadow; StelTextureSP Planet::texEarthShadow;
Planet::Planet(const QString& englishName, Planet::Planet(const QString& englishName,
int flagLighting, int flagLighting,
double radius, double radius,
double oblateness, double oblateness,
Vec3f color, Vec3f color,
float albedo, float albedo,
const QString& atexMapName, const QString& atexMapName,
const QString& texHaloName, const QString& texHaloName,
posFuncType coordFunc, posFuncType coordFunc,
OsulatingFunctType *osculatingFunc, void* auserDataPtr,
bool acloseOrbit, OsulatingFunctType *osculatingFunc,
bool hidden, bool acloseOrbit,
bool hasAtmosphere) bool hidden,
bool hasAtmosphere)
: englishName(englishName), : englishName(englishName),
flagLighting(flagLighting), flagLighting(flagLighting),
radius(radius), oneMinusOblateness(1.0-oblateness), radius(radius), oneMinusOblateness(1.0-oblateness),
color(color), albedo(albedo), axisRotation(0.), rings(NULL), color(color), albedo(albedo), axisRotation(0.), rings(NULL),
sphereScale(1.f), sphereScale(1.f),
lastJD(J2000), lastJD(J2000),
coordFunc(coordFunc), coordFunc(coordFunc),
userDataPtr(auserDataPtr),
osculatingFunc(osculatingFunc), osculatingFunc(osculatingFunc),
parent(NULL), parent(NULL),
hidden(hidden), hidden(hidden),
atmosphere(hasAtmosphere) atmosphere(hasAtmosphere)
{ {
texMapName = atexMapName; texMapName = atexMapName;
lastOrbitJD =0; lastOrbitJD =0;
deltaJD = JD_SECOND; deltaJD = JD_SECOND;
orbitCached = 0; orbitCached = 0;
closeOrbit = acloseOrbit; closeOrbit = acloseOrbit;
eclipticPos=Vec3d(0.,0.,0.); eclipticPos=Vec3d(0.,0.,0.);
rotLocalToParent = Mat4d::identity(); rotLocalToParent = Mat4d::identity();
StelApp::getInstance().getTextureManager().setDefaultParams(); texMap = StelApp::getInstance().getTextureManager().createTexture(te
StelApp::getInstance().getTextureManager().setWrapMode(GL_REPEAT); xMapName, StelTexture::StelTextureParams(true, GL_LINEAR, GL_REPEAT));
texMap = StelApp::getInstance().getTextureManager().createTexture(te
xMapName);
// 60 day trails // 60 day trails
DeltaTrail = 1; DeltaTrail = 1;
// small increment like 0.125 would allow observation of latitude re lated wobble of moon // small increment like 0.125 would allow observation of latitude re lated wobble of moon
// if decide to show moon trail // if decide to show moon trail
MaxTrail = 60; MaxTrail = 60;
lastTrailJD = 0; // for now lastTrailJD = 0; // for now
trailOn = 0; trailOn = 0;
firstPoint = 1; firstPoint = 1;
skipping to change at line 109 skipping to change at line 109
} }
flagLabels = true; flagLabels = true;
} }
Planet::~Planet() Planet::~Planet()
{ {
if (rings) if (rings)
delete rings; delete rings;
} }
void Planet::setParent(Planet* newParent) void Planet::translateName(StelTranslator& trans) {nameI18 = trans.qtransla
{ te(englishName);}
Q_ASSERT(newParent);
newParent->satellites.push_back(this);
parent = newParent;
}
// Return the information string "ready to print" :) // Return the information string "ready to print" :)
QString Planet::getInfoString(const StelCore* core, const InfoStringGroup& flags) const QString Planet::getInfoString(const StelCore* core, const InfoStringGroup& flags) const
{ {
const StelNavigator* nav = core->getNavigator(); const StelNavigator* nav = core->getNavigator();
QString str; QString str;
QTextStream oss(&str); QTextStream oss(&str);
if (flags&Name) if (flags&Name)
skipping to change at line 235 skipping to change at line 230
{ {
return StelNavigator::matVsop87ToJ2000.multiplyWithoutTranslation(ge tHeliocentricEclipticPos() - nav->getObserverHeliocentricEclipticPos()); return StelNavigator::matVsop87ToJ2000.multiplyWithoutTranslation(ge tHeliocentricEclipticPos() - nav->getObserverHeliocentricEclipticPos());
} }
// Compute the position in the parent Planet coordinate system // Compute the position in the parent Planet coordinate system
// Actually call the provided function to compute the ecliptical position // Actually call the provided function to compute the ecliptical position
void Planet::computePositionWithoutOrbits(const double date) void Planet::computePositionWithoutOrbits(const double date)
{ {
if (fabs(lastJD-date)>deltaJD) if (fabs(lastJD-date)>deltaJD)
{ {
coordFunc(date, eclipticPos); coordFunc(date, eclipticPos, userDataPtr);
lastJD = date; lastJD = date;
} }
} }
void Planet::computePosition(const double date) void Planet::computePosition(const double date)
{ {
if (deltaOrbitJD > 0 && (fabs(lastOrbitJD-date)>deltaOrbitJD || !orb itCached)) if (orbitFader.getInterstate()>0.000001 && deltaOrbitJD > 0 && (fabs (lastOrbitJD-date)>deltaOrbitJD || !orbitCached))
{ {
// calculate orbit first (for line drawing) // calculate orbit first (for line drawing)
double date_increment = re.siderealPeriod/ORBIT_SEGMENTS; double date_increment = re.siderealPeriod/ORBIT_SEGMENTS;
double calc_date; double calc_date;
// int delta_points = (int)(0.5 + (date - lastOrbitJD)/date_ increment); // int delta_points = (int)(0.5 + (date - lastOrbitJD)/date_ increment);
int delta_points; int delta_points;
if( date > lastOrbitJD ) if( date > lastOrbitJD )
{ {
skipping to change at line 282 skipping to change at line 277
calc_date = new_date + (d-ORBIT_SEGM ENTS/2)*date_increment; calc_date = new_date + (d-ORBIT_SEGM ENTS/2)*date_increment;
// date increments between points wi ll not be completely constant though // date increments between points wi ll not be completely constant though
computeTransMatrix(calc_date); computeTransMatrix(calc_date);
if (osculatingFunc) if (osculatingFunc)
{ {
(*osculatingFunc)(date,calc_ date,eclipticPos); (*osculatingFunc)(date,calc_ date,eclipticPos);
} }
else else
{ {
coordFunc(calc_date, eclipti cPos); coordFunc(calc_date, eclipti cPos, userDataPtr);
} }
orbit[d] = getHeliocentricEclipticPo s(); orbit[d] = getHeliocentricEclipticPo s();
} }
else else
{ {
orbit[d] = orbit[d+delta_points]; orbit[d] = orbit[d+delta_points];
} }
} }
lastOrbitJD = new_date; lastOrbitJD = new_date;
skipping to change at line 310 skipping to change at line 305
{ {
// calculate new points // calculate new points
calc_date = new_date + (d-ORBIT_SEGM ENTS/2)*date_increment; calc_date = new_date + (d-ORBIT_SEGM ENTS/2)*date_increment;
computeTransMatrix(calc_date); computeTransMatrix(calc_date);
if (osculatingFunc) { if (osculatingFunc) {
(*osculatingFunc)(date,calc_ date,eclipticPos); (*osculatingFunc)(date,calc_ date,eclipticPos);
} }
else else
{ {
coordFunc(calc_date, eclipti cPos); coordFunc(calc_date, eclipti cPos, userDataPtr);
} }
orbit[d] = getHeliocentricEclipticPo s(); orbit[d] = getHeliocentricEclipticPo s();
} }
else else
{ {
orbit[d] = orbit[d+delta_points]; orbit[d] = orbit[d+delta_points];
} }
} }
lastOrbitJD = new_date; lastOrbitJD = new_date;
skipping to change at line 337 skipping to change at line 332
for( int d=0; d<ORBIT_SEGMENTS; d++ ) for( int d=0; d<ORBIT_SEGMENTS; d++ )
{ {
calc_date = date + (d-ORBIT_SEGMENTS/2)*date _increment; calc_date = date + (d-ORBIT_SEGMENTS/2)*date _increment;
computeTransMatrix(calc_date); computeTransMatrix(calc_date);
if (osculatingFunc) if (osculatingFunc)
{ {
(*osculatingFunc)(date,calc_date,ecl ipticPos); (*osculatingFunc)(date,calc_date,ecl ipticPos);
} }
else else
{ {
coordFunc(calc_date, eclipticPos); coordFunc(calc_date, eclipticPos, us erDataPtr);
} }
orbit[d] = getHeliocentricEclipticPos(); orbit[d] = getHeliocentricEclipticPos();
} }
lastOrbitJD = date; lastOrbitJD = date;
if (!osculatingFunc) orbitCached = 1; if (!osculatingFunc) orbitCached = 1;
} }
// calculate actual Planet position // calculate actual Planet position
coordFunc(date, eclipticPos); coordFunc(date, eclipticPos, userDataPtr);
lastJD = date; lastJD = date;
} }
else if (fabs(lastJD-date)>deltaJD) else if (fabs(lastJD-date)>deltaJD)
{ {
// calculate actual Planet position // calculate actual Planet position
coordFunc(date, eclipticPos); coordFunc(date, eclipticPos, userDataPtr);
lastJD = date; lastJD = date;
} }
} }
// Compute the transformation matrix from the local Planet coordinate to th e parent Planet coordinate // Compute the transformation matrix from the local Planet coordinate to th e parent Planet coordinate
void Planet::computeTransMatrix(double jd) void Planet::computeTransMatrix(double jd)
{ {
axisRotation = getSiderealTime(jd); axisRotation = getSiderealTime(jd);
skipping to change at line 379 skipping to change at line 374
{ {
rotLocalToParent = Mat4d::zrotation(re.ascendingNode - re.pr ecessionRate*(jd-re.epoch)) * Mat4d::xrotation(re.obliquity); rotLocalToParent = Mat4d::zrotation(re.ascendingNode - re.pr ecessionRate*(jd-re.epoch)) * Mat4d::xrotation(re.obliquity);
} }
} }
Mat4d Planet::getRotEquatorialToVsop87(void) const Mat4d Planet::getRotEquatorialToVsop87(void) const
{ {
Mat4d rval = rotLocalToParent; Mat4d rval = rotLocalToParent;
if (parent) if (parent)
{ {
for (const Planet *p=parent;p->parent;p=p->parent) for (PlanetP p=parent;p->parent;p=p->parent)
rval = p->rotLocalToParent * rval; rval = p->rotLocalToParent * rval;
} }
return rval; return rval;
} }
void Planet::setRotEquatorialToVsop87(const Mat4d &m) void Planet::setRotEquatorialToVsop87(const Mat4d &m)
{ {
Mat4d a = Mat4d::identity(); Mat4d a = Mat4d::identity();
if (parent) if (parent)
{ {
for (const Planet *p=parent;p->parent;p=p->parent) for (PlanetP p=parent;p->parent;p=p->parent)
a = p->rotLocalToParent * a; a = p->rotLocalToParent * a;
} }
rotLocalToParent = a.transpose() * m; rotLocalToParent = a.transpose() * m;
} }
// Compute the z rotation to use from equatorial to geographic coordinates // Compute the z rotation to use from equatorial to geographic coordinates
double Planet::getSiderealTime(double jd) const double Planet::getSiderealTime(double jd) const
{ {
if (englishName=="Earth") if (englishName=="Earth")
{ {
skipping to change at line 422 skipping to change at line 417
// Get the Planet position in the parent Planet ecliptic coordinate in AU // Get the Planet position in the parent Planet ecliptic coordinate in AU
Vec3d Planet::getEclipticPos() const Vec3d Planet::getEclipticPos() const
{ {
return eclipticPos; return eclipticPos;
} }
// Return the heliocentric ecliptical position (Vsop87) // Return the heliocentric ecliptical position (Vsop87)
Vec3d Planet::getHeliocentricEclipticPos() const Vec3d Planet::getHeliocentricEclipticPos() const
{ {
Vec3d pos = eclipticPos; Vec3d pos = eclipticPos;
const Planet *pp = parent; PlanetP pp = parent;
if (pp) if (pp)
{ {
while (pp->parent) while (pp->parent)
{ {
pos += pp->eclipticPos; pos += pp->eclipticPos;
pp = pp->parent; pp = pp->parent;
} }
} }
return pos; return pos;
} }
void Planet::setHeliocentricEclipticPos(const Vec3d &pos) void Planet::setHeliocentricEclipticPos(const Vec3d &pos)
{ {
eclipticPos = pos; eclipticPos = pos;
const Planet *p = parent; PlanetP p = parent;
if (p) while (p->parent) if (p)
{ {
eclipticPos -= p->eclipticPos; while (p->parent)
p = p->parent; {
eclipticPos -= p->eclipticPos;
p = p->parent;
}
} }
} }
// Compute the distance to the given position in heliocentric coordinate (i n AU) // Compute the distance to the given position in heliocentric coordinate (i n AU)
double Planet::computeDistance(const Vec3d& obsHelioPos) double Planet::computeDistance(const Vec3d& obsHelioPos)
{ {
distance = (obsHelioPos-getHeliocentricEclipticPos()).length(); distance = (obsHelioPos-getHeliocentricEclipticPos()).length();
return distance; return distance;
} }
// Get the phase angle for an observer at pos obsPos in the heliocentric co ordinate (dist in AU) // Get the phase angle for an observer at pos obsPos in the heliocentric co ordinate (dist in AU)
double Planet::getPhase(Vec3d obsPos) const double Planet::getPhase(const Vec3d& obsPos) const
{ {
const double sq = obsPos.lengthSquared(); const double observerRq = obsPos.lengthSquared();
const Vec3d heliopos = getHeliocentricEclipticPos(); const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double Rq = heliopos.lengthSquared(); const double planetRq = planetHelioPos.lengthSquared();
const double pq = (obsPos - heliopos).lengthSquared(); const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua
const double cos_chi = (pq + Rq - sq)/(2.0*sqrt(pq*Rq)); red();
return (1.0 - acos(cos_chi)/M_PI) * cos_chi + sqrt(1.0 - cos_chi*cos return std::acos(observerPlanetRq + planetRq - observerRq)/(2.0*sqrt
_chi) / M_PI; (observerPlanetRq*planetRq));
} }
// Computation of the visual magnitude (V band) of the planet.
float Planet::getVMagnitude(const StelNavigator * nav) const float Planet::getVMagnitude(const StelNavigator * nav) const
{ {
Vec3d obsPos = nav->getObserverHeliocentricEclipticPos();
const double sq = obsPos.lengthSquared();
if (parent == 0) if (parent == 0)
{ {
// sun, compute the apparent magnitude for the absolute mag (4.83) and observer's distance // sun, compute the apparent magnitude for the absolute mag (4.83) and observer's distance
double distParsec = std::sqrt(sq)*AU/PARSEC; const double distParsec = std::sqrt(nav->getObserverHeliocen tricEclipticPos().lengthSquared())*AU/PARSEC;
return 4.83 + 5.*(std::log10(distParsec)-1.); return 4.83 + 5.*(std::log10(distParsec)-1.);
} }
const Vec3d heliopos = getHeliocentricEclipticPos();
const double Rq = heliopos.lengthSquared();
const double pq = (obsPos - heliopos).lengthSquared();
const double cos_chi = (pq + Rq - sq)/(2.0*sqrt(pq*Rq));
const double phase = (1.0 - std::acos(cos_chi)/M_PI) * cos_chi + std
::sqrt(1.0 - cos_chi*cos_chi) / M_PI;
double F = 2.0 * albedo * radius * radius * phase / (3.0*pq*Rq);
// Compute the angular phase
const Vec3d& observerHelioPos = nav->getObserverHeliocentricEcliptic
Pos();
const double observerRq = observerHelioPos.lengthSquared();
const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double planetRq = planetHelioPos.lengthSquared();
const double observerPlanetRq = (observerHelioPos - planetHelioPos).
lengthSquared();
const double cos_chi = (observerPlanetRq + planetRq - observerRq)/(2
.0*sqrt(observerPlanetRq*planetRq));
double phase = std::acos(cos_chi);
double shadowFactor = 1.;
// Check if the satellite is inside the inner shadow of the parent p lanet: // Check if the satellite is inside the inner shadow of the parent p lanet:
if (parent->parent != 0) { if (parent->parent != 0)
const Vec3d parent_heliopos = parent->getHeliocentricEclipti {
cPos(); const Vec3d& parentHeliopos = parent->getHeliocentricEclipti
const double parent_Rq = parent_heliopos.lengthSquared(); cPos();
const double pos_times_parent_pos = heliopos * parent_heliop const double parent_Rq = parentHeliopos.lengthSquared();
os; const double pos_times_parent_pos = planetHelioPos * parentH
if (pos_times_parent_pos > parent_Rq) { eliopos;
if (pos_times_parent_pos > parent_Rq)
{
// The satellite is farther away from the sun than t he parent planet. // The satellite is farther away from the sun than t he parent planet.
const double sun_radius = parent->parent->radius; const double sun_radius = parent->parent->radius;
const double sun_minus_parent_radius = sun_radius - parent->radius; const double sun_minus_parent_radius = sun_radius - parent->radius;
const double quot = pos_times_parent_pos/parent_Rq; const double quot = pos_times_parent_pos/parent_Rq;
// compute d = distance from satellite center to bor
der // Compute d = distance from satellite center to bor
// of inner shadow. d>0 means inside the shadow cone der of inner shadow.
. // d>0 means inside the shadow cone.
double d = sun_radius - sun_minus_parent_radius*quot double d = sun_radius - sun_minus_parent_radius*quot
- std::sqrt( (1.0-sun_minus_parent_radius/sqrt(paren - std::sqrt((1.-sun_minus_parent_radius/sqrt(parent_Rq)) * (planetRq-pos_t
t_Rq)) imes_parent_pos*quot));
* (Rq-pos_times_parent_pos*quot) ); if (d>=radius)
if (d >= radius)
{ {
// The satellite is totally inside the inner shadow. // The satellite is totally inside the inner shadow.
F *= 1e-9; shadowFactor = 1e-9;
} }
else if (d > -radius) else if (d>-radius)
{ {
// The satellite is partly inside the inner shadow, // The satellite is partly inside the inner shadow,
// compute a fantasy value for the magnitude : // compute a fantasy value for the magnitude :
d /= radius; d /= radius;
F *= (0.5 - (std::asin(d)+d*std::sqrt(1.0-d* d))/M_PI); shadowFactor = (0.5 - (std::asin(d)+d*std::s qrt(1.0-d*d))/M_PI);
} }
} }
} }
const double rval = -26.73 - 2.5 * std::log10(F); // Use empirical formulae for main planets when seen from earth
//qDebug() << "Planet(" << getEnglishName() // Algorithm provided by Pere Planesas (Observatorio Astronomico Nac
// << ")::getVMagnitude(" << obsPos << "): " ional)
// << "phase: " << phase if (nav->getCurrentLocation().planetName=="Earth")
// << ",F: " << F {
// << ",rval: " << rval; phase*=180./M_PI;
return rval; const double d = 5. * log10(sqrt(observerPlanetRq*planetRq))
;
double f1 = phase/100.;
if (englishName=="Mercury")
{
if ( phase > 150. ) f1 = 1.5;
return -0.36 + d + 3.8*f1 - 2.73*f1*f1 + 2*f1*f1*f1;
}
if (englishName=="Venus")
return -4.29 + d + 0.09*f1 + 2.39*f1*f1 - 0.65*f1*f1
*f1;
if (englishName=="Mars")
return -1.52 + d + 0.016*phase;
if (englishName=="Jupiter")
return -9.25 + d + 0.005*phase;
if (englishName=="Saturn")
{
// TODO re-add rings computation
// double rings = -2.6*sinx + 1.25*sinx*sinx;
return -8.88 + d + 0.044*phase;// + rings;
}
if (englishName=="Uranus")
return -7.19 + d + 0.0028*phase;
if (englishName=="Neptune")
return -6.87 + d;
if (englishName=="Pluto")
return -1.01 + d + 0.041*phase;
phase/=180./M_PI;
}
// This formula seems to give wrong results
const double p = (1.0 - phase/M_PI) * cos_chi + std::sqrt(1.0 - cos_
chi*cos_chi) / M_PI;
double F = 2.0 * albedo * radius * radius * p / (3.0*observerPlanetR
q*planetRq) * shadowFactor;
return -26.73 - 2.5 * std::log10(F);
} }
double Planet::getAngularSize(const StelCore* core) const double Planet::getAngularSize(const StelCore* core) const
{ {
double rad = radius; double rad = radius;
if (rings) if (rings)
rad = rings->getSize(); rad = rings->getSize();
return std::atan2(rad*sphereScale,getJ2000EquatorialPos(core->getNav igator()).length()) * 180./M_PI; return std::atan2(rad*sphereScale,getJ2000EquatorialPos(core->getNav igator()).length()) * 180./M_PI;
} }
double Planet::getSpheroidAngularSize(const StelCore* core) const double Planet::getSpheroidAngularSize(const StelCore* core) const
{ {
return std::atan2(radius*sphereScale,getJ2000EquatorialPos(core->get Navigator()).length()) * 180./M_PI; return std::atan2(radius*sphereScale,getJ2000EquatorialPos(core->get Navigator()).length()) * 180./M_PI;
} }
// Draw the Planet and all the related infos : name, circle etc.. // Draw the Planet and all the related infos : name, circle etc..
void Planet::draw(StelCore* core, float maxMagLabels) void Planet::draw(StelCore* core, float maxMagLabels, const QFont& planetNa meFont)
{ {
if (hidden) if (hidden)
return; return;
StelNavigator* nav = core->getNavigator(); StelNavigator* nav = core->getNavigator();
Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
const Planet *p = parent; PlanetP p = parent;
while (p && p->parent) while (p && p->parent)
{ {
mat = Mat4d::translation(p->eclipticPos) * mat * p->rotLocal ToParent; mat = Mat4d::translation(p->eclipticPos) * mat * p->rotLocal ToParent;
p = p->parent; p = p->parent;
} }
// This removed totally the Planet shaking bug!!! // This removed totally the Planet shaking bug!!!
mat = nav->getHeliocentricEclipticModelViewMat() * mat; mat = nav->getHeliocentricEclipticModelViewMat() * mat;
if (this == nav->getHomePlanet()) if (getEnglishName() == nav->getCurrentLocation().planetName)
{ {
// Draw the rings if we are located on a planet with rings, but not the planet itself.
if (rings) if (rings)
{ {
StelPainter sPainter(core->getProjection(mat)); StelPainter sPainter(core->getProjection(mat));
rings->draw(&sPainter,mat,1000.0); rings->draw(&sPainter,mat,1000.0);
} }
return; return;
} }
// Compute the 2D position and check if in the screen // Compute the 2D position and check if in the screen
const StelProjectorP prj = core->getProjection(mat); const StelProjectorP prj = core->getProjection(mat);
float screenSz = getAngularSize(core)*M_PI/180.*prj->getPixelPerRadA tCenter(); float screenSz = getAngularSize(core)*M_PI/180.*prj->getPixelPerRadA tCenter();
float viewport_left = prj->getViewportPosX(); float viewport_left = prj->getViewportPosX();
float viewport_bottom = prj->getViewportPosY(); float viewport_bottom = prj->getViewportPosY();
if (prj->project(Vec3f(0,0,0), screenPos) && if (prj->project(Vec3f(0,0,0), screenPos) &&
screenPos[1]>viewport_bottom - screenSz && screenPos[1]<view screenPos[1]>viewport_bottom - screenSz && screenPos
port_bottom + prj->getViewportHeight()+screenSz && [1]<viewport_bottom + prj->getViewportHeight()+screenSz &&
screenPos[0]>viewport_left - screenSz && screenPos[0]<viewpo screenPos[0]>viewport_left - screenSz && screenPos[0
rt_left + prj->getViewportWidth() + screenSz) ]<viewport_left + prj->getViewportWidth() + screenSz)
{ {
// Draw the name, and the circle if it's not too close from the body it's turning around // Draw the name, and the circle if it's not too close from the body it's turning around
// this prevents name overlaping (ie for jupiter satellites) // this prevents name overlaping (ie for jupiter satellites)
float ang_dist = 300.f*atan(getEclipticPos().length()/getEqu inoxEquatorialPos(nav).length())/core->getMovementMgr()->getCurrentFov(); float ang_dist = 300.f*atan(getEclipticPos().length()/getEqu inoxEquatorialPos(nav).length())/core->getMovementMgr()->getCurrentFov();
if (ang_dist==0.f) if (ang_dist==0.f)
ang_dist = 1.f; // if ang_dist == 0, the Planet is s un.. ang_dist = 1.f; // if ang_dist == 0, the Planet is s un..
// by putting here, only draw orbit if Planet is visible for clarity // by putting here, only draw orbit if Planet is visible for clarity
drawOrbit(core); // TODO - fade in here also... drawOrbit(core); // TODO - fade in here also...
drawTrail(core); drawTrail(core);
if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitud e(nav)) if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitud e(nav))
{ {
labelsFader=true; labelsFader=true;
} }
else else
{ {
labelsFader=false; labelsFader=false;
} }
drawHints(core); drawHints(core, planetNameFont);
draw3dModel(core,mat,screenSz); draw3dModel(core,mat,screenSz);
} }
return; return;
} }
void Planet::draw3dModel(StelCore* core, const Mat4d& mat, float screenSz) void Planet::draw3dModel(StelCore* core, const Mat4d& mat, float screenSz)
{ {
// This is the main method drawing a planet 3d model // This is the main method drawing a planet 3d model
// Some work has to be done on this method to make the rendering nic er // Some work has to be done on this method to make the rendering nic er
StelNavigator* nav = core->getNavigator(); StelNavigator* nav = core->getNavigator();
if (screenSz>1.) if (screenSz>1.)
{ {
StelPainter* sPainter = new StelPainter(core->getProjection( mat * Mat4d::zrotation(M_PI/180*(axisRotation + 90.)))); StelPainter* sPainter = new StelPainter(core->getProjection( mat * Mat4d::zrotation(M_PI/180*(axisRotation + 90.))));
if (flagLighting) if (flagLighting)
{ {
glEnable(GL_LIGHTING); sPainter->getLight().enable();
// Set the main source of light to be the sun // Set the main source of light to be the sun
const Vec3d sunPos = core->getNavigator()->getHelioc const Vec3d& sunPos = core->getNavigator()->getHelio
entricEclipticModelViewMat()*Vec3d(0,0,0); centricEclipticModelViewMat()*Vec3d(0,0,0);
glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(sunPos[0],sunP sPainter->getLight().setPosition(Vec4f(sunPos[0],sun
os[1],sunPos[2],1.f)); Pos[1],sunPos[2],1.f));
const float diffuse[4] = {2.,2.,2.,1};
glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse);
// Set the light parameters taking sun as the light source // Set the light parameters taking sun as the light source
const float zero[4] = {0,0,0,0}; static const Vec4f diffuse = Vec4f(2.,2.,2.,1);
const float ambient[4] = {0.02,0.02,0.02,0.02}; static const Vec4f zero = Vec4f(0,0,0,0);
glLightfv(GL_LIGHT0,GL_AMBIENT, ambient); static const Vec4f ambient = Vec4f(0.02,0.02,0.02,0.
glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse); 02);
glLightfv(GL_LIGHT0,GL_SPECULAR,zero); sPainter->getLight().setAmbient(ambient);
glMaterialfv(GL_FRONT,GL_AMBIENT, ambient); sPainter->getLight().setDiffuse(diffuse);
glMaterialfv(GL_FRONT,GL_EMISSION, zero); sPainter->getLight().setSpecular(zero);
glMaterialfv(GL_FRONT,GL_SHININESS,zero);
glMaterialfv(GL_FRONT,GL_SPECULAR, zero); sPainter->getMaterial().setAmbient(ambient);
sPainter->getMaterial().setEmission(zero);
sPainter->getMaterial().setShininess(0);
sPainter->getMaterial().setSpecular(zero);
} }
else else
{ {
glDisable(GL_LIGHTING); sPainter->getLight().disable();
glColor3fv(Vec3f(1.f,1.f,1.f)); sPainter->setColor(1.f,1.f,1.f);
} }
if (rings) if (rings)
{ {
const double dist = getEquinoxEquatorialPos(nav).len gth(); const double dist = getEquinoxEquatorialPos(nav).len gth();
double z_near = 0.9*(dist - rings->getSize()); double z_near = 0.9*(dist - rings->getSize());
double z_far = 1.1*(dist + rings->getSize()); double z_far = 1.1*(dist + rings->getSize());
if (z_near < 0.0) z_near = 0.0; if (z_near < 0.0) z_near = 0.0;
double n,f; double n,f;
core->getClippingPlanes(&n,&f); // Save clipping pla nes core->getClippingPlanes(&n,&f); // Save clipping pla nes
core->setClippingPlanes(z_near,z_far); core->setClippingPlanes(z_near,z_far);
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
drawSphere(sPainter, screenSz); drawSphere(sPainter, screenSz);
glDisable(GL_LIGHTING); glDepthMask(GL_FALSE);
sPainter->getLight().disable();
rings->draw(sPainter,mat,screenSz); rings->draw(sPainter,mat,screenSz);
glEnable(GL_LIGHTING); sPainter->getLight().enable();
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
core->setClippingPlanes(n,f); // Restore old clippi ng planes core->setClippingPlanes(n,f); // Restore old clippi ng planes
} }
else else
{ {
SolarSystem* ssm = GETSTELMODULE(SolarSystem); SolarSystem* ssm = GETSTELMODULE(SolarSystem);
if (this==ssm->getMoon() && nav->getHomePlanet()==ss m->getEarth() && ssm->nearLunarEclipse()) if (this==ssm->getMoon() && nav->getCurrentLocation( ).planetName=="Earth" && ssm->nearLunarEclipse())
{ {
// Draw earth shadow over moon using stencil buffer if appropriate // Draw earth shadow over moon using stencil buffer if appropriate
// This effect curently only looks right fro m earth viewpoint // This effect curently only looks right fro m earth viewpoint
// TODO: moon magnitude label during eclipse isn't accurate... // TODO: moon magnitude label during eclipse isn't accurate...
glClearStencil(0x0); glClearStencil(0x0);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 0x1, 0x1); glStencilFunc(GL_ALWAYS, 0x1, 0x1);
glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE) ; glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE) ;
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
drawSphere(sPainter, screenSz); drawSphere(sPainter, screenSz);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING); sPainter->getLight().disable();
delete sPainter; drawEarthShadow(core, sPainter);
sPainter=NULL;
drawEarthShadow(core);
} }
else else
{ {
// Normal planet // Normal planet
drawSphere(sPainter, screenSz); drawSphere(sPainter, screenSz);
} }
} }
if (sPainter) if (sPainter)
delete sPainter; delete sPainter;
sPainter=NULL; sPainter=NULL;
} }
// Draw the halo // Draw the halo
// Prepare openGL lighting parameters according to luminance // Prepare openGL lighting parameters according to luminance
float surfArcMin2 = getSpheroidAngularSize(core)*60; float surfArcMin2 = getSpheroidAngularSize(core)*60;
surfArcMin2 = surfArcMin2*surfArcMin2*M_PI; // the total illuminated area in arcmin^2 surfArcMin2 = surfArcMin2*surfArcMin2*M_PI; // the total illuminated area in arcmin^2
StelPainter sPainter(core->getProjection(StelCore::FrameJ2000)); StelPainter sPainter(core->getProjection(StelCore::FrameJ2000));
core->getSkyDrawer()->postDrawSky3dModel(screenPos[0],screenPos[1], surfArcMin2, getVMagnitude(core->getNavigator()), &sPainter, color); core->getSkyDrawer()->postDrawSky3dModel(&sPainter, getJ2000Equatori alPos(nav), surfArcMin2, getVMagnitude(core->getNavigator()), color);
} }
void Planet::drawSphere(const StelPainter* painter, float screenSz) void Planet::drawSphere(StelPainter* painter, float screenSz)
{ {
glEnable(GL_TEXTURE_2D); painter->enableTexture2d(true);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
if (texMap) if (texMap)
texMap->bind(); texMap->bind();
// Draw the spheroid itself // Draw the spheroid itself
// Adapt the number of facets according with the size of the sphere for optimization // Adapt the number of facets according with the size of the sphere for optimization
int nb_facet = (int)(screenSz * 40/50); // 40 facets for 1024 pixels diameter on screen int nb_facet = (int)(screenSz * 40/50); // 40 facets for 1024 pixels diameter on screen
if (nb_facet<10) nb_facet = 10; if (nb_facet<10) nb_facet = 10;
if (nb_facet>40) nb_facet = 40; if (nb_facet>40) nb_facet = 40;
glShadeModel(GL_SMOOTH); painter->setShadeModel(StelPainter::ShadeModelSmooth);
// Rotate and add an extra quarter rotation so that the planet textu re map // Rotate and add an extra quarter rotation so that the planet textu re map
// fits to the observers position. No idea why this is necessary, // fits to the observers position. No idea why this is necessary,
// perhaps some openGl strangeness, or confusing sin/cos. // perhaps some openGl strangeness, or confusing sin/cos.
painter->sSphere(radius*sphereScale, oneMinusOblateness, nb_facet, n b_facet); painter->sSphere(radius*sphereScale, oneMinusOblateness, nb_facet, n b_facet);
glShadeModel(GL_FLAT); painter->setShadeModel(StelPainter::ShadeModelFlat);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }
// draws earth shadow overlapping the moon using stencil buffer // draws earth shadow overlapping the moon using stencil buffer
// umbra and penumbra are sized separately for accuracy // umbra and penumbra are sized separately for accuracy
void Planet::drawEarthShadow(StelCore* core) void Planet::drawEarthShadow(StelCore* core, StelPainter* sPainter)
{ {
SolarSystem* ssm = GETSTELMODULE(SolarSystem); SolarSystem* ssm = GETSTELMODULE(SolarSystem);
Vec3d e = ssm->getEarth()->getEclipticPos(); Vec3d e = ssm->getEarth()->getEclipticPos();
Vec3d m = ssm->getMoon()->getEclipticPos(); // relative to earth Vec3d m = ssm->getMoon()->getEclipticPos(); // relative to earth
Vec3d mh = ssm->getMoon()->getHeliocentricEclipticPos(); // relativ e to sun Vec3d mh = ssm->getMoon()->getHeliocentricEclipticPos(); // relativ e to sun
float mscale = ssm->getMoon()->getSphereScale(); float mscale = ssm->getMoon()->getSphereScale();
// shadow location at earth + moon distance along earth vector from sun // shadow location at earth + moon distance along earth vector from sun
Vec3d en = e; Vec3d en = e;
en.normalize(); en.normalize();
skipping to change at line 745 skipping to change at line 779
// find vector orthogonal to sun-earth vector using cross product wi th // find vector orthogonal to sun-earth vector using cross product wi th
// a non-parallel vector // a non-parallel vector
Vec3d rpt = shadow^Vec3d(0,0,1); Vec3d rpt = shadow^Vec3d(0,0,1);
rpt.normalize(); rpt.normalize();
Vec3d upt = rpt*r_umbra*mscale*1.02; // point on umbra edge Vec3d upt = rpt*r_umbra*mscale*1.02; // point on umbra edge
rpt *= r_penumbra*mscale; // point on penumbra edge rpt *= r_penumbra*mscale; // point on penumbra edge
// modify shadow location for scaled moon // modify shadow location for scaled moon
Vec3d mdist = shadow - mh; Vec3d mdist = shadow - mh;
if(mdist.length() > r_penumbra + 2000./AU) if (mdist.length() > r_penumbra + 2000./AU)
return; // not visible so don't bother drawing return; // not visible so don't bother drawing
shadow = mh + mdist*mscale; shadow = mh + mdist*mscale;
r_penumbra *= mscale; r_penumbra *= mscale;
const StelProjectorP prj = core->getProjection(StelCore::FrameHelioc StelProjectorP saveProj = sPainter->getProjector();
entricEcliptic); sPainter->setProjector(core->getProjection(StelCore::FrameHeliocentr
StelPainter sPainter(prj); icEcliptic));
glEnable(GL_TEXTURE_2D); sPainter->enableTexture2d(true);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor3f(1,1,1); sPainter->setColor(1,1,1);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
// We draw only where the stencil buffer is at 1, i.e. where the moo n was drawn
glStencilFunc(GL_EQUAL, 0x1, 0x1); glStencilFunc(GL_EQUAL, 0x1, 0x1);
// Don't change stencil buffer value
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// shadow radial texture // shadow radial texture
texEarthShadow->bind(); texEarthShadow->bind();
Vec3d r, s; Vec3d r;
// umbra first
glBegin(GL_TRIANGLE_FAN);
// johannes: work-around for nasty ATI rendering bug:
// use y-texture coordinate of 0.5 instead of 0.0
glTexCoord2f(0.f,0.5f);
sPainter.drawVertex3v(shadow);
for (int i=0; i<=100; i++) // Draw umbra first
{ QVarLengthArray<Vec2f, 210> texCoordArray(210);
r = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * upt; QVarLengthArray<Vec3d, 210> vertexArray(210);
s = shadow + r; texCoordArray[0].set(0.f, 0.5);
// johannes: work-around for nasty ATI rendering bug: use y-texture
glTexCoord2f(0.6f,0.5f); // position in texture of umbra ed coordinate of 0.5 instead of 0.0
ge vertexArray[0]=shadow;
sPainter.drawVertex3v(s);
const Mat4d& rotMat = Mat4d::rotation(shadow, 2.*M_PI/100.);
r = upt;
for (int i=1; i<=101; ++i)
{
// position in texture of umbra edge
texCoordArray[i].set(0.6, 0.5);
r.transfo4d(rotMat);
vertexArray[i] = shadow + r;
} }
glEnd(); sPainter->setArrays(vertexArray.constData(), texCoordArray.constData
());
sPainter->drawFromArray(StelPainter::TriangleFan, 102);
// now penumbra // now penumbra
Vec3d u, sp; Vec3d u;
glBegin(GL_TRIANGLE_STRIP); r = rpt;
for (int i=0; i<=100; i++) u = upt;
{ for (int i=0; i<=200; i+=2)
r = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * rpt; {
u = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * upt; r.transfo4d(rotMat);
s = shadow + r; u.transfo4d(rotMat);
sp = shadow + u; texCoordArray[i].set(0.6, 0.5);
texCoordArray[i+1].set(1., 0.5); // position in texture of u
glTexCoord2f(0.6f,0.5f); mbra edge
sPainter.drawVertex3v(sp); vertexArray[i] = shadow + u;
vertexArray[i+1] = shadow + r;
glTexCoord2f(1.f,0.5f); // position in texture of umbra edg
e
sPainter.drawVertex3v(s);
} }
glEnd(); sPainter->setArrays(vertexArray.constData(), texCoordArray.constData
());
sPainter->drawFromArray(StelPainter::TriangleStrip, 202);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
glClearStencil(0x0); glClearStencil(0x0);
glClear(GL_STENCIL_BUFFER_BIT); // Clean again to let a clean buffer for later Qt display glClear(GL_STENCIL_BUFFER_BIT); // Clean again to let a clean buffer for later Qt display
sPainter->setProjector(saveProj);
} }
void Planet::drawHints(const StelCore* core) void Planet::drawHints(const StelCore* core, const QFont& planetNameFont)
{ {
if (labelsFader.getInterstate()<=0.f) if (labelsFader.getInterstate()<=0.f)
return; return;
const StelNavigator* nav = core->getNavigator(); const StelNavigator* nav = core->getNavigator();
const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ;
StelPainter sPainter(prj); StelPainter sPainter(prj);
sPainter.setFont(planetNameFont);
// Draw nameI18 + scaling if it's not == 1. // Draw nameI18 + scaling if it's not == 1.
float tmp = 10.f + getAngularSize(core)*M_PI/180.*prj->getPixelPerRa dAtCenter()/1.44; // Shift for nameI18 printing float tmp = 10.f + getAngularSize(core)*M_PI/180.*prj->getPixelPerRa dAtCenter()/1.44; // Shift for nameI18 printing
glColor4f(labelColor[0], labelColor[1], labelColor[2],labelsFader.ge sPainter.setColor(labelColor[0], labelColor[1], labelColor[2],labels
tInterstate()); Fader.getInterstate());
sPainter.drawText(planetNameFont,screenPos[0],screenPos[1], getSkyLa sPainter.drawText(screenPos[0],screenPos[1], getSkyLabel(nav), 0, tm
bel(nav), 0, tmp, tmp, false); p, tmp, false);
// hint disapears smoothly on close view // hint disapears smoothly on close view
if (hintFader.getInterstate()<=0) if (hintFader.getInterstate()<=0)
return; return;
tmp -= 10.f; tmp -= 10.f;
if (tmp<1) tmp=1; if (tmp<1) tmp=1;
glColor4f(labelColor[0], labelColor[1], labelColor[2],labelsFader.ge tInterstate()*hintFader.getInterstate()/tmp*0.7); sPainter.setColor(labelColor[0], labelColor[1], labelColor[2],labels Fader.getInterstate()*hintFader.getInterstate()/tmp*0.7);
// Draw the 2D small circle // Draw the 2D small circle
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D); sPainter.enableTexture2d(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Planet::hintCircleTex->bind(); Planet::hintCircleTex->bind();
sPainter.drawSprite2dMode(screenPos[0], screenPos[1], 22); sPainter.drawSprite2dMode(screenPos[0], screenPos[1], 11);
} }
Ring::Ring(double radiusMin,double radiusMax,const QString &texname) Ring::Ring(double radiusMin,double radiusMax,const QString &texname)
:radiusMin(radiusMin),radiusMax(radiusMax) :radiusMin(radiusMin),radiusMax(radiusMax)
{ {
tex = StelApp::getInstance().getTextureManager().createTexture(texna me); tex = StelApp::getInstance().getTextureManager().createTexture(texna me);
} }
Ring::~Ring(void) Ring::~Ring(void)
{ {
} }
void Ring::draw(const StelPainter* painter,const Mat4d& mat,double screenSz ) void Ring::draw(StelPainter* sPainter,const Mat4d& mat,double screenSz)
{ {
screenSz -= 50; screenSz -= 50;
screenSz /= 250.0; screenSz /= 250.0;
if (screenSz < 0.0) screenSz = 0.0; if (screenSz < 0.0) screenSz = 0.0;
else if (screenSz > 1.0) screenSz = 1.0; else if (screenSz > 1.0) screenSz = 1.0;
const int slices = 128+(int)((256-128)*screenSz); const int slices = 128+(int)((256-128)*screenSz);
const int stacks = 8+(int)((32-8)*screenSz); const int stacks = 8+(int)((32-8)*screenSz);
// Normal transparency mode // Normal transparency mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor3f(1.f, 1.f, 1.f); sPainter->setColor(1.f, 1.f, 1.f);
glEnable(GL_TEXTURE_2D); sPainter->enableTexture2d(true);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glEnable(GL_BLEND); glEnable(GL_BLEND);
if (tex) tex->bind(); if (tex) tex->bind();
// solve the ring wraparound by culling: // solve the ring wraparound by culling:
// decide if we are above or below the ring plane // decide if we are above or below the ring plane
const double h = mat.r[ 8]*mat.r[12] const double h = mat.r[ 8]*mat.r[12]
+ mat.r[ 9]*mat.r[13] + mat.r[ 9]*mat.r[13]
+ mat.r[10]*mat.r[14]; + mat.r[10]*mat.r[14];
painter->sRing(radiusMin,radiusMax,(h<0.0)?slices:-slices,stacks, 0) sPainter->sRing(radiusMin,radiusMax,(h<0.0)?slices:-slices,stacks, 0
; );
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }
// draw orbital path of Planet // draw orbital path of Planet
void Planet::drawOrbit(const StelCore* core) void Planet::drawOrbit(const StelCore* core)
{ {
if (!orbitFader.getInterstate()) if (!orbitFader.getInterstate())
return; return;
if (!re.siderealPeriod) if (!re.siderealPeriod)
return; return;
const StelProjectorP prj = core->getProjection(StelCore::FrameHelioc entricEcliptic); const StelProjectorP prj = core->getProjection(StelCore::FrameHelioc entricEcliptic);
StelPainter sPainter(prj); StelPainter sPainter(prj);
// Normal transparency mode // Normal transparency mode
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glColor4f(orbitColor[0], orbitColor[1], orbitColor[2], orbitFader.ge sPainter.setColor(orbitColor[0], orbitColor[1], orbitColor[2], orbit
tInterstate()); Fader.getInterstate());
int on=0;
int d;
Vec3d onscreen; Vec3d onscreen;
for( int n=0; n<=ORBIT_SEGMENTS; n++) // special case - use current Planet position as center vertex so th
at draws
// on it's orbit all the time (since segmented rather than smooth cu
rve)
Vec3d savePos = orbit[ORBIT_SEGMENTS/2];
orbit[ORBIT_SEGMENTS/2]=getHeliocentricEclipticPos();
orbit[ORBIT_SEGMENTS]=orbit[0];
int nbIter = closeOrbit ? ORBIT_SEGMENTS : ORBIT_SEGMENTS-1;
QVarLengthArray<float, 1024> vertexArray;
sPainter.enableClientStates(true, false, false);
for (int n=0; n<=nbIter; ++n)
{ {
if( n==ORBIT_SEGMENTS ) if (prj->project(orbit[n],onscreen))
{
d = 0; // connect loop
if (!closeOrbit) break;
}
else
{ {
d = n; vertexArray.append(onscreen[0]);
vertexArray.append(onscreen[1]);
} }
else if (!vertexArray.isEmpty())
// special case - use current Planet position as center vert
ex so that draws
// on it's orbit all the time (since segmented rather than s
mooth curve)
if( n == ORBIT_SEGMENTS/2 )
{ {
if(prj->project(getHeliocentricEclipticPos(), onscre sPainter.setVertexPointer(2, GL_FLOAT, vertexArray.c
en)) onstData());
{ sPainter.drawFromArray(StelPainter::LineStrip, verte
if(!on) glBegin(GL_LINE_STRIP); xArray.size()/2, 0, false);
glVertex3d(onscreen[0], onscreen[1], 0); vertexArray.clear();
on=1;
}
else if( on )
{
glEnd();
on=0;
}
}
else
{
if(prj->project(orbit[d],onscreen))
{
if(!on) glBegin(GL_LINE_STRIP);
glVertex3d(onscreen[0], onscreen[1], 0);
on=1;
}
else if( on )
{
glEnd();
on=0;
}
} }
} }
orbit[ORBIT_SEGMENTS/2]=savePos;
if (on) if (!vertexArray.isEmpty())
glEnd(); {
sPainter.setVertexPointer(2, GL_FLOAT, vertexArray.constData
());
sPainter.drawFromArray(StelPainter::LineStrip, vertexArray.s
ize()/2, 0, false);
}
sPainter.enableClientStates(false);
} }
// draw trail of Planet as seen from earth // draw trail of Planet as seen from earth
void Planet::drawTrail(const StelCore* core) void Planet::drawTrail(const StelCore* core)
{ {
if (!trailFader.getInterstate()) if (!trailFader.getInterstate())
return; return;
const StelNavigator* nav = core->getNavigator(); const StelNavigator* nav = core->getNavigator();
const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ;
Vec3d onscreen1; Vec3d onscreen1;
Vec3d onscreen2; Vec3d onscreen2;
StelPainter sPainter(prj); StelPainter sPainter(prj);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glColor3fv(trailColor*trailFader.getInterstate()); sPainter.setColor(trailColor[0]*trailFader.getInterstate(), trailCol or[1]*trailFader.getInterstate(), trailColor[2]*trailFader.getInterstate(), 1.);
std::list<TrailPoint>::iterator iter; std::list<TrailPoint>::iterator iter;
std::list<TrailPoint>::iterator nextiter; std::list<TrailPoint>::iterator nextiter;
std::list<TrailPoint>::iterator begin = trail.begin(); std::list<TrailPoint>::iterator begin = trail.begin();
// begin++; // begin++;
if(trail.begin() != trail.end()) if (trail.begin() != trail.end())
{ {
nextiter = trail.end(); nextiter = trail.end();
nextiter--; nextiter--;
for( iter=nextiter; iter != begin; iter--) for (iter=nextiter; iter != begin; --iter)
{ {
nextiter--; nextiter--;
if( prj->projectLineCheck( (*iter).point, onscreen1, if (prj->projectLineCheck( (*iter).point, onscreen1,
(*(nextiter)).point, onscreen2) ) (*(nextiter)).point, onscreen2))
{ sPainter.drawLine2d(onscreen1[0], onscreen1[
glBegin(GL_LINE_STRIP); 1], onscreen2[0], onscreen2[1]);
glVertex2d(onscreen1[0], onscreen1[1]);
glVertex2d(onscreen2[0], onscreen2[1]);
glEnd();
}
} }
} }
// draw final segment to finish at current Planet position // draw final segment to finish at current Planet position
if( !firstPoint && prj->projectLineCheck( (*trail.begin()).point, on if (!firstPoint && prj->projectLineCheck( (*trail.begin()).point, on
screen1, getEquinoxEquatorialPos(nav), onscreen2) ) screen1, getEquinoxEquatorialPos(nav), onscreen2))
{ sPainter.drawLine2d(onscreen1[0], onscreen1[1], onscreen2[0]
glBegin(GL_LINE_STRIP); , onscreen2[1]);
glVertex2d(onscreen1[0], onscreen1[1]);
glVertex2d(onscreen2[0], onscreen2[1]);
glEnd();
}
} }
// update trail points as needed // update trail points as needed
void Planet::updateTrail(const StelNavigator* nav) void Planet::updateTrail(const StelNavigator* nav)
{ {
if (!trailOn) if (!trailOn)
return; return;
double date = nav->getJDay(); double date = nav->getJDay();
 End of changes. 88 change blocks. 
246 lines changed or deleted 270 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/