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 <QVarLengthArray> #include <QVarLengthArray>
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelTexture.hpp" #include "renderer/GenericVertexTypes.hpp"
#include "renderer/StelGeometryBuilder.hpp"
#include "renderer/StelRenderer.hpp"
#include "renderer/StelTextureNew.hpp"
#include "StelSkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "SolarSystem.hpp" #include "SolarSystem.hpp"
#include "Planet.hpp" #include "Planet.hpp"
#include "StelProjector.hpp" #include "StelProjector.hpp"
#include "sideral_time.h" #include "sideral_time.h"
#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 "StelTranslator.hpp" #include "StelTranslator.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
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);
StelTextureSP Planet::hintCircleTex;
StelTextureSP Planet::texEarthShadow; Planet::SharedPlanetGraphics::~SharedPlanetGraphics()
{
if(!initialized){return;}
delete texEarthShadow;
delete texHintCircle;
if(NULL != simplePlanetShader)
delete simplePlanetShader;
if(NULL != shadowPlanetShader)
delete shadowPlanetShader;
initialized = false;
}
void Planet::SharedPlanetGraphics::lazyInit(StelRenderer* renderer)
{
if(initialized){return;}
texHintCircle = renderer->createTexture("textures/planet-indicator.
png");
texEarthShadow = renderer->createTexture("textures/earth-shadow.png"
);
planetShader = simplePlanetShader = shadowPlanetShader = NULL;
if(renderer->isGLSLSupported())
{
if(!loadPlanetShaders(renderer))
{
qWarning() << "Failed to load planet shaders, fallin
g back to CPU implementation";
simplePlanetShader = shadowPlanetShader = NULL;
}
}
initialized = true;
}
bool Planet::SharedPlanetGraphics::loadPlanetShaders(StelRenderer* renderer
)
{
Q_ASSERT_X(renderer->isGLSLSupported(), Q_FUNC_INFO,
"Trying to load planet shaders but GLSL is not supported"
);
simplePlanetShader = renderer->createGLSLShader();
if(!simplePlanetShader->addVertexShader(
"vec4 project(in vec4 v);\n"
"attribute mediump vec4 vertex;\n"
"attribute mediump vec4 unprojectedVertex;\n"
"attribute mediump vec2 texCoord;\n"
"uniform mediump mat4 projectionMatrix;\n"
"uniform highp vec3 lightPos;\n"
"uniform highp float oneMinusOblateness;\n"
"uniform highp float radius;\n"
"uniform mediump vec4 ambientLight;\n"
"uniform mediump vec4 diffuseLight;\n"
"varying mediump vec2 texc;\n"
"varying mediump vec4 litColor;\n"
"void main(void)\n"
"{\n"
" gl_Position = projectionMatrix * project(vertex);\n"
" texc = texCoord;\n"
" // Must be a separate variable due to Intel drivers\n"
" vec4 normal = unprojectedVertex / radius;\n"
" float c = lightPos.x * normal.x * oneMinusOblateness +\n"
" lightPos.y * normal.y * oneMinusOblateness +\n"
" lightPos.z * normal.z / oneMinusOblateness;\n"
" litColor = clamp(c, 0.0, 0.5) * diffuseLight + ambientLight;\
n"
"}\n"))
{
qWarning() << "Error adding simple planet vertex shader: " <
< simplePlanetShader->log();
delete simplePlanetShader;
return false;
}
if(!simplePlanetShader->addFragmentShader(
"varying mediump vec2 texc;\n"
"varying mediump vec4 litColor;\n"
"uniform sampler2D tex;\n"
"uniform mediump vec4 globalColor;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(tex, texc) * litColor;\n"
"}\n"))
{
qWarning() << "Error adding simple planet fragment shader: "
<< simplePlanetShader->log();
delete simplePlanetShader;
return false;
}
if(!simplePlanetShader->build())
{
qWarning() << "Error building shader: " << simplePlanetShade
r->log();
delete simplePlanetShader;
return false;
}
qDebug() << "Simple planet shader build log: " << simplePlanetShader
->log();
shadowPlanetShader = renderer->createGLSLShader();
if(!shadowPlanetShader->addVertexShader(
"vec4 project(in vec4 v);\n"
"attribute mediump vec4 vertex;\n"
"attribute mediump vec4 unprojectedVertex;\n"
"attribute mediump vec2 texCoord;\n"
"uniform mediump mat4 projectionMatrix;\n"
"uniform highp vec3 lightPos;\n"
"uniform highp float oneMinusOblateness;\n"
"uniform highp float radius;\n"
"varying mediump vec2 texc;\n"
"varying mediump float lambert;\n"
"varying highp vec3 P;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = projectionMatrix * project(vertex);\n"
" texc = texCoord;\n"
" // Must be a separate variable due to Intel drivers\n"
" vec4 normal = unprojectedVertex / radius;\n"
" float c = lightPos.x * normal.x * oneMinusOblateness +\n"
" lightPos.y * normal.y * oneMinusOblateness +\n"
" lightPos.z * normal.z / oneMinusOblateness;\n"
" lambert = clamp(c, 0.0, 0.5);\n"
"\n"
" P = vec3(unprojectedVertex);\n"
"}\n"
"\n"))
{
qWarning() << "Error adding shadow planet vertex shader: " <
< shadowPlanetShader->log();
delete shadowPlanetShader;
return false;
}
if(!shadowPlanetShader->addFragmentShader(
"varying mediump vec2 texc;\n"
"varying mediump float lambert;\n"
"uniform sampler2D tex;\n"
"uniform mediump vec4 globalColor;\n"
"uniform mediump vec4 ambientLight;\n"
"uniform mediump vec4 diffuseLight;\n"
"\n"
"varying highp vec3 P;\n"
"\n"
"uniform sampler2D info;\n"
"uniform int current;\n"
"uniform int infoCount;\n"
"uniform float infoSize;\n"
"\n"
"uniform bool ring;\n"
"uniform highp float outerRadius;\n"
"uniform highp float innerRadius;\n"
"uniform sampler2D ringS;\n"
"uniform bool isRing;\n"
"\n"
"uniform bool isMoon;\n"
"uniform sampler2D earthShadow;\n"
"\n"
"bool visible(vec3 normal, vec3 light)\n"
"{\n"
" return (dot(light, normal) > 0.0);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" float final_illumination = 1.0;\n"
" vec4 diffuse = diffuseLight;\n"
" vec4 data = texture2D(info, vec2(0.0, current) / infoSize);\n
"
" float RS = data.w;\n"
" vec3 Lp = data.xyz;\n"
"\n"
" vec3 P3;\n"
"\n"
" if(isRing)\n"
" P3 = P;\n"
" else\n"
" {\n"
" data = texture2D(info, vec2(current, current) / infoSize)
;\n"
" P3 = normalize(P) * data.w;\n"
" }\n"
"\n"
" if((lambert > 0.0) || isRing)\n"
" {\n"
" if(ring && !isRing)\n"
" {\n"
" vec3 ray = normalize(Lp);\n"
" vec3 normal = normalize(vec3(0.0, 0.0, 1.0));\n"
" float u = - dot(P3, normal) / dot(ray, normal);\n"
"\n"
" if(u > 0.0 && u < 1e10)\n"
" {\n"
" float ring_radius = length(P3 + u * ray);\n"
"\n"
" if(ring_radius > innerRadius && ring_radius < out
erRadius)\n"
" {\n"
" ring_radius = (ring_radius - innerRadius) / (
outerRadius - innerRadius);\n"
" data = texture2D(ringS, vec2(ring_radius, 0.5
));\n"
"\n"
" final_illumination = 1.0 - data.w;\n"
" }\n"
" }\n"
" }\n"
"\n"
" for(int i = 1; i < infoCount; i++)\n"
" {\n"
" if(current == i && !isRing)\n"
" continue;\n"
"\n"
" data = texture2D(info, vec2(i, current) / infoSize);\
n"
" vec3 C = data.rgb;\n"
" float radius = data.a;\n"
"\n"
" float L = length(Lp - P3);\n"
" float l = length(C - P3);\n"
"\n"
" float R = RS / L;\n"
" float r = radius / l;\n"
" float d = length( (Lp - P3) / L - (C - P3) / l );\n"
"\n"
" float illumination = 1.0;\n"
"\n"
" // distance too far\n"
" if(d >= R + r)\n"
" {\n"
" illumination = 1.0;\n"
" }\n"
" // umbra\n"
" else if(r >= R + d)\n"
" {\n"
" if(isMoon)\n"
" illumination = d / (r - R) * 0.6;\n"
" else"
" illumination = 0.0;\n"
" }\n"
" // penumbra completely inside\n"
" else if(d + r <= R)\n"
" {\n"
" illumination = 1.0 - r * r / (R * R);\n"
" }\n"
" // penumbra partially inside\n"
" else\n"
" {\n"
" if(isMoon)\n"
" illumination = ((d - abs(R-r)) / (R + r - abs
(R-r))) * 0.4 + 0.6;\n"
" else\n"
" {\n"
" float x = (R * R + d * d - r * r) / (2.0 * d)
;\n"
"\n"
" float alpha = acos(x / R);\n"
" float beta = acos((d - x) / r);\n"
"\n"
" float AR = R * R * (alpha - 0.5 * sin(2.0 * a
lpha));\n"
" float Ar = r * r * (beta - 0.5 * sin(2.0 * be
ta));\n"
" float AS = R * R * 2.0 * asin(1.0);\n"
"\n"
" illumination = 1.0 - (AR + Ar) / AS;\n"
" }\n"
" }\n"
"\n"
" if(illumination < final_illumination)\n"
" final_illumination = illumination;\n"
" }\n"
" }\n"
"\n"
" vec4 litColor = (isRing ? 1.0 : lambert) * final_illumination
* diffuse + ambientLight;\n"
" if(isMoon && final_illumination < 1.0)\n"
" {\n"
" vec4 shadowColor = texture2D(earthShadow, vec2(final_illu
mination, 0.5));\n"
" gl_FragColor = mix(texture2D(tex, texc) * litColor, shado
wColor, shadowColor.a);\n"
" }\n"
" else\n"
" gl_FragColor = texture2D(tex, texc) * litColor;\n"
"}\n"
"\n"))
{
qWarning() << "Error adding shadow planet fragment shader: "
<< shadowPlanetShader->log();
delete shadowPlanetShader;
return false;
}
if(!shadowPlanetShader->build())
{
qWarning() << "Error building shader: " << shadowPlanetShade
r->log();
delete shadowPlanetShader;
return false;
}
qDebug() << "Shadow planet shader build log: " << shadowPlanetShader
->log();
return true;
}
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,
posFuncType coordFunc, posFuncType coordFunc,
void* auserDataPtr, void* auserDataPtr,
OsculatingFunctType *osculatingFunc, OsculatingFunctType *osculatingFunc,
bool acloseOrbit, bool acloseOrbit,
bool hidden, bool hidden,
bool hasAtmosphere) bool hasAtmosphere,
const QString& pType)
: 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.),
texture(NULL),
rings(NULL),
sphereScale(1.f), sphereScale(1.f),
lastJD(J2000), lastJD(J2000),
coordFunc(coordFunc), coordFunc(coordFunc),
userDataPtr(auserDataPtr), userDataPtr(auserDataPtr),
osculatingFunc(osculatingFunc), osculatingFunc(osculatingFunc),
parent(NULL), parent(NULL),
hidden(hidden), hidden(hidden),
atmosphere(hasAtmosphere) atmosphere(hasAtmosphere),
pType(pType),
unlitSphere(NULL),
litSphere(NULL)
{ {
texMapName = atexMapName; texMapName = atexMapName;
lastOrbitJD =0; lastOrbitJD =0;
deltaJD = StelCore::JD_SECOND; deltaJD = StelCore::JD_SECOND;
orbitCached = 0; orbitCached = 0;
orbitVertices = NULL;
closeOrbit = acloseOrbit; closeOrbit = acloseOrbit;
eclipticPos=Vec3d(0.,0.,0.); eclipticPos=Vec3d(0.,0.,0.);
rotLocalToParent = Mat4d::identity(); rotLocalToParent = Mat4d::identity();
texMap = StelApp::getInstance().getTextureManager().createTextureThr ead("textures/"+texMapName, StelTexture::StelTextureParams(true, GL_LINEAR, GL_REPEAT));
nameI18 = englishName; nameI18 = englishName;
if (englishName!="Pluto") if (englishName!="Pluto")
{ {
deltaJD = 0.001*StelCore::JD_SECOND; deltaJD = 0.001*StelCore::JD_SECOND;
} }
flagLabels = true; flagLabels = true;
} }
Planet::~Planet() Planet::~Planet()
{ {
if (rings) if(NULL != rings)
{
delete rings; delete rings;
rings = NULL;
}
if(NULL != orbitVertices)
{
delete orbitVertices;
orbitVertices = NULL;
}
if(NULL != litSphere)
{
Q_ASSERT_X(NULL == unlitSphere, Q_FUNC_INFO,
"Both lit and unlit spheres have been generated")
;
delete litSphere;
litSphere = NULL;
}
if(NULL != unlitSphere)
{
Q_ASSERT_X(NULL == litSphere, Q_FUNC_INFO,
"Both lit and unlit spheres have been generated")
;
delete unlitSphere;
unlitSphere = NULL;
}
if(NULL != texture)
{
delete texture;
texture = NULL;
}
} }
void Planet::translateName(StelTranslator& trans) void Planet::translateName(StelTranslator& trans)
{ {
nameI18 = trans.qtranslate(englishName); nameI18 = trans.qtranslate(englishName);
} }
// 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
{ {
skipping to change at line 118 skipping to change at line 435
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&Extra1)
{
if (pType.length()>0)
oss << q_("Type: <b>%1</b>").arg(q_(pType)) << "<br
/>";
}
if (flags&Magnitude) if (flags&Magnitude)
{ {
if (core->getSkyDrawer()->getFlagHasAtmosphere()) if (core->getSkyDrawer()->getFlagHasAtmosphere())
oss << q_("Magnitude: <b>%1</b> (extincted to: <b>%2</b> )").arg(QString::number(getVMagnitude(core, false), 'f', 2), oss << q_("Magnitude: <b>%1</b> (extincted to: <b>%2</b> )").arg(QString::number(getVMagnitude(core, false), 'f', 2),
QString::number(getVMagnitude(core, true), 'f', 2)) << "<br>"; QString::number(getVMagnitude(core, true), 'f', 2)) << "<br>";
else else
oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(core , false), 0, 'f', 2) << "<br>"; oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(core , false), 0, 'f', 2) << "<br>";
} }
if (flags&AbsoluteMagnitude) if (flags&AbsoluteMagnitude)
oss << q_("Absolute Magnitude: %1").arg(getVMagnitude(core, false)-5.*(std::log10(getJ2000EquatorialPos(core).length()*AU/PARSEC)-1.), 0, 'f', 2) << "<br>"; oss << q_("Absolute Magnitude: %1").arg(getVMagnitude(core, false)-5.*(std::log10(getJ2000EquatorialPos(core).length()*AU/PARSEC)-1.), 0, 'f', 2) << "<br>";
skipping to change at line 140 skipping to change at line 463
if ((flags&Extra1) && (core->getCurrentLocation().planetName=="Earth ")) if ((flags&Extra1) && (core->getCurrentLocation().planetName=="Earth "))
{ {
//static SolarSystem *ssystem=GETSTELMODULE(SolarSystem); //static SolarSystem *ssystem=GETSTELMODULE(SolarSystem);
//double ecl= -(ssystem->getEarth()->getRotObliquity()); // BUG DETECTED! Earth's obliquity is apparently reported constant. //double ecl= -(ssystem->getEarth()->getRotObliquity()); // BUG DETECTED! Earth's obliquity is apparently reported constant.
double ra_equ, dec_equ, lambda, beta; double ra_equ, dec_equ, lambda, beta;
double ecl= get_mean_ecliptical_obliquity(core->getJDay()) * M_PI/180.0; double ecl= get_mean_ecliptical_obliquity(core->getJDay()) * M_PI/180.0;
StelUtils::rectToSphe(&ra_equ,&dec_equ,getEquinoxEquatorialP os(core)); StelUtils::rectToSphe(&ra_equ,&dec_equ,getEquinoxEquatorialP os(core));
StelUtils::ctRadec2Ecl(ra_equ, dec_equ, ecl, &lambda, &beta) ; StelUtils::ctRadec2Ecl(ra_equ, dec_equ, ecl, &lambda, &beta) ;
if (lambda<0) lambda+=2.0*M_PI; if (lambda<0) lambda+=2.0*M_PI;
oss << q_("Ecliptic Geocentric (of date): %1/%2").arg(StelUt oss << q_("Ecliptic Topocentric (of date): %1/%2").arg(StelU
ils::radToDmsStr(lambda, true), StelUtils::radToDmsStr(beta, true)) << "<br tils::radToDmsStr(lambda, true), StelUtils::radToDmsStr(beta, true)) << "<b
>"; r>";
oss << q_("Obliquity (of date): %1").arg(StelUtils::radToDms oss << q_("Obliquity (of date, for Earth): %1").arg(StelUtil
Str(ecl, true)) << "<br>"; s::radToDmsStr(ecl, true)) << "<br>";
} }
if (flags&Distance) if (flags&Distance)
{ {
double distanceAu = getJ2000EquatorialPos(core).length(); double distanceAu = getJ2000EquatorialPos(core).length();
if (distanceAu < 0.1) if (distanceAu < 0.1)
{ {
double distanceKm = AU * distanceAu; double distanceKm = AU * distanceAu;
// xgettext:no-c-format // xgettext:no-c-format
oss << QString(q_("Distance: %1AU (%2 km)")) oss << QString(q_("Distance: %1AU (%2 km)"))
skipping to change at line 180 skipping to change at line 503
.arg(StelUtils::radToDmsStr(withoutRings, tru e), .arg(StelUtils::radToDmsStr(withoutRings, tru e),
StelUtils::radToDmsStr(angularSize, true )); StelUtils::radToDmsStr(angularSize, true ));
} }
else else
{ {
oss << q_("Apparent diameter: %1").arg(StelUtils::ra dToDmsStr(angularSize, true)); oss << q_("Apparent diameter: %1").arg(StelUtils::ra dToDmsStr(angularSize, true));
} }
oss << "<br>"; oss << "<br>";
} }
double siderealPeriod = getSiderealPeriod();
if ((flags&Extra1) && (siderealPeriod>0))
{
// TRANSLATORS: Sidereal (orbital) period for solar system b
odies in days and in Julian years (symbol: a)
oss << q_("Sidereal period: %1 days (%2 a)").arg(QString::nu
mber(siderealPeriod, 'f', 2)).arg(QString::number(siderealPeriod/365.25, 'f
', 3)) << "<br>";
if (std::abs(getSiderealDay())>0)
{
oss << q_("Sidereal day: %1").arg(StelUtils::hoursTo
HmsStr(std::abs(getSiderealDay()*24))) << "<br>";
bool fwddir = true;
if (englishName.compare("Venus") || englishName.comp
are("Uranus"))
fwddir = false;
oss << q_("Mean solar day: %1").arg(StelUtils::hours
ToHmsStr(std::abs(StelUtils::calculateSolarDay(siderealPeriod, getSiderealD
ay(), fwddir)*24))) << "<br>";
}
}
if ((flags&Extra2) && (englishName.compare("Sun")!=0)) if ((flags&Extra2) && (englishName.compare("Sun")!=0))
{ {
const Vec3d& observerHelioPos = core->getObserverHeliocentri cEclipticPos(); const Vec3d& observerHelioPos = core->getObserverHeliocentri cEclipticPos();
const double observerRq = observerHelioPos.lengthSquared(); oss << QString(q_("Phase Angle: %1")).arg(StelUtils::radToDm
const Vec3d& planetHelioPos = getHeliocentricEclipticPos(); sStr(getPhaseAngle(observerHelioPos))) << "<br>";
const double planetRq = planetHelioPos.lengthSquared(); oss << QString(q_("Elongation: %1")).arg(StelUtils::radToDms
const double observerPlanetRq = (observerHelioPos - planetHe Str(getElongation(observerHelioPos))) << "<br>";
lioPos).lengthSquared(); oss << QString(q_("Phase: %1")).arg(getPhase(observerHelioPo
const double cos_chi = (observerPlanetRq + planetRq - observ s), 0, 'f', 2) << "<br>";
erRq)/(2.0*sqrt(observerPlanetRq*planetRq)); oss << QString(q_("Illuminated: %1%")).arg(getPhase(observer
float planetPhase = 0.5f * std::abs(1.f + cos_chi); HelioPos) * 100, 0, 'f', 1) << "<br>";
oss << QString(q_("Phase Angle: %1")).arg(StelUtils::radToDm
sStr(getPhase(core->getObserverHeliocentricEclipticPos()))) << "<br>";
oss << QString(q_("Elongation: %1")).arg(StelUtils::radToDms
Str(getElongation(core->getObserverHeliocentricEclipticPos()))) << "<br>";
oss << QString(q_("Phase: %1")).arg(planetPhase, 0, 'f', 2)
<< "<br>";
oss << QString(q_("Illuminated: %1%")).arg(planetPhase * 100
, 0, 'f', 1) << "<br>";
} }
postProcessInfoString(str, flags); postProcessInfoString(str, flags);
return str; return str;
} }
//! Get sky label (sky translation) //! Get sky label (sky translation)
QString Planet::getSkyLabel(const StelCore*) const QString Planet::getSkyLabel(const StelCore*) const
{ {
skipping to change at line 428 skipping to change at line 760
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 - 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);
} }
} }
void Planet::computeModelMatrix(Mat4d &result) const
{
result = Mat4d::translation(eclipticPos) * rotLocalToParent * Mat4d:
:zrotation(M_PI/180*(axisRotation + 90.));
PlanetP p = parent;
while (p && p->parent)
{
result = Mat4d::translation(p->eclipticPos) * result * p->ro
tLocalToParent;
p = p->parent;
}
}
Mat4d Planet::getRotEquatorialToVsop87(void) const Mat4d Planet::getRotEquatorialToVsop87(void) const
{ {
Mat4d rval = rotLocalToParent; Mat4d rval = rotLocalToParent;
if (parent) if (parent)
{ {
for (PlanetP 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;
} }
skipping to change at line 463 skipping to change at line 806
if (englishName=="Earth") if (englishName=="Earth")
{ {
return get_apparent_sidereal_time(jd); return get_apparent_sidereal_time(jd);
} }
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; if (englishName=="Jupiter")
{
// use semi-empirical coefficient for GRS drift
// TODO: need improved
return remainder * 360. + re.offset - 0.2483 * std::abs(Stel
App::getInstance().getCore()->getJDay() - 2456172);
}
else
return remainder * 360. + re.offset;
} }
// 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
skipping to change at line 491 skipping to change at line 841
pos += pp->eclipticPos; pos += pp->eclipticPos;
pp = pp->parent; pp = pp->parent;
} }
} }
return pos; return pos;
} }
// Return heliocentric coordinate of p // Return heliocentric coordinate of p
Vec3d Planet::getHeliocentricPos(Vec3d p) const Vec3d Planet::getHeliocentricPos(Vec3d p) const
{ {
// Optimization:
//
// This code used about 8% of runtime before,
// this is an optimized version - avoiding smart pointer checks
// (this function doesn't own any of the parents - planets
// and solar system do, so we're OK)
//
// This is the equivalent (previous) unoptimized code:
// (update this if you make any functionality changes)
// PlanetP pp = parent;
// if (pp)
// {
// while (pp->parent)
// {
// pos += pp->eclipticPos;
// pp = pp->parent;
// }
// }
Vec3d pos = p; Vec3d pos = p;
PlanetP pp = parent; const Planet* ourParent = &(*parent);
if (pp) const Planet* parentsParent;
// int i = 0;
if (NULL != ourParent)
{ {
while (pp->parent) // const Planet* const parentsParent = &(*(ourParent->parent
));
while (NULL != (parentsParent = &(*(ourParent->parent))))
{ {
pos += pp->eclipticPos; pos += ourParent->eclipticPos;
pp = pp->parent; ourParent = parentsParent;
} }
} }
return pos; return pos;
} }
void Planet::setHeliocentricEclipticPos(const Vec3d &pos) void Planet::setHeliocentricEclipticPos(const Vec3d &pos)
{ {
eclipticPos = pos; eclipticPos = pos;
PlanetP p = parent; PlanetP p = parent;
if (p) if (p)
skipping to change at line 526 skipping to change at line 897
} }
// 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 (radians) for an observer at pos obsPos in heliocent ric coordinates (dist in AU) // Get the phase angle (radians) for an observer at pos obsPos in heliocent ric coordinates (dist in AU)
double Planet::getPhase(const Vec3d& obsPos) const double Planet::getPhaseAngle(const Vec3d& obsPos) const
{ {
const double observerRq = obsPos.lengthSquared(); const double observerRq = obsPos.lengthSquared();
const Vec3d& planetHelioPos = getHeliocentricEclipticPos(); const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double planetRq = planetHelioPos.lengthSquared(); const double planetRq = planetHelioPos.lengthSquared();
const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua red(); const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua red();
//return std::acos(observerPlanetRq + planetRq - observerRq)/(2.0*sq rt(observerPlanetRq*planetRq)); //return std::acos(observerPlanetRq + planetRq - observerRq)/(2.0*sq rt(observerPlanetRq*planetRq));
return std::acos((observerPlanetRq + planetRq - observerRq)/(2.0*sqr t(observerPlanetRq*planetRq))); return std::acos((observerPlanetRq + planetRq - observerRq)/(2.0*sqr t(observerPlanetRq*planetRq)));
} }
// Get the planet phase for an observer at pos obsPos in heliocentric coord
inates (in AU)
float Planet::getPhase(const Vec3d& obsPos) const
{
const double observerRq = obsPos.lengthSquared();
const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double planetRq = planetHelioPos.lengthSquared();
const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua
red();
const double cos_chi = (observerPlanetRq + planetRq - observerRq)/(2
.0*sqrt(observerPlanetRq*planetRq));
return 0.5f * std::abs(1.f + cos_chi);
}
// Get the elongation angle (radians) for an observer at pos obsPos in heli ocentric coordinates (dist in AU) // Get the elongation angle (radians) for an observer at pos obsPos in heli ocentric coordinates (dist in AU)
double Planet::getElongation(const Vec3d& obsPos) const double Planet::getElongation(const Vec3d& obsPos) const
{ {
const double observerRq = obsPos.lengthSquared(); const double observerRq = obsPos.lengthSquared();
const Vec3d& planetHelioPos = getHeliocentricEclipticPos(); const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double planetRq = planetHelioPos.lengthSquared(); const double planetRq = planetHelioPos.lengthSquared();
const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua red(); const double observerPlanetRq = (obsPos - planetHelioPos).lengthSqua red();
return std::acos((observerPlanetRq + observerRq - planetRq)/(2.0*sq rt(observerPlanetRq*observerRq))); return std::acos((observerPlanetRq + observerRq - planetRq)/(2.0*sq rt(observerPlanetRq*observerRq)));
} }
skipping to change at line 561 skipping to change at line 943
{ {
Vec3d altAz=getAltAzPosApparent(core); Vec3d altAz=getAltAzPosApparent(core);
altAz.normalize(); altAz.normalize();
core->getSkyDrawer()->getExtinction().forward(&altAz[2], &extinc tionMag); core->getSkyDrawer()->getExtinction().forward(&altAz[2], &extinc tionMag);
} }
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
const double distParsec = std::sqrt(core->getObserverHelioce ntricEclipticPos().lengthSquared())*AU/PARSEC; const double distParsec = std::sqrt(core->getObserverHelioce ntricEclipticPos().lengthSquared())*AU/PARSEC;
return 4.83 + 5.*(std::log10(distParsec)-1.) + extinctionMag
; // check how much of it is visible
const SolarSystem* ssm = GETSTELMODULE(SolarSystem);
double shadowFactor = ssm->getEclipseFactor(core);
if(shadowFactor < 1e-11)
shadowFactor = 1e-11;
return 4.83 + 5.*(std::log10(distParsec)-1.) - 2.5*(std::log
10(shadowFactor)) + extinctionMag;
} }
// Compute the angular phase // Compute the angular phase
const Vec3d& observerHelioPos = core->getObserverHeliocentricEclipti cPos(); const Vec3d& observerHelioPos = core->getObserverHeliocentricEclipti cPos();
const double observerRq = observerHelioPos.lengthSquared(); const double observerRq = observerHelioPos.lengthSquared();
const Vec3d& planetHelioPos = getHeliocentricEclipticPos(); const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
const double planetRq = planetHelioPos.lengthSquared(); const double planetRq = planetHelioPos.lengthSquared();
const double observerPlanetRq = (observerHelioPos - planetHelioPos). lengthSquared(); const double observerPlanetRq = (observerHelioPos - planetHelioPos). lengthSquared();
const double cos_chi = (observerPlanetRq + planetRq - observerRq)/(2 .0*sqrt(observerPlanetRq*planetRq)); const double cos_chi = (observerPlanetRq + planetRq - observerRq)/(2 .0*sqrt(observerPlanetRq*planetRq));
double phase = std::acos(cos_chi); double phase = std::acos(cos_chi);
skipping to change at line 734 skipping to change at line 1123
rad = rings->getSize(); rad = rings->getSize();
return std::atan2(rad*sphereScale,getJ2000EquatorialPos(core).length ()) * 180./M_PI; return std::atan2(rad*sphereScale,getJ2000EquatorialPos(core).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).len gth()) * 180./M_PI; return std::atan2(radius*sphereScale,getJ2000EquatorialPos(core).len gth()) * 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, const QFont& planetNa void Planet::draw(StelCore* core, StelRenderer* renderer, float maxMagLabel
meFont) s,
const QFont& planetNameFont,
SharedPlanetGraphics& planetGraphics)
{ {
if (hidden) if (hidden)
return; return;
Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
PlanetP 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!!!
StelProjector::ModelViewTranformP transfo = core->getHeliocentricEcl ipticModelViewTransform(); StelProjector::ModelViewTranformP transfo = core->getHeliocentricEcl ipticModelViewTransform();
transfo->combine(mat); transfo->combine(mat);
if (getEnglishName() == core->getCurrentLocation().planetName) if (getEnglishName() == core->getCurrentLocation().planetName)
{ {
// Draw the rings if we are located on a planet with rings, but not the planet itself. // 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(transfo)); rings->draw(core->getProjection(transfo), renderer,
rings->draw(&sPainter,transfo,1000.0); transfo, planetGraphics.planetShader, 1000.0,
planetGraphics.planetShader
== planetGraphics.shadowPlanetShader ? &planetGraphics.info : NULL);
} }
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(transfo); const StelProjectorP prj = core->getProjection(transfo);
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(Vec3d(0), screenPos) if (prj->project(Vec3d(0), screenPos)
&& screenPos[1]>viewport_bottom - screenSz && screenPos[1] < vie wport_bottom + prj->getViewportHeight()+screenSz && screenPos[1]>viewport_bottom - screenSz && screenPos[1] < vie wport_bottom + prj->getViewportHeight()+screenSz
&& screenPos[0]>viewport_left - screenSz && screenPos[0] < viewp ort_left + prj->getViewportWidth() + screenSz) && screenPos[0]>viewport_left - screenSz && screenPos[0] < viewp ort_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(core).length())/core->getMovementMgr()->getCurrentFov(); float ang_dist = 300.f*atan(getEclipticPos().length()/getEqu inoxEquatorialPos(core).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, renderer); // TODO - fade in here also...
if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitud e(core)) if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitud e(core))
{ {
labelsFader=true; labelsFader=true;
} }
else else
{ {
labelsFader=false; labelsFader=false;
} }
drawHints(core, planetNameFont); drawHints(core, renderer, planetNameFont, planetGraphics);
draw3dModel(core,transfo,screenSz); draw3dModel(core, renderer, planetGraphics, transfo, screenS z);
} }
return; return;
} }
void Planet::draw3dModel(StelCore* core, StelProjector::ModelViewTranformP void Planet::draw3dModel(StelCore* core, StelRenderer* renderer,
transfo, float screenSz) SharedPlanetGraphics& planetGraphics,
StelProjector::ModelViewTranformP transfo, float s
creenSz)
{ {
// 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
if (screenSz>1.) if (screenSz > 1.0f)
{ {
StelProjector::ModelViewTranformP transfo2 = transfo->clone( ); StelProjector::ModelViewTranformP transfo2 = transfo->clone( );
transfo2->combine(Mat4d::zrotation(M_PI/180*(axisRotation + 90.))); transfo2->combine(Mat4d::zrotation(M_PI/180*(axisRotation + 90.)));
StelPainter* sPainter = new StelPainter(core->getProjection( StelProjectorP projector = core->getProjection(transfo2);
transfo2)); StelLight light;
if (flagLighting) if (flagLighting)
{ {
sPainter->getLight().enable();
// Set the main source of light to be the sun // Set the main source of light to be the sun
Vec3d sunPos(0); Vec3d sunPos(0);
core->getHeliocentricEclipticModelViewTransform()->f orward(sunPos); core->getHeliocentricEclipticModelViewTransform()->f orward(sunPos);
sPainter->getLight().setPosition(Vec4f(sunPos[0],sun
Pos[1],sunPos[2],1.f));
// Set the light parameters taking sun as the light source // Set the light parameters taking sun as the light source
static Vec4f diffuse = Vec4f(2.f,2.f,2.f,1.f); light.position = Vec3f(sunPos[0], sunPos[1], sunPos[
static Vec4f zero = Vec4f(0.f,0.f,0.f,0.f); 2]);
static Vec4f ambient = Vec4f(0.02f,0.02f,0.02f,0.02f light.ambient = Vec4f(0.02f, 0.02f, 0.02f, 0.02f);
); light.diffuse = Vec4f(2.0f, 2.0f, 2.0f, 1.0f);
if (StelApp::getInstance().getVisionModeNight()) if (StelApp::getInstance().getVisionModeNight())
{ {
diffuse[1] = 0.; diffuse[2] = 0.; light.diffuse[1] = 0.; light.diffuse[2] = 0.
ambient[1] = 0.; ambient[2] = 0.; ;
light.ambient[1] = 0.; light.ambient[2] = 0.
;
} }
else
{
diffuse[1] = 2.; diffuse[2] = 2.;
ambient[1] = 0.02; ambient[2] = 0.02;
}
sPainter->getLight().setAmbient(ambient);
sPainter->getLight().setDiffuse(diffuse);
sPainter->getLight().setSpecular(zero);
sPainter->getMaterial().setAmbient(ambient);
sPainter->getMaterial().setEmission(zero);
sPainter->getMaterial().setShininess(0.f);
sPainter->getMaterial().setSpecular(zero);
}
else
{
sPainter->getLight().disable();
sPainter->setColor(1.f,1.f,1.f);
} }
if (rings) if (rings)
{ {
const double dist = getEquinoxEquatorialPos(core).le ngth(); const double dist = getEquinoxEquatorialPos(core).le ngth();
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); renderer->clearDepthBuffer();
glEnable(GL_DEPTH_TEST); renderer->setDepthTest(DepthTest_ReadWrite);
drawSphere(sPainter, screenSz); drawSphere(renderer, projector, flagLighting ? &ligh
glDepthMask(GL_FALSE); t : NULL,
sPainter->getLight().disable(); planetGraphics, screenSz);
rings->draw(sPainter,transfo,screenSz); renderer->setDepthTest(DepthTest_ReadOnly);
sPainter->getLight().enable(); rings->draw(projector, renderer, transfo, planetGrap
glDisable(GL_DEPTH_TEST); hics.planetShader, screenSz,
planetGraphics.planetShader
== planetGraphics.shadowPlanetShader ? &planetGraphics.info : NULL);
renderer->setDepthTest(DepthTest_Disabled);
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() && core->getCurrentLocation ().planetName=="Earth" && ssm->nearLunarEclipse()) if (this==ssm->getMoon() && core->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); renderer->clearStencilBuffer();
glClear(GL_STENCIL_BUFFER_BIT); renderer->setStencilTest(StencilTest_Write_1
glStencilFunc(GL_ALWAYS, 0x1, 0x1); );
glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE) drawSphere(renderer, projector, flagLighting
; ? &light : NULL,
glEnable(GL_STENCIL_TEST); planetGraphics, screenSz)
drawSphere(sPainter, screenSz); ;
glDisable(GL_STENCIL_TEST); renderer->setStencilTest(StencilTest_Disable
d);
sPainter->getLight().disable(); if(planetGraphics.planetShader == planetGrap
drawEarthShadow(core, sPainter); hics.simplePlanetShader)
drawEarthShadow(core, renderer, plan
etGraphics);
} }
else else
{ {
// Normal planet // Normal planet
drawSphere(sPainter, screenSz); drawSphere(renderer, projector, flagLighting
? &light : NULL,
planetGraphics, screenSz)
;
} }
} }
if (sPainter)
delete sPainter;
sPainter=NULL;
} }
// Draw the halo // Draw the halo
// 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)); const Vec3d tmp = getJ2000EquatorialPos(core);
Vec3d tmp = getJ2000EquatorialPos(core); float mag = getVMagnitude(core, true);
core->getSkyDrawer()->postDrawSky3dModel(&sPainter, tmp, surfArcMin2
, getVMagnitude(core, true), color); SolarSystem* ssm = GETSTELMODULE(SolarSystem);
if(this != ssm->getSun() || mag < -15.0f)
core->getSkyDrawer()
->postDrawSky3dModel(core->getProjection(StelCore::F
rameJ2000),
tmp, surfAr
cMin2, mag, color);
if(this == ssm->getSun() && core->getCurrentLocation().planetName ==
"Earth")
{
float eclipseFactor = ssm->getEclipseFactor(core);
if(eclipseFactor < 0.001)
{
core->getSkyDrawer()->drawSunCorona(core->getProject
ion(StelCore::FrameJ2000), tmp, screenSz, 1.0 - eclipseFactor * 1000);
}
}
} }
void Planet::drawSphere(StelPainter* painter, float screenSz) void Planet::drawUnlitSphere(StelRenderer* renderer, StelProjectorP project or)
{ {
if (texMap) if(NULL == unlitSphere)
{ {
// For lazy loading, return if texture not yet loaded const SphereParams params = SphereParams(radius * sphereScal
if (!texMap->bind()) e).resolution(40, 40)
.oneMinusOblateness(oneMinusObla
teness);
unlitSphere = StelGeometryBuilder().buildSphereUnlit(params)
;
}
unlitSphere->draw(renderer, projector);
}
void Planet::drawSphere(StelRenderer* renderer, StelProjectorP projector,
const StelLight* light, Shar
edPlanetGraphics& planetGraphics, float screenSz)
{
if(texMapName == "") {return;}
if(NULL == texture)
{
const TextureParams textureParams =
TextureParams().generateMipmaps().wrap(TextureWrap_R
epeat);
texture = renderer->createTexture("textures/" + texMapName,
textureParams,
TextureLoadingMode_LazyAsy
nchronous);
}
texture->bind();
renderer->setBlendMode(BlendMode_None);
renderer->setCulledFaces(CullFace_Back);
// Now draw the sphere
// Lighting is disabled, so just draw the plain sphere.
if(NULL == light)
{
const Vec4f color = StelApp::getInstance().getVisionModeNigh
t()
? Vec4f(1.f, 0.f, 0.f, 1.0f) : Vec4f(1.f,
1.f, 1.f, 1.0f);
renderer->setGlobalColor(color);
drawUnlitSphere(renderer, projector);
}
// Do the lighting on shader, avoiding the need to regenerate the sp
here.
// Shader is NULL if it failed to load, in that case we need to do l
ighting on the CPU.
else if(renderer->isGLSLSupported() && NULL != planetGraphics.planet
Shader)
{
StelGLSLShader* shader = planetGraphics.planetShader;
shader->bind();
// provides the unprojectedVertex attribute to the shader.
shader->useUnprojectedPositionAttribute();
Vec3d lightPos = Vec3d(light->position[0], light->position[1
], light->position[2]);
projector->getModelViewTransform()
->getApproximateLinearTransfo()
.transpose()
.multiplyWithoutTranslation(Vec3d(lightPos[0], ligh
tPos[1], lightPos[2]));
projector->getModelViewTransform()->backward(lightPos);
lightPos.normalize();
shader->setUniformValue("lightPos" , Vec3f(lightPo
s[0], lightPos[1] , lightPos[2]));
shader->setUniformValue("diffuseLight" , light->diffus
e);
shader->setUniformValue("ambientLight" , light->ambien
t);
shader->setUniformValue("radius" , static_cast<f
loat>(radius * sphereScale));
shader->setUniformValue("oneMinusOblateness" , static_cast<f
loat>(oneMinusOblateness));
if(shader == planetGraphics.shadowPlanetShader)
{ {
return; shader->setUniformValue("info", planetGraphics.info.
info);
shader->setUniformValue("infoCount", planetGraphics.
info.infoCount);
shader->setUniformValue("infoSize", planetGraphics.i
nfo.infoSize);
shader->setUniformValue("current", planetGraphics.in
fo.current);
shader->setUniformValue("isRing", false);
const bool ring = (rings != NULL) && rings->texture;
if(ring)
rings->texture->bind(2);
shader->setUniformValue("ring", ring);
shader->setUniformValue("outerRadius", ring ? static
_cast<float>(rings->radiusMax) : 0.0f);
shader->setUniformValue("innerRadius", ring ? static
_cast<float>(rings->radiusMin) : 0.0f);
shader->setUniformValue("ringS", ring ? 2 : 0)
;
const bool moon = this == GETSTELMODULE(SolarSystem)
->getMoon();
if(moon)
planetGraphics.texEarthShadow->bind(3);
shader->setUniformValue("isMoon", moon);
shader->setUniformValue("earthShadow", moon ? 3: 0);
} }
drawUnlitSphere(renderer, projector);
shader->release();
} }
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // If shaders are not supported and we need lighting, we generate th
if (StelApp::getInstance().getVisionModeNight()) e sphere
painter->setColor(1.f, 0.f, 0.f); // with lighting baked into vertex colors.
else else
painter->setColor(1.f, 1.f, 1.f); {
// Adapt the number of facets according with the size of the
sphere for optimization
// 40 facets for 1024 pixels diameter on screen
const int resolution = std::min(40, std::max(7, static_cast<
int>(screenSz * 40.0 / 50.0)));
// Lazily construct the lit sphere.
if(NULL == litSphere)
{
const SphereParams params = SphereParams(radius * sp
hereScale)
.resolution(resolution,
resolution)
.oneMinusOblateness(oneM
inusOblateness);
litSphere = StelGeometryBuilder().buildSphereLit(par
ams, *light);
}
else
{
litSphere->setResolution(resolution, resolution);
litSphere->setLight(*light);
}
litSphere->draw(renderer, projector);
}
painter->enableTexture2d(true); renderer->setCulledFaces(CullFace_None);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
// 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;
painter->setShadeModel(StelPainter::ShadeModelSmooth);
// 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);
painter->setShadeModel(StelPainter::ShadeModelFlat);
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, StelPainter* sPainter) void Planet::drawEarthShadow(StelCore* core, StelRenderer* renderer,
SharedPlanetGraphics& planetGraphics)
{ {
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 972 skipping to change at line 1433
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;
StelProjectorP saveProj = sPainter->getProjector(); StelProjectorP projector = core->getProjection(StelCore::FrameHelioc
sPainter->setProjector(core->getProjection(StelCore::FrameHeliocentr entricEcliptic);
icEcliptic));
sPainter->enableTexture2d(true);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
sPainter->setColor(1,1,1);
glEnable(GL_STENCIL_TEST); renderer->setBlendMode(BlendMode_Alpha);
renderer->setGlobalColor(1.0f, 1.0f, 1.0f);
// We draw only where the stencil buffer is at 1, i.e. where the moo n was drawn // We draw only where the stencil buffer is at 1, i.e. where the moo n was drawn
glStencilFunc(GL_EQUAL, 0x1, 0x1); renderer->setStencilTest(StencilTest_DrawIf_1);
// Don't change stencil buffer value
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// shadow radial texture // shadow radial texture
texEarthShadow->bind(); planetGraphics.texEarthShadow->bind();
Vec3d r;
// Draw umbra first // Draw umbra first
QVector<Vec2f> texCoordArray; StelVertexBuffer<VertexP3T2>* umbra =
QVector<Vec3d> vertexArray; renderer->createVertexBuffer<VertexP3T2>(PrimitiveType_Trian
texCoordArray.reserve(210); gleFan);
vertexArray.reserve(210);
texCoordArray << Vec2f(0.f, 0.5f);
// johannes: work-around for nasty ATI rendering bug: use y-texture
coordinate of 0.5 instead of 0.0
vertexArray << shadow;
// johannes: work-around for nasty ATI rendering bug: use y-texture coordinate of 0.5 instead of 0.0
const Mat4d& rotMat = Mat4d::rotation(shadow, 2.*M_PI/100.); const Mat4d& rotMat = Mat4d::rotation(shadow, 2.*M_PI/100.);
r = upt; Vec3f r(upt[0], upt[1], upt[2]);
const Vec3f shadowF(shadow[0], shadow[1], shadow[2]);
umbra->addVertex(VertexP3T2(shadowF, Vec2f(0.0f, 0.5f)));
for (int i=1; i<=101; ++i) for (int i=1; i<=101; ++i)
{ {
// position in texture of umbra edge
texCoordArray << Vec2f(0.6f, 0.5f);
r.transfo4d(rotMat); r.transfo4d(rotMat);
vertexArray << shadow + r; // position in texture of umbra edge
umbra->addVertex(VertexP3T2(shadowF + r, Vec2f(0.6f, 0.5f)))
;
} }
sPainter->setArrays(vertexArray.constData(), texCoordArray.constData umbra->lock();
()); renderer->drawVertexBuffer(umbra, NULL, projector);
sPainter->drawFromArray(StelPainter::TriangleFan, 102); delete umbra;
// now penumbra // now penumbra
vertexArray.resize(0); StelVertexBuffer<VertexP3T2>* penumbra =
texCoordArray.resize(0); renderer->createVertexBuffer<VertexP3T2>(PrimitiveType_Trian
Vec3d u; gleStrip);
r = rpt; Vec3f u = r;
u = upt; r = Vec3f(rpt[0], rpt[1], rpt[2]);
for (int i=0; i<=200; i+=2) for (int i=0; i<=200; i+=2)
{ {
r.transfo4d(rotMat); r.transfo4d(rotMat);
u.transfo4d(rotMat); u.transfo4d(rotMat);
texCoordArray << Vec2f(0.6f, 0.5f) << Vec2f(1.f, 0.5f); // p
osition in texture of umbra edge // position in texture of umbra edge
vertexArray << shadow + u << shadow + r; penumbra->addVertex(VertexP3T2(shadowF + u, Vec2f(0.6f, 0.5f
)));
penumbra->addVertex(VertexP3T2(shadowF + r, Vec2f(1.0f, 0.5f
)));
} }
sPainter->setArrays(vertexArray.constData(), texCoordArray.constData penumbra->lock();
()); renderer->drawVertexBuffer(penumbra, NULL, projector);
sPainter->drawFromArray(StelPainter::TriangleStrip, 202); delete penumbra;
glDisable(GL_STENCIL_TEST);
glClearStencil(0x0); renderer->setStencilTest(StencilTest_Disabled);
glClear(GL_STENCIL_BUFFER_BIT); // Clean again to let a clean buffer renderer->clearStencilBuffer();
for later Qt display
sPainter->setProjector(saveProj);
} }
void Planet::drawHints(const StelCore* core, const QFont& planetNameFont) void Planet::drawHints(const StelCore* core, StelRenderer* renderer,
const QFont& planetNameFont, SharedPlanetGraphics& p
lanetGraphics)
{ {
if (labelsFader.getInterstate()<=0.f) if (labelsFader.getInterstate()<=0.f)
return; return;
const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000) ;
StelPainter sPainter(prj); renderer->setFont(planetNameFont);
sPainter.setFont(planetNameFont);
// Draw nameI18 + scaling if it's not == 1. // Draw nameI18 + scaling if it's not == 1.
float tmp = (hintFader.getInterstate()<=0 ? 7.f : 10.f) + getAngular Size(core)*M_PI/180.f*prj->getPixelPerRadAtCenter()/1.44f; // Shift for nam eI18 printing float tmp = (hintFader.getInterstate()<=0 ? 7.f : 10.f) + getAngular Size(core)*M_PI/180.f*prj->getPixelPerRadAtCenter()/1.44f; // Shift for nam eI18 printing
sPainter.setColor(labelColor[0], labelColor[1], labelColor[2],labels
Fader.getInterstate()); Vec4f color(labelColor[0], labelColor[1], labelColor[2], labelsFader
sPainter.drawText(screenPos[0],screenPos[1], getSkyLabel(core), 0, t .getInterstate());
mp, tmp, false); renderer->setGlobalColor(color);
renderer->drawText(TextParams(screenPos[0], screenPos[1], getSkyLabe
l(core))
.shift(tmp, tmp).useGravity());
// 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;
sPainter.setColor(labelColor[0], labelColor[1], labelColor[2],labels color[3] *= hintFader.getInterstate() / tmp * 0.7f;
Fader.getInterstate()*hintFader.getInterstate()/tmp*0.7f); renderer->setGlobalColor(color);
// Draw the 2D small circle // Draw the 2D small circle
glEnable(GL_BLEND); renderer->setBlendMode(BlendMode_Alpha);
sPainter.enableTexture2d(true); planetGraphics.texHintCircle->bind();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); renderer->drawTexturedRect(screenPos[0] - 11, screenPos[1] - 11, 22,
Planet::hintCircleTex->bind(); 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)
, texName(texname)
, texture(NULL)
, ring(NULL)
{ {
tex = StelApp::getInstance().getTextureManager().createTexture("text ures/"+texname);
} }
Ring::~Ring(void) Ring::~Ring(void)
{ {
if(NULL != ring)
{
delete ring;
ring = NULL;
}
if(NULL != texture)
{
delete texture;
texture = NULL;
}
} }
void Ring::draw(StelPainter* sPainter,StelProjector::ModelViewTranformP tra void Ring::draw(StelProjectorP projector, StelRenderer* renderer,
nsfo,double screenSz) StelProjector::ModelViewTranformP transfo, c
lass StelGLSLShader* shader, double screenSz, ShadowPlanetShaderInfo* info)
{ {
if(NULL == texture)
{
texture = renderer->createTexture("textures/" + texName);
}
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 renderer->setBlendMode(BlendMode_Alpha);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); renderer->setCulledFaces(CullFace_Back);
if (StelApp::getInstance().getVisionModeNight()) const Vec4f color = StelApp::getInstance().getVisionModeNight()
sPainter->setColor(1.f, 0.f, 0.f); ? Vec4f(1.f, 0.f, 0.f, 1.0f) : Vec4f(1.f, 1.f, 1.f
, 1.0f);
renderer->setGlobalColor(color);
texture->bind();
Mat4d mat = transfo->getApproximateLinearTransfo();
// solve the ring wraparound by culling:
// decide if we are above or below the ring plane
const double h = mat.r[ 8] * mat.r[12]
+ mat.r[ 9] * mat.r[13]
+ mat.r[10] * mat.r[14];
if(NULL == ring)
{
ring = StelGeometryBuilder()
.buildRingTextured(RingParams(radiusMin, radiusMax).
resolution(slices, stacks));
}
else else
sPainter->setColor(1.f, 1.f, 1.f); {
ring->setResolution(slices, stacks);
}
ring->setFlipFaces(h >= 0);
sPainter->enableTexture2d(true); if(info && renderer->isGLSLSupported())
glEnable(GL_CULL_FACE); {
glEnable(GL_BLEND); shader->bind();
// provides the unprojectedVertex attribute to the shader.
shader->useUnprojectedPositionAttribute();
if (tex) tex->bind(); shader->setUniformValue("lightPos" , Vec3f(0, 0, 0
));
shader->setUniformValue("diffuseLight" , Vec4f(1, 1, 1
, 1));
shader->setUniformValue("ambientLight" , Vec4f(0, 0, 0
, 1));
shader->setUniformValue("radius" , 1.0f);
shader->setUniformValue("oneMinusOblateness" , 1.0f);
Mat4d mat = transfo->getApproximateLinearTransfo(); shader->setUniformValue("info", info->info);
// solve the ring wraparound by culling: shader->setUniformValue("infoCount", info->infoCount);
// decide if we are above or below the ring plane shader->setUniformValue("infoSize", info->infoSize);
const double h = mat.r[ 8]*mat.r[12] shader->setUniformValue("current", info->current);
+ mat.r[ 9]*mat.r[13]
+ mat.r[10]*mat.r[14]; shader->setUniformValue("isRing", true);
sPainter->sRing(radiusMin,radiusMax,(h<0.0)?slices:-slices,stacks, 0
); shader->setUniformValue("ring", true);
glDisable(GL_CULL_FACE); shader->setUniformValue("outerRadius", static_cast<float>(ra
diusMax));
shader->setUniformValue("innerRadius", static_cast<float>(ra
diusMin));
shader->setUniformValue("ringS", 0);
}
ring->draw(renderer, projector);
if(info && renderer->isGLSLSupported())
{
shader->release();
}
renderer->setCulledFaces(CullFace_None);
} }
// draw orbital path of Planet // draw orbital path of Planet
void Planet::drawOrbit(const StelCore* core) void Planet::drawOrbit(const StelCore* core, StelRenderer* renderer)
{ {
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); renderer->setBlendMode(BlendMode_Alpha);
renderer->setGlobalColor(orbitColor[0], orbitColor[1],
// Normal transparency mode orbitColor[2], orbitFader.getInterstate());
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
sPainter.setColor(orbitColor[0], orbitColor[1], orbitColor[2], orbit Fader.getInterstate());
Vec3d onscreen; Vec3d onscreen;
// special case - use current Planet position as center vertex so th at draws // 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) // on it's orbit all the time (since segmented rather than smooth cu rve)
Vec3d savePos = orbit[ORBIT_SEGMENTS/2]; Vec3d savePos = orbit[ORBIT_SEGMENTS/2];
orbit[ORBIT_SEGMENTS/2]=getHeliocentricEclipticPos(); orbit[ORBIT_SEGMENTS/2]=getHeliocentricEclipticPos();
orbit[ORBIT_SEGMENTS]=orbit[0]; orbit[ORBIT_SEGMENTS]=orbit[0];
int nbIter = closeOrbit ? ORBIT_SEGMENTS : ORBIT_SEGMENTS-1; int nbIter = closeOrbit ? ORBIT_SEGMENTS : ORBIT_SEGMENTS-1;
QVarLengthArray<float, 1024> vertexArray;
sPainter.enableClientStates(true, false, false); if(NULL == orbitVertices)
{
orbitVertices =
renderer->createVertexBuffer<Vertex2D>(PrimitiveType
_LineStrip);
}
for (int n=0; n<=nbIter; ++n) for (int n=0; n<=nbIter; ++n)
{ {
if (prj->project(orbit[n],onscreen) && (vertexArray.size()== 0 || !prj->intersectViewportDiscontinuity(orbit[n-1], orbit[n]))) if (prj->project(orbit[n],onscreen) && (orbitVertices->lengt h()==0 || !prj->intersectViewportDiscontinuity(orbit[n-1], orbit[n])))
{ {
vertexArray.append(onscreen[0]); orbitVertices->addVertex(Vertex2D(onscreen[0], onscr
vertexArray.append(onscreen[1]); een[1]));
} }
else if (!vertexArray.isEmpty()) else if(orbitVertices->length() > 0)
{ {
sPainter.setVertexPointer(2, GL_FLOAT, vertexArray.c orbitVertices->lock();
onstData()); renderer->drawVertexBuffer(orbitVertices);
sPainter.drawFromArray(StelPainter::LineStrip, verte orbitVertices->unlock();
xArray.size()/2, 0, false); orbitVertices->clear();
vertexArray.clear();
} }
} }
orbit[ORBIT_SEGMENTS/2]=savePos; orbit[ORBIT_SEGMENTS/2]=savePos;
if (!vertexArray.isEmpty())
if(orbitVertices->length() > 0)
{ {
sPainter.setVertexPointer(2, GL_FLOAT, vertexArray.constData orbitVertices->lock();
()); renderer->drawVertexBuffer(orbitVertices);
sPainter.drawFromArray(StelPainter::LineStrip, vertexArray.s orbitVertices->unlock();
ize()/2, 0, false); orbitVertices->clear();
} }
sPainter.enableClientStates(false);
} }
void Planet::update(int deltaTime) void Planet::update(int deltaTime)
{ {
hintFader.update(deltaTime); hintFader.update(deltaTime);
labelsFader.update(deltaTime); labelsFader.update(deltaTime);
orbitFader.update(deltaTime); orbitFader.update(deltaTime);
} }
void Planet::setSphereScale(float s)
{
sphereScale = s;
if(NULL != unlitSphere) {unlitSphere->setRadius(radius * s);}
if(NULL != litSphere) {litSphere->setRadius(radius * s);}
}
 End of changes. 93 change blocks. 
258 lines changed or deleted 862 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/