Planet.cpp   Planet.cpp 
skipping to change at line 28 skipping to change at line 28
*/ */
#include <iomanip> #include <iomanip>
#include <QTextStream> #include <QTextStream>
#include <QString> #include <QString>
#include <QDebug> #include <QDebug>
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "SkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "SolarSystem.hpp" #include "SolarSystem.hpp"
#include "STexture.hpp" #include "StelTexture.hpp"
#include "Planet.hpp" #include "Planet.hpp"
#include "Navigator.hpp" #include "StelNavigator.hpp"
#include "Projector.hpp" #include "StelProjector.hpp"
#include "SFont.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 "StelPainter.hpp"
SFont* Planet::planetNameFont = NULL; 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);
STextureSP Planet::hintCircleTex; StelTextureSP Planet::hintCircleTex;
StelTextureSP Planet::texEarthShadow;
Planet::Planet(Planet *parent, Planet::Planet(const QString& englishName,
const QString& englishName,
int flagHalo,
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, OsulatingFunctType *osculatingFunc,
bool acloseOrbit, bool acloseOrbit,
bool hidden, bool hidden,
bool hasAtmosphere) bool hasAtmosphere)
: englishName(englishName), : englishName(englishName),
flagHalo(flagHalo),
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),
osculatingFunc(osculatingFunc), osculatingFunc(osculatingFunc),
parent(parent), 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;
if (parent)
parent->satellites.push_back(this);
eclipticPos=Vec3d(0.,0.,0.); eclipticPos=Vec3d(0.,0.,0.);
rotLocalToParent = Mat4d::identity(); rotLocalToParent = Mat4d::identity();
StelApp::getInstance().getTextureManager().setDefaultParams(); StelApp::getInstance().getTextureManager().setDefaultParams();
StelApp::getInstance().getTextureManager().setWrapMode(GL_REPEAT); StelApp::getInstance().getTextureManager().setWrapMode(GL_REPEAT);
texMap = StelApp::getInstance().getTextureManager().createTexture(te xMapName); 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
skipping to change at line 111 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)
{
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 Navigator* nav = core->getNavigation(); const StelNavigator* nav = core->getNavigator();
QString str; QString str;
QTextStream oss(&str); QTextStream oss(&str);
if (flags&Name) if (flags&Name)
{ {
oss << "<h2>" << q_(englishName); // UI translation can dif fer from sky translation oss << "<h2>" << q_(englishName); // UI translation can dif fer from sky translation
oss.setRealNumberNotation(QTextStream::FixedNotation); oss.setRealNumberNotation(QTextStream::FixedNotation);
oss.setRealNumberPrecision(1); oss.setRealNumberPrecision(1);
if (sphereScale != 1.f) if (sphereScale != 1.f)
oss << QString::fromUtf8(" (\xC3\x97") << sphereScal e << ")"; oss << QString::fromUtf8(" (\xC3\x97") << sphereScal e << ")";
oss << "</h2>"; oss << "</h2>";
} }
if (flags&Magnitude) if (flags&Magnitude)
oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(nav), 0, 'f', 2) << "<br>"; oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(nav), 0, 'f', 2) << "<br>";
if (flags&AbsoluteMagnitude) if (flags&AbsoluteMagnitude)
oss << q_("Absolute Magnitude: %1").arg(getVMagnitude(nav)-5 .*(std::log10(getObsJ2000Pos(nav).length()*AU/(SPEED_OF_LIGHT*86400*365.25) )-1.), 0, 'f', 2) << "<br>"; oss << q_("Absolute Magnitude: %1").arg(getVMagnitude(nav)-5 .*(std::log10(getJ2000EquatorialPos(nav).length()*AU/PARSEC)-1.), 0, 'f', 2 ) << "<br>";
oss << getPositionInfoString(core, flags); oss << getPositionInfoString(core, flags);
if (flags&Distance) if (flags&Distance)
{ {
// xgettext:no-c-format // xgettext:no-c-format
oss << q_("Distance: %1AU").arg(getObsJ2000Pos(nav).length() , 0, 'f', 8) << "<br>"; oss << q_("Distance: %1AU").arg(getJ2000EquatorialPos(nav).l ength(), 0, 'f', 8) << "<br>";
} }
if (flags&Size) if (flags&Size)
oss << q_("Apparent diameter: %1").arg(StelUtils::radToDmsSt r(2.*getAngularSize(core)*M_PI/180., true)); oss << q_("Apparent diameter: %1").arg(StelUtils::radToDmsSt r(2.*getAngularSize(core)*M_PI/180., true));
postProcessInfoString(str, flags); postProcessInfoString(str, flags);
return str; return str;
} }
//! Get sky label (sky translation) //! Get sky label (sky translation)
QString Planet::getSkyLabel(const Navigator * nav) const QString Planet::getSkyLabel(const StelNavigator * nav) const
{ {
QString str; QString str;
QTextStream oss(&str); QTextStream oss(&str);
oss.setRealNumberPrecision(2); oss.setRealNumberPrecision(2);
oss << nameI18; oss << nameI18;
if (sphereScale != 1.f) if (sphereScale != 1.f)
{ {
oss << QString::fromUtf8(" (\xC3\x97") << sphereScale << ")" ; oss << QString::fromUtf8(" (\xC3\x97") << sphereScale << ")" ;
} }
return str; return str;
} }
float Planet::getSelectPriority(const Navigator *nav) const float Planet::getSelectPriority(const StelNavigator *nav) const
{ {
if( ((SolarSystem*)StelApp::getInstance().getModuleMgr().getModule(" SolarSystem"))->getFlagHints() ) if( ((SolarSystem*)StelApp::getInstance().getModuleMgr().getModule(" SolarSystem"))->getFlagHints() )
{ {
// easy to select, especially pluto // easy to select, especially pluto
return getVMagnitude(nav)-15.f; return getVMagnitude(nav)-15.f;
} }
else else
{ {
return getVMagnitude(nav) - 8.f; return getVMagnitude(nav) - 8.f;
} }
} }
Vec3f Planet::getInfoColor(void) const Vec3f Planet::getInfoColor(void) const
{ {
return StelApp::getInstance().getVisionModeNight() ? Vec3f(0.8, 0.2, 0.4) : ((SolarSystem*)StelApp::getInstance().getModuleMgr().getModule("Sol arSystem"))->getLabelsColor(); return StelApp::getInstance().getVisionModeNight() ? Vec3f(0.8, 0.2, 0.4) : ((SolarSystem*)StelApp::getInstance().getModuleMgr().getModule("Sol arSystem"))->getLabelsColor();
} }
double Planet::getCloseViewFov(const Navigator* nav) const double Planet::getCloseViewFov(const StelNavigator* nav) const
{ {
return std::atan(radius*sphereScale*2.f/getObsEquatorialPos(nav).len gth())*180./M_PI * 4; return std::atan(radius*sphereScale*2.f/getEquinoxEquatorialPos(nav) .length())*180./M_PI * 4;
} }
double Planet::getSatellitesFov(const Navigator * nav) const double Planet::getSatellitesFov(const StelNavigator * nav) const
{ {
// TODO: calculate from satellite orbits rather than hard code // TODO: calculate from satellite orbits rather than hard code
if (englishName=="Jupiter") return std::atan(0.005f/getObsEquatorial if (englishName=="Jupiter") return std::atan(0.005f/getEquinoxEquato
Pos(nav).length())*180./M_PI * 4; rialPos(nav).length())*180./M_PI * 4;
if (englishName=="Saturn") return std::atan(0.005f/getObsEquatorialP if (englishName=="Saturn") return std::atan(0.005f/getEquinoxEquator
os(nav).length())*180./M_PI * 4; ialPos(nav).length())*180./M_PI * 4;
if (englishName=="Mars") return std::atan(0.0001f/getObsEquatorialPo if (englishName=="Mars") return std::atan(0.0001f/getEquinoxEquatori
s(nav).length())*180./M_PI * 4; alPos(nav).length())*180./M_PI * 4;
if (englishName=="Uranus") return std::atan(0.002f/getObsEquatorialP if (englishName=="Uranus") return std::atan(0.002f/getEquinoxEquator
os(nav).length())*180./M_PI * 4; ialPos(nav).length())*180./M_PI * 4;
return -1.; return -1.;
} }
double Planet::getParentSatellitesFov(const Navigator *nav) const double Planet::getParentSatellitesFov(const StelNavigator *nav) const
{ {
if (parent && parent->parent) return parent->getSatellitesFov(nav); if (parent && parent->parent) return parent->getSatellitesFov(nav);
return -1.0; return -1.0;
} }
// Set the orbital elements // Set the orbital elements
void Planet::setRotationElements(float _period, float _offset, double _epoc h, float _obliquity, float _ascendingNode, float _precessionRate, double _s iderealPeriod ) void Planet::setRotationElements(float _period, float _offset, double _epoc h, float _obliquity, float _ascendingNode, float _precessionRate, double _s iderealPeriod )
{ {
re.period = _period; re.period = _period;
re.offset = _offset; re.offset = _offset;
re.epoch = _epoch; re.epoch = _epoch;
re.obliquity = _obliquity; re.obliquity = _obliquity;
re.ascendingNode = _ascendingNode; re.ascendingNode = _ascendingNode;
re.precessionRate = _precessionRate; re.precessionRate = _precessionRate;
re.siderealPeriod = _siderealPeriod; // used for drawing orbit line s re.siderealPeriod = _siderealPeriod; // used for drawing orbit line s
deltaOrbitJD = re.siderealPeriod/ORBIT_SEGMENTS; deltaOrbitJD = re.siderealPeriod/ORBIT_SEGMENTS;
} }
Vec3d Planet::getObsJ2000Pos(const Navigator *nav) const Vec3d Planet::getJ2000EquatorialPos(const StelNavigator *nav) const
{ {
return matVsop87ToJ2000.multiplyWithoutTranslation(getHeliocentricEc lipticPos() - nav->getObserverHelioPos()); 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);
lastJD = date; lastJD = date;
skipping to change at line 365 skipping to change at line 370
// 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);
// Special case - heliocentric coordinates are on ecliptic, // Special case - heliocentric coordinates are on ecliptic,
// not solar equator... // not solar equator...
if (parent) if (parent)
{ {
rotLocalToParent = Mat4d::zrotation(re.ascendingNode rotLocalToParent = Mat4d::zrotation(re.ascendingNode - re.pr
- re.precessionRate*(jd-re.epoch)) ecessionRate*(jd-re.epoch)) * Mat4d::xrotation(re.obliquity);
* 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 (const Planet *p=parent;p->parent;p=p->parent)
rval = p->rotLocalToParent * rval; rval = p->rotLocalToParent * rval;
skipping to change at line 409 skipping to change at line 412
} }
double t = jd - re.epoch; double t = jd - re.epoch;
double rotations = t / (double) re.period; double rotations = t / (double) re.period;
double wholeRotations = floor(rotations); double wholeRotations = floor(rotations);
double remainder = rotations - wholeRotations; double remainder = rotations - wholeRotations;
return remainder * 360. + re.offset; return remainder * 360. + re.offset;
} }
// Get the Planet position in the parent Planet ecliptic coordinate // 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 // Return the heliocentric ecliptical position (Vsop87)
// used only for earth shadow, lunar eclipse
Vec3d Planet::getHeliocentricEclipticPos() const Vec3d Planet::getHeliocentricEclipticPos() const
{ {
Vec3d pos = eclipticPos; Vec3d pos = eclipticPos;
const Planet *pp = parent; const Planet *pp = parent;
if (pp) if (pp)
{ {
while (pp->parent) while (pp->parent)
{ {
pos += pp->eclipticPos; pos += pp->eclipticPos;
pp = pp->parent; pp = pp->parent;
skipping to change at line 461 skipping to change at line 463
double Planet::getPhase(Vec3d obsPos) const double Planet::getPhase(Vec3d obsPos) const
{ {
const double sq = obsPos.lengthSquared(); const double sq = obsPos.lengthSquared();
const Vec3d heliopos = getHeliocentricEclipticPos(); const Vec3d heliopos = getHeliocentricEclipticPos();
const double Rq = heliopos.lengthSquared(); const double Rq = heliopos.lengthSquared();
const double pq = (obsPos - heliopos).lengthSquared(); const double pq = (obsPos - heliopos).lengthSquared();
const double cos_chi = (pq + Rq - sq)/(2.0*sqrt(pq*Rq)); const double cos_chi = (pq + Rq - sq)/(2.0*sqrt(pq*Rq));
return (1.0 - acos(cos_chi)/M_PI) * cos_chi + sqrt(1.0 - cos_chi*cos _chi) / M_PI; return (1.0 - acos(cos_chi)/M_PI) * cos_chi + sqrt(1.0 - cos_chi*cos _chi) / M_PI;
} }
float Planet::getVMagnitude(const Navigator * nav) const float Planet::getVMagnitude(const StelNavigator * nav) const
{ {
Vec3d obsPos = nav->getObserverHelioPos(); Vec3d obsPos = nav->getObserverHeliocentricEclipticPos();
const double sq = obsPos.lengthSquared(); const double sq = obsPos.lengthSquared();
if (parent == 0) { if (parent == 0)
// sun {
return -26.73f + 2.5f*std::log10(sq); // sun, compute the apparent magnitude for the absolute mag
(4.83) and observer's distance
double distParsec = std::sqrt(sq)*AU/PARSEC;
return 4.83 + 5.*(std::log10(distParsec)-1.);
} }
const Vec3d heliopos = getHeliocentricEclipticPos(); const Vec3d heliopos = getHeliocentricEclipticPos();
const double Rq = heliopos.lengthSquared(); const double Rq = heliopos.lengthSquared();
const double pq = (obsPos - heliopos).lengthSquared(); const double pq = (obsPos - heliopos).lengthSquared();
const double cos_chi = (pq + Rq - sq)/(2.0*sqrt(pq*Rq)); 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; 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); double F = 2.0 * albedo * radius * radius * phase / (3.0*pq*Rq);
// 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) {
skipping to change at line 520 skipping to change at line 524
// << ",F: " << F // << ",F: " << F
// << ",rval: " << rval; // << ",rval: " << rval;
return rval; return rval;
} }
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,getObsJ2000Pos(core->getNavigation ()).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,getObsJ2000Pos(core->getNavigat ion()).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)
{ {
if (hidden) if (hidden)
return; return;
Navigator* nav = core->getNavigation(); StelNavigator* nav = core->getNavigator();
Projector* prj = core->getProjection();
Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
const Planet *p = parent; const Planet *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->getHelioToEyeMat() * mat; mat = nav->getHeliocentricEclipticModelViewMat() * mat;
const Vec3d sunPos = nav->getHelioToEyeMat()*Vec3d(0,0,0);
glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(sunPos[0],sunPos[1],sunPos[2],
1.f));
if (this == nav->getHomePlanet()) if (this == nav->getHomePlanet())
{ {
if (rings) if (rings)
rings->draw(prj,mat,1000.0); {
StelPainter sPainter(core->getProjection(mat));
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
float screenSz = getOnScreenSize(core); const StelProjectorP prj = core->getProjection(mat);
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();
prj->setCustomFrame(mat);
if (prj->project(Vec3f(0,0,0), screenPos) && if (prj->project(Vec3f(0,0,0), screenPos) &&
screenPos[1]>viewport_bottom - screenSz && screenPos[1]<view port_bottom + prj->getViewportHeight()+screenSz && screenPos[1]>viewport_bottom - screenSz && screenPos[1]<view port_bottom + prj->getViewportHeight()+screenSz &&
screenPos[0]>viewport_left - screenSz && screenPos[0]<viewpo rt_left + prj->getViewportWidth() + screenSz) screenPos[0]>viewport_left - screenSz && screenPos[0]<viewpo rt_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()/getObs EquatorialPos(nav).length())/prj->getFov(); 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(nav, prj); // TODO - fade in here also... drawOrbit(core); // TODO - fade in here also...
drawTrail(nav, prj); 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);
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)
{ {
Navigator* nav = core->getNavigation(); // This is the main method drawing a planet 3d model
Projector* prj = core->getProjection(); // Some work has to be done on this method to make the rendering nic
er
// Prepare openGL lighting parameters according to luminance StelNavigator* nav = core->getNavigator();
float surfArcMin2 = getSpheroidAngularSize(core)*60;
surfArcMin2 = surfArcMin2*surfArcMin2*M_PI;
core->getSkyDrawer()->preDrawSky3dModel(surfArcMin2, getVMagnitude(c
ore->getNavigation()), flagLighting);
if (screenSz>1.) if (screenSz>1.)
{ {
StelPainter* sPainter = new StelPainter(core->getProjection(
mat * Mat4d::zrotation(M_PI/180*(axisRotation + 90.))));
if (flagLighting)
{
glEnable(GL_LIGHTING);
// Set the main source of light to be the sun
const Vec3d sunPos = core->getNavigator()->getHelioc
entricEclipticModelViewMat()*Vec3d(0,0,0);
glLightfv(GL_LIGHT0,GL_POSITION,Vec4f(sunPos[0],sunP
os[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
const float zero[4] = {0,0,0,0};
const float ambient[4] = {0.02,0.02,0.02,0.02};
glLightfv(GL_LIGHT0,GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,zero);
glMaterialfv(GL_FRONT,GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT,GL_EMISSION, zero);
glMaterialfv(GL_FRONT,GL_SHININESS,zero);
glMaterialfv(GL_FRONT,GL_SPECULAR, zero);
}
else
{
glDisable(GL_LIGHTING);
glColor3fv(Vec3f(1.f,1.f,1.f));
}
if (rings) if (rings)
{ {
const double dist = getObsEquatorialPos(nav).length( ); 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;
prj->getClippingPlanes(&n,&f); // Save clipping plan core->getClippingPlanes(&n,&f); // Save clipping pla
es nes
prj->setClippingPlanes(z_near,z_far); core->setClippingPlanes(z_near,z_far);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
drawSphere(core,mat,screenSz); drawSphere(sPainter, screenSz);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
rings->draw(prj,mat,screenSz); rings->draw(sPainter,mat,screenSz);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
prj->setClippingPlanes(n,f); // Restore old clippin g planes core->setClippingPlanes(n,f); // Restore old clippi ng planes
} }
else else
{ {
SolarSystem* ssm = (SolarSystem*)GETSTELMODULE("Sola rSystem"); SolarSystem* ssm = (SolarSystem*)GETSTELMODULE("Sola rSystem");
if (this==ssm->getMoon() && ssm->nearLunarEclipse()) if (this==ssm->getMoon() && nav->getHomePlanet()==ss m->getEarth() && ssm->nearLunarEclipse())
{ {
// Draw earth shadow over moon using stencil
buffer if appropriate
// 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...
// special case to update stencil buffer for
drawing lunar eclipses
glClear(GL_STENCIL_BUFFER_BIT);
glClearStencil(0x0); glClearStencil(0x0);
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(core, mat, screenSz); drawSphere(sPainter, screenSz);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);
delete sPainter;
sPainter=NULL;
drawEarthShadow(core);
} }
else else
{ {
drawSphere(core, mat, screenSz); // Normal planet
drawSphere(sPainter, screenSz);
} }
} }
if (sPainter)
delete sPainter;
sPainter=NULL;
} }
//qDebug() << nameI18; // Draw the halo
core->getSkyDrawer()->postDrawSky3dModel(screenPos[0],screenPos[1],
surfArcMin2, getVMagnitude(core->getNavigation()), color); // Prepare openGL lighting parameters according to luminance
float surfArcMin2 = getSpheroidAngularSize(core)*60;
surfArcMin2 = surfArcMin2*surfArcMin2*M_PI; // the total illuminated
area in arcmin^2
StelPainter sPainter(core->getProjection(StelCore::FrameJ2000));
core->getSkyDrawer()->postDrawSky3dModel(screenPos[0],screenPos[1],
surfArcMin2, getVMagnitude(core->getNavigator()), &sPainter, color);
}
void Planet::drawSphere(const StelPainter* painter, float screenSz)
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
if (texMap)
texMap->bind();
// Draw the spheroid itself
// 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
if (nb_facet<10) nb_facet = 10;
if (nb_facet>40) nb_facet = 40;
glShadeModel(GL_SMOOTH);
// 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,
// perhaps some openGl strangeness, or confusing sin/cos.
painter->sSphere(radius*sphereScale, oneMinusOblateness, nb_facet, n
b_facet);
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
}
// draws earth shadow overlapping the moon using stencil buffer
// umbra and penumbra are sized separately for accuracy
void Planet::drawEarthShadow(StelCore* core)
{
SolarSystem* ssm = (SolarSystem*)GETSTELMODULE("SolarSystem");
Vec3d e = ssm->getEarth()->getEclipticPos();
Vec3d m = ssm->getMoon()->getEclipticPos(); // relative to earth
Vec3d mh = ssm->getMoon()->getHeliocentricEclipticPos(); // relativ
e to sun
float mscale = ssm->getMoon()->getSphereScale();
// shadow location at earth + moon distance along earth vector from
sun
Vec3d en = e;
en.normalize();
Vec3d shadow = en * (e.length() + m.length());
// find shadow radii in AU
double r_penumbra = shadow.length()*702378.1/AU/e.length() - 696000.
/AU;
double r_umbra = 6378.1/AU - m.length()*(689621.9/AU/e.length());
// find vector orthogonal to sun-earth vector using cross product wi
th
// a non-parallel vector
Vec3d rpt = shadow^Vec3d(0,0,1);
rpt.normalize();
Vec3d upt = rpt*r_umbra*mscale*1.02; // point on umbra edge
rpt *= r_penumbra*mscale; // point on penumbra edge
// modify shadow location for scaled moon
Vec3d mdist = shadow - mh;
if(mdist.length() > r_penumbra + 2000./AU)
return; // not visible so don't bother drawing
shadow = mh + mdist*mscale;
r_penumbra *= mscale;
const StelProjectorP prj = core->getProjection(StelCore::FrameHelioc
entricEcliptic);
StelPainter sPainter(prj);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor3f(1,1,1);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// shadow radial texture
texEarthShadow->bind();
Vec3d r, s;
// 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++)
{
r = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * upt;
s = shadow + r;
glTexCoord2f(0.6f,0.5f); // position in texture of umbra ed
ge
sPainter.drawVertex3v(s);
}
glEnd();
// now penumbra
Vec3d u, sp;
glBegin(GL_TRIANGLE_STRIP);
for (int i=0; i<=100; i++)
{
r = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * rpt;
u = Mat4d::rotation(shadow, 2.*M_PI*i/100.) * upt;
s = shadow + r;
sp = shadow + u;
glTexCoord2f(0.6f,0.5f);
sPainter.drawVertex3v(sp);
glTexCoord2f(1.f,0.5f); // position in texture of umbra edg
e
sPainter.drawVertex3v(s);
}
glEnd();
glDisable(GL_STENCIL_TEST);
glClearStencil(0x0);
glClear(GL_STENCIL_BUFFER_BIT); // Clean again to let a clean buffer
for later Qt display
} }
void Planet::drawHints(const StelCore* core) void Planet::drawHints(const StelCore* core)
{ {
if (labelsFader.getInterstate()<=0.f) if (labelsFader.getInterstate()<=0.f)
return; return;
const Navigator* nav = core->getNavigation(); const StelNavigator* nav = core->getNavigator();
const Projector* prj = core->getProjection(); const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000)
;
StelPainter sPainter(prj);
// Draw nameI18 + scaling if it's not == 1. // Draw nameI18 + scaling if it's not == 1.
float tmp = 10.f + getOnScreenSize(core)/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 tInterstate()); glColor4f(labelColor[0], labelColor[1], labelColor[2],labelsFader.ge tInterstate());
prj->drawText(planetNameFont,screenPos[0],screenPos[1], getSkyLabel( nav), 0, tmp, tmp, false); sPainter.drawText(planetNameFont,screenPos[0],screenPos[1], getSkyLa bel(nav), 0, tmp, 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); glColor4f(labelColor[0], labelColor[1], labelColor[2],labelsFader.ge tInterstate()*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);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Planet::hintCircleTex->bind(); Planet::hintCircleTex->bind();
prj->drawSprite2dMode(screenPos[0], screenPos[1], 22); sPainter.drawSprite2dMode(screenPos[0], screenPos[1], 22);
}
void Planet::drawSphere(StelCore* core, const Mat4d& mat, float screenSz)
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
if (texMap)
texMap->bind();
// 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,
// perhaps some openGl strangeness, or confusing sin/cos.
core->getProjection()->setCustomFrame(mat * Mat4d::zrotation(M_PI/18
0*(axisRotation + 90.)));
// Draw the spheroid itself
// 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
if (nb_facet<10) nb_facet = 10;
if (nb_facet>40) nb_facet = 40;
glShadeModel(GL_SMOOTH);
core->getProjection()->sSphere(radius*sphereScale, oneMinusOblatenes
s, nb_facet, nb_facet);
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
} }
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 Projector* prj,const Mat4d& mat,double screenSz) void Ring::draw(const StelPainter* painter,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.0f, 0.88f, 0.82f); // For saturn only..
glColor3f(1.f, 1.f, 1.f); glColor3f(1.f, 1.f, 1.f);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
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];
prj->setCustomFrame(mat); painter->sRing(radiusMin,radiusMax,(h<0.0)?slices:-slices,stacks, 0)
prj->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 Navigator * nav, const Projector* prj) void Planet::drawOrbit(const StelCore* core)
{ {
if(!orbitFader.getInterstate()) return; if (!orbitFader.getInterstate())
if(!re.siderealPeriod) return; return;
if (!re.siderealPeriod)
return;
const StelProjectorP prj = core->getProjection(StelCore::FrameHelioc
entricEcliptic);
prj->setCurrentFrame(Projector::FrameHelio); // 2D coordinate 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);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor4f(orbitColor[0], orbitColor[1], orbitColor[2], orbitFader.ge tInterstate()); glColor4f(orbitColor[0], orbitColor[1], orbitColor[2], orbitFader.ge tInterstate());
int on=0; int on=0;
int d; int d;
Vec3d onscreen; Vec3d onscreen;
for( int n=0; n<=ORBIT_SEGMENTS; n++) for( int n=0; n<=ORBIT_SEGMENTS; n++)
{ {
if( n==ORBIT_SEGMENTS ) if( n==ORBIT_SEGMENTS )
{ {
skipping to change at line 805 skipping to change at line 939
on=1; on=1;
} }
else if( on ) else if( on )
{ {
glEnd(); glEnd();
on=0; on=0;
} }
} }
} }
if(on) glEnd(); if (on)
glEnd();
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
} }
// draw trail of Planet as seen from earth // draw trail of Planet as seen from earth
void Planet::drawTrail(const Navigator * nav, const Projector* prj) void Planet::drawTrail(const StelCore* core)
{ {
if(!trailFader.getInterstate()) return; if (!trailFader.getInterstate())
return;
const StelNavigator* nav = core->getNavigator();
const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000)
;
Vec3d onscreen1; Vec3d onscreen1;
Vec3d onscreen2; Vec3d onscreen2;
prj->setCurrentFrame(Projector::FrameJ2000); StelPainter sPainter(prj);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor3fv(trailColor*trailFader.getInterstate()); glColor3fv(trailColor*trailFader.getInterstate());
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())
{ {
skipping to change at line 853 skipping to change at line 984
{ {
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
glVertex2d(onscreen1[0], onscreen1[1]); glVertex2d(onscreen1[0], onscreen1[1]);
glVertex2d(onscreen2[0], onscreen2[1]); glVertex2d(onscreen2[0], onscreen2[1]);
glEnd(); 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 screen1, getObsEquatorialPos(nav), onscreen2) ) if( !firstPoint && prj->projectLineCheck( (*trail.begin()).point, on screen1, getEquinoxEquatorialPos(nav), onscreen2) )
{ {
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
glVertex2d(onscreen1[0], onscreen1[1]); glVertex2d(onscreen1[0], onscreen1[1]);
glVertex2d(onscreen2[0], onscreen2[1]); glVertex2d(onscreen2[0], onscreen2[1]);
glEnd(); glEnd();
} }
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
} }
// update trail points as needed // update trail points as needed
void Planet::updateTrail(const Navigator* nav) void Planet::updateTrail(const StelNavigator* nav)
{ {
if(!trailOn) return; if (!trailOn)
return;
double date = nav->getJDay(); double date = nav->getJDay();
int dt=0; int dt=0;
if(firstPoint || (dt=abs(int((date-lastTrailJD)/DeltaTrail))) > MaxT rail) if(firstPoint || (dt=abs(int((date-lastTrailJD)/DeltaTrail))) > MaxT rail)
{ {
dt=1; dt=1;
// clear old trail // clear old trail
trail.clear(); trail.clear();
firstPoint = 0; firstPoint = 0;
} }
// Note that when jump by a week or day at a time, loose detail on t rails // Note that when jump by a week or day at a time, loose detail on t rails
// particularly for moon (if decide to show moon trail) // particularly for moon (if decide to show moon trail)
// add only one point at a time, using current position only // add only one point at a time, using current position only
if(dt) if(dt)
{ {
lastTrailJD = date; lastTrailJD = date;
TrailPoint tp; TrailPoint tp;
tp.point = getObsJ2000Pos(nav); tp.point = getJ2000EquatorialPos(nav);
tp.date = date; tp.date = date;
trail.push_front( tp ); trail.push_front( tp );
// if( trail.size() > (unsigned int)MaxTrail ) { // if( trail.size() > (unsigned int)MaxTrail ) {
if( trail.size() > (unsigned int)MaxTrail ) if( trail.size() > (unsigned int)MaxTrail )
{ {
trail.pop_back(); trail.pop_back();
} }
} }
 End of changes. 79 change blocks. 
151 lines changed or deleted 298 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/