Comet.cpp   Comet.cpp 
/* /*
* Stellarium * Stellarium
* Copyright (C) 2010 Bogdan Marinov * Copyright (C) 2010 Bogdan Marinov
* Copyright (C) 2014 Georg Zotti (Tails)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 29 skipping to change at line 30
#include "Comet.hpp" #include "Comet.hpp"
#include "Orbit.hpp" #include "Orbit.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "StelTexture.hpp" #include "StelTexture.hpp"
#include "StelTextureMgr.hpp" #include "StelTextureMgr.hpp"
#include "StelToneReproducer.hpp"
#include "StelTranslator.hpp" #include "StelTranslator.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "StelMovementMgr.hpp" #include "StelMovementMgr.hpp"
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "LandscapeMgr.hpp" #include "LandscapeMgr.hpp"
#include <QRegExp> #include <QRegExp>
#include <QDebug> #include <QDebug>
skipping to change at line 74 skipping to change at line 76
"", "",
coordFunc, coordFunc,
auserDataPtr, auserDataPtr,
osculatingFunc, osculatingFunc,
acloseOrbit, acloseOrbit,
hidden, hidden,
false, //No atmosphere false, //No atmosphere
true, //halo true, //halo
pTypeStr), pTypeStr),
tailActive(false), tailActive(false),
tailBright(false),
dustTailWidthFactor(dustTailWidthFact), dustTailWidthFactor(dustTailWidthFact),
dustTailLengthFactor(dustTailLengthFact), dustTailLengthFactor(dustTailLengthFact),
dustTailBrightnessFactor(dustTailBrightnessFact) dustTailBrightnessFactor(dustTailBrightnessFact)
{ {
texMapName = atexMapName; texMapName = atexMapName;
lastOrbitJD =0; lastOrbitJD =0;
deltaJD = StelCore::JD_SECOND; deltaJD = StelCore::JD_SECOND;
deltaJDtail=15.0*StelCore::JD_MINUTE; // update tail geometry every 15 minutes only deltaJDtail=15.0*StelCore::JD_MINUTE; // update tail geometry every 15 minutes only
lastJDtail=0.0; lastJDtail=0.0;
orbitCached = 0; orbitCached = 0;
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(StelFileMgr::getInstallationDir()+"/textures/"+texMapName, StelTexture: :StelTextureParams(true, GL_LINEAR, GL_REPEAT)); texMap = StelApp::getInstance().getTextureManager().createTextureThr ead(StelFileMgr::getInstallationDir()+"/textures/"+texMapName, StelTexture: :StelTextureParams(true, GL_LINEAR, GL_REPEAT));
gastailVertexArr.clear(); gastailVertexArr.clear();
dusttailVertexArr.clear(); dusttailVertexArr.clear();
comaVertexArr.clear(); comaVertexArr.clear();
gastailColorArr.clear();
dusttailColorArr.clear();
//Comet specific members //Comet specific members
absoluteMagnitude = 0; absoluteMagnitude = 0;
slopeParameter = -1;//== uninitialized: used in getVMagnitude() slopeParameter = -1;//== uninitialized: used in getVMagnitude()
//TODO: Name processing? //TODO: Name processing?
nameI18 = englishName; nameI18 = englishName;
flagLabels = true; flagLabels = true;
skipping to change at line 127 skipping to change at line 132
return; return;
} }
//TODO: More checks? //TODO: More checks?
//TODO: Make it set-once like the number? //TODO: Make it set-once like the number?
absoluteMagnitude = magnitude; absoluteMagnitude = magnitude;
slopeParameter = slope; slopeParameter = slope;
} }
void Comet::translateName(const StelTranslator &translator)
{
nameI18 = translator.qtranslate(englishName);
}
QString Comet::getInfoString(const StelCore *core, const InfoStringGroup &f lags) const QString Comet::getInfoString(const StelCore *core, const InfoStringGroup &f lags) const
{ {
//Mostly copied from Planet::getInfoString(): //Mostly copied from Planet::getInfoString():
QString str; QString str;
QTextStream oss(&str); QTextStream oss(&str);
if (flags&Name) if (flags&Name)
{ {
oss << "<h2>"; oss << "<h2>";
oss << q_(englishName); // UI translation can differ from s ky translation oss << getNameI18n(); // UI translation can differ 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&ObjectType) if (flags&ObjectType && getPlanetType()!=isUNDEFINED)
{ {
oss << q_("Type: <b>%1</b>").arg(q_(getPlanetTypeString())) << "<br />"; oss << q_("Type: <b>%1</b>").arg(q_(getPlanetTypeString())) << "<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), 'f', 2), oss << q_("Magnitude: <b>%1</b> (extincted to: <b>%2</b>)"). arg(QString::number(getVMagnitude(core), 'f', 2),
QString::number(getVMagnitudeWithExtinction(core), 'f', 2)) << "<br>"; QString::number(getVMagnitudeWithExtinction(core), 'f', 2)) << "<br>";
else else
skipping to change at line 284 skipping to change at line 294
//Sources: http://www.clearskyinstitute.com/xephem/help/xephem.html# mozTocId564354 //Sources: http://www.clearskyinstitute.com/xephem/help/xephem.html# mozTocId564354
//(XEphem manual, section 7.1.2.3 "Magnitude models"), also //(XEphem manual, section 7.1.2.3 "Magnitude models"), also
//http://www.ayton.id.au/gary/Science/Astronomy/Ast_comets.htm#Comet %20facts: //http://www.ayton.id.au/gary/Science/Astronomy/Ast_comets.htm#Comet %20facts:
// GZ: Note that Meeus, Astr.Alg.1998 p.231, has m=absoluteMagnitude +5log10(observerCometDistance) + kappa*log10(cometSunDistance) // GZ: Note that Meeus, Astr.Alg.1998 p.231, has m=absoluteMagnitude +5log10(observerCometDistance) + kappa*log10(cometSunDistance)
// with kappa typically 5..15. MPC provides Slope parameter. So we s hould expect to have slopeParameter (a word only used for minor planets!) f or our comets 2..6 // with kappa typically 5..15. MPC provides Slope parameter. So we s hould expect to have slopeParameter (a word only used for minor planets!) f or our comets 2..6
double apparentMagnitude = absoluteMagnitude + 5 * std::log10(observ erCometDistance) + 2.5 * slopeParameter * std::log10(cometSunDistance); double apparentMagnitude = absoluteMagnitude + 5 * std::log10(observ erCometDistance) + 2.5 * slopeParameter * std::log10(cometSunDistance);
return apparentMagnitude; return apparentMagnitude;
} }
// Compute the position in the parent Planet coordinate system void Comet::update(int deltaTime)
// Actually call the provided function to compute the ecliptical position, {
and buildup the tails! Planet::update(deltaTime);
void Comet::computePosition(const double date)
{ // The rest used to be in computePosition(), but is better in update
Planet::computePosition(date); (). Unfortunately we need date (JD).
//GZ: I think we can make deltaJD adaptive, depending on distance to StelCore* core=StelApp::getInstance().getCore();
sun! For some reason though, this leads to a crash! double date=core->getJDay();
//deltaJD=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(),
20.0)); // The CometOrbit is in fact available in userDataPtr!
CometOrbit* orbit=(CometOrbit*)userDataPtr;
Q_ASSERT(orbit);
if (!orbit->objectDateValid(core->getJDay())) return; // don't do an
ything if out of useful date range. This allows having hundreds of comet el
ements.
//GZ: I think we can make deltaJDtail adaptive, depending on distanc
e to sun! For some reason though, this leads to a crash!
//deltaJDtail=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.lengt
h(), 20.0));
if (fabs(lastJDtail-date)>deltaJDtail) if (fabs(lastJDtail-date)>deltaJDtail)
{ {
lastJDtail=date; lastJDtail=date;
// GZ: Moved from draw() :-)
// The CometOrbit is in fact available in userDataPtr! // The CometOrbit is in fact available in userDataPtr!
CometOrbit* orbit=(CometOrbit*)userDataPtr; CometOrbit* orbit=(CometOrbit*)userDataPtr;
Q_ASSERT(orbit); Q_ASSERT(orbit);
if (!orbit->objectDateValid(date)) return; // out of useful date range. This should allow having hundreds of comet elements. if (!orbit->objectDateValid(date)) return; // out of useful date range. This should allow having hundreds of comet elements.
if (orbit->getUpdateTails()){ if (orbit->getUpdateTails()){
// Compute lengths and orientations from orbit objec t, but only if required. // Compute lengths and orientations from orbit objec t, but only if required.
// This part moved from draw() to keep draw() free f rom too much computation.
tailFactors=getComaDiameterAndTailLengthAU(); tailFactors=getComaDiameterAndTailLengthAU();
// Note that we use a diameter larger than what the formula returns. A scale factor of 1.2 is ad-hoc/empirical (GZ), but may lo ok better. // Note that we use a diameter larger than what the formula returns. A scale factor of 1.2 is ad-hoc/empirical (GZ), but may lo ok better.
computeComa(1.0f*tailFactors[0]); computeComa(1.0f*tailFactors[0]); // TBD: APPARENTLY NO SCALING? REMOVE 1.0 and note above.
tailActive = (tailFactors[1] > tailFactors[0]); // I nhibit tails drawing if too short. Would be nice to include geometric proje ction angle, but this is too costly. tailActive = (tailFactors[1] > tailFactors[0]); // I nhibit tails drawing if too short. Would be nice to include geometric proje ction angle, but this is too costly.
if (tailActive) if (tailActive)
{ {
float gasTailEndRadius=qMax(tailFactors[0], 0.025f*tailFactors[1]) ; // This avoids too slim gas tails for bright comet s like Hale-Bopp. float gasTailEndRadius=qMax(tailFactors[0], 0.025f*tailFactors[1]) ; // This avoids too slim gas tails for bright comet s like Hale-Bopp.
float gasparameter=gasTailEndRadius*gasTailE ndRadius/(2.0f*tailFactors[1]); // parabola formula: z=r²/2p, so p=r²/2z float gasparameter=gasTailEndRadius*gasTailE ndRadius/(2.0f*tailFactors[1]); // parabola formula: z=r²/2p, so p=r²/2z
// The dust tail is thicker and usually shor ter. The factors can be configured in the elements. // The dust tail is thicker and usually shor ter. The factors can be configured in the elements.
float dustparameter=gasTailEndRadius*gasTail EndRadius*dustTailWidthFactor*dustTailWidthFactor/(2.0f*dustTailLengthFacto r*tailFactors[1]); float dustparameter=gasTailEndRadius*gasTail EndRadius*dustTailWidthFactor*dustTailWidthFactor/(2.0f*dustTailLengthFacto r*tailFactors[1]);
// Find valid parameters to create paraboloi d vertex arrays: dustTail, gasTail. // Find valid parameters to create paraboloi d vertex arrays: dustTail, gasTail.
computeParabola(gasparameter, gasTailEndRadi us, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices); computeParabola(gasparameter, gasTailEndRadi us, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices);
// This was for a rotated straight parabola: //gastailColorArr.fill(Vec3f(0.3,0.3,0.3), g
//computeParabola(dustparameter, 2.0f*tailFa astailVertexArr.length());
ctors[0], -0.5f*dustparameter, dusttailVertexArr, dusttailTexCoordArr, dust
tailIndices);
// Now we make a skewed parabola. Skew facto r (xOffset, last arg) is rather ad-hoc/empirical. TBD later: Find physicall y correct solution. // Now we make a skewed parabola. Skew facto r (xOffset, last arg) is rather ad-hoc/empirical. TBD later: Find physicall y correct solution.
computeParabola(dustparameter, dustTailWidth Factor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoo rdArr, tailIndices, 25.0f*orbit->getVelocity().length()); computeParabola(dustparameter, dustTailWidth Factor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoo rdArr, tailIndices, 25.0f*orbit->getVelocity().length());
//dusttailColorArr.fill(Vec3f(0.3,0.3,0.3), dusttailVertexArr.length());
// 2014-08 for 0.13.1 Moved from drawTail() to save lots of computation per frame (There *are* folks downloading all 73 0 MPC current comet elements...) // 2014-08 for 0.13.1 Moved from drawTail() to save lots of computation per frame (There *are* folks downloading all 73 0 MPC current comet elements...)
// Find rotation matrix from 0/0/1 to eclipt icPosition: crossproduct for axis (normal vector), dotproduct for angle. // Find rotation matrix from 0/0/1 to eclipt icPosition: crossproduct for axis (normal vector), dotproduct for angle.
Vec3d eclposNrm=eclipticPos; eclposNrm.norma lize(); Vec3d eclposNrm=eclipticPos; eclposNrm.norma lize();
gasTailRot=Mat4d::rotation(Vec3d(0.0, 0.0, 1 .0)^(eclposNrm), std::acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) ); gasTailRot=Mat4d::rotation(Vec3d(0.0, 0.0, 1 .0)^(eclposNrm), std::acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) );
Vec3d velocity=orbit->getVelocity(); // [AU/ d] Vec3d velocity=orbit->getVelocity(); // [AU/ d]
// This was a try to rotate a straight parab ola somewhat away from the antisolar direction. // This was a try to rotate a straight parab ola somewhat away from the antisolar direction.
//Mat4d dustTailRot=Mat4d::rotation(eclposNr m^(-velocity), 0.15f*std::acos(eclposNrm.dot(-velocity))); // GZ: This scal e factor of 0.15 is empirical from photos of Halley and Hale-Bopp. //Mat4d dustTailRot=Mat4d::rotation(eclposNr m^(-velocity), 0.15f*std::acos(eclposNrm.dot(-velocity))); // GZ: This scal e factor of 0.15 is empirical from photos of Halley and Hale-Bopp.
// The curved tail is curved towards positiv e X. We first rotate around the Z axis into a direction opposite of the mot ion vector, then again the antisolar rotation applies. // The curved tail is curved towards positiv e X. We first rotate around the Z axis into a direction opposite of the mot ion vector, then again the antisolar rotation applies.
// In addition, we let the dust tail already start with a light tilt. // In addition, we let the dust tail already start with a light tilt.
dustTailRot=gasTailRot * Mat4d::zrotation(at an2(velocity[1], velocity[0]) + M_PI) * Mat4d::yrotation(5.0f*velocity.leng th()); dustTailRot=gasTailRot * Mat4d::zrotation(at an2(velocity[1], velocity[0]) + M_PI) * Mat4d::yrotation(5.0f*velocity.leng th());
// TODO: If we want to be even faster, rotat e vertex arrays here and not in drawTail()! // Rotate vertex arrays:
Vec3d* gasVertices=(Vec3d*) (gastailVertexAr r.data()); Vec3d* gasVertices=(Vec3d*) (gastailVertexAr r.data());
Vec3d* dustVertices=(Vec3d*) (dusttailVertex Arr.data()); Vec3d* dustVertices=(Vec3d*) (dusttailVertex Arr.data());
for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL _STACKS+1; ++i) for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL _STACKS+1; ++i)
{ {
gasVertices[i].transfo4d(gasTailRot) ; gasVertices[i].transfo4d(gasTailRot) ;
dustVertices[i].transfo4d(dustTailRo t); dustVertices[i].transfo4d(dustTailRo t);
} }
} }
orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere
} }
// Note: we can make deltaJDtail adaptive, depending on dist
ance to sun!
//deltaJDtail=5.0*StelCore::JD_MINUTE * qMax(0.01, qMin(ecli
pticPos.length(), 20.0));
} }
// And also update magnitude and tail brightness/extinction here.
const bool withAtmosphere=(core->getSkyDrawer()->getFlagHasAtmospher
e());
StelToneReproducer* eye = core->getToneReproducer();
float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVM
agnitude(core)+13.0f); // How to calibrate?
// Get the luminance scaled between 0 and 1
float aLum =eye->adaptLuminanceScaled(lum);
// To make comet more apparent in overviews, take field of view into
account:
const float fov=core->getProjection(core->getAltAzModelViewTransform
())->getFov();
if (fov>20)
aLum*= (fov/20.0f);
// Now inhibit tail drawing if still too dim.
if (aLum<0.002f)
{
// Far too dim: don't even show tail...
tailBright=false;
return;
} else
tailBright=true;
// Separate factors, but avoid overly bright tails. I limit to about
0.7 for overlapping both tails which should not exceed full-white.
float gasMagFactor=qMin(0.9f*aLum, 0.7f);
float dustMagFactor=qMin(dustTailBrightnessFactor*aLum, 0.7f);
Vec3f gasColor(0.15f*gasMagFactor,0.35f*gasMagFactor,0.6f*gasMagFact
or); // Orig color 0.15/0.15/0.6
Vec3f dustColor(dustMagFactor, dustMagFactor,0.6f*dustMagFactor);
if (withAtmosphere)
{
Extinction extinction=core->getSkyDrawer()->getExtinction();
// Not only correct the color values for extinction, but for
twilight conditions, also make tail end less visible.
// I consider sky brightness over 1cd/m^2 as reason to short
en tail.
// Below this brightness, the tail brightness loss by this m
ethod is insignificant:
// Just counting through the vertices might make a spiral ap
perance. Maybe even better than stackwise? Let's see...
const float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosp
hereAverageLuminance();
const float brightnessDecreasePerVertexFromHead=1.0f/(COMET_
TAIL_SLICES*COMET_TAIL_STACKS) * avgAtmLum;
float brightnessPerVertexFromHead=1.0f;
gastailColorArr.clear();
dusttailColorArr.clear();
for (int i=0; i<gastailVertexArr.size(); ++i)
{
// Gastail extinction:
Vec3d vertAltAz=core->j2000ToAltAz(gastailVertexArr.
at(i), StelCore::RefractionOn);
vertAltAz.normalize();
Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001
);
float oneMag=0.0f;
extinction.forward(vertAltAz, &oneMag);
float extinctionFactor=std::pow(0.4f, oneMag); // dr
op of one magnitude: factor 2.5 or 40%
gastailColorArr.append(gasColor*extinctionFactor* br
ightnessPerVertexFromHead);
// dusttail extinction:
vertAltAz=core->j2000ToAltAz(dusttailVertexArr.at(i)
, StelCore::RefractionOn);
vertAltAz.normalize();
Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001
);
oneMag=0.0f;
extinction.forward(vertAltAz, &oneMag);
extinctionFactor=std::pow(0.4f, oneMag); // drop of
one magnitude: factor 2.5 or 40%
dusttailColorArr.append(dustColor*extinctionFactor *
brightnessPerVertexFromHead);
brightnessPerVertexFromHead-=brightnessDecreasePerVe
rtexFromHead;
}
}
else // no atmosphere: set all vertices to same brightness.
{
gastailColorArr.fill(gasColor, gastailVertexArr.length());
dusttailColorArr.fill(dustColor, dusttailVertexArr.length())
;
}
//qDebug() << "Comet " << getEnglishName() << "JD: " << date << "ga
sR" << gasColor[0] << " dustR" << dustColor[0];
} }
// Draw the Comet and all the related infos : name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended // Draw the Comet and all the related infos: name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended
void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNam eFont) void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNam eFont)
{ {
if (hidden) if (hidden)
return; return;
if (getEnglishName() == core->getCurrentLocation().planetName) if (getEnglishName() == core->getCurrentLocation().planetName)
{ // GZ: Maybe even don't do that? E.g., draw tail while riding the comet? Decide later. { // Maybe even don't do that? E.g., draw tail while riding the come t? Decide later.
return; return;
} }
// GZ: If comet is too faint to be seen, don't bother rendering. (oo // This test seemed necessary for reasonable fps in case too many co
ps, should have been here in 2014-01... ;-) met elements are loaded.
if ((getVMagnitude(core)-2.0f) > core->getSkyDrawer()->getLimitMagni // Problematic: Early-out here of course disables the wanted hint ci
tude()) rcles for dim comets.
// The line makes hints for comets 5 magnitudes below sky limiting m
agnitude visible.
// If comet is too faint to be seen, don't bother rendering. (Massiv
e speedup if people have hundreds of comet elements!)
if ((getVMagnitude(core)-5.0f) > core->getSkyDrawer()->getLimitMagni
tude())
{ {
return; return;
} }
// The CometOrbit is in fact available in userDataPtr! // The CometOrbit is in fact available in userDataPtr!
CometOrbit* orbit=(CometOrbit*)userDataPtr; CometOrbit* orbit=(CometOrbit*)userDataPtr;
Q_ASSERT(orbit); Q_ASSERT(orbit);
if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all out of useful date range. This allows having hundreds of comet eleme nts. if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all if out of useful date range. This allows having hundreds of comet el ements.
Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
// 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);
// 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();
skipping to change at line 409 skipping to change at line 499
labelsFader=true; labelsFader=true;
} }
else else
{ {
labelsFader=false; labelsFader=false;
} }
drawHints(core, planetNameFont); drawHints(core, planetNameFont);
draw3dModel(core,transfo,screenSz); draw3dModel(core,transfo,screenSz);
} }
// tails should also be drawn if comet core is off-screen...
if (tailActive) // If comet is too faint to be seen, don't bother rendering. (Massiv
e speedup if people have hundreds of comets!)
// This test moved here so that hints are still drawn.
if ((getVMagnitude(core)-3.0f) > core->getSkyDrawer()->getLimitMagni
tude())
{
return;
}
// but tails should also be drawn if comet core is off-screen...
if (tailActive && tailBright)
{ {
drawTail(core,transfo,true); // gas tail drawTail(core,transfo,true); // gas tail
drawTail(core,transfo,false); // dust tail drawTail(core,transfo,false); // dust tail
} }
//Coma: this is just a fan disk tilted towards the observer;-) //Coma: this is just a fan disk tilted towards the observer;-)
drawComa(core, transfo); drawComa(core, transfo);
return; return;
} }
void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP tran sfo, bool gas) void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP tran sfo, bool gas)
{ {
StelPainter* sPainter = new StelPainter(core->getProjection(transfo) ); StelPainter* sPainter = new StelPainter(core->getProjection(transfo) );
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE); glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
// GZ: If we use getVMagnitudeWithExtinction(), a head extincted in
the horizon mist can completely hide an otherwise frighteningly long tail.
// we must use unextincted mag, but mix/dim with atmosphere/sky brig
htness.
// In addition, light falloff is a bit reduced for better visibility
. Power basis should be 0.4, we use 0.6.
float magFactor=std::pow(0.6f , getVMagnitude(core));
if (core->getSkyDrawer()->getFlagHasAtmosphere())
{
// Mix with sky brightness and light pollution: This is very
ad-hoc, if someone finds a better solution, please go ahead!
// Light pollution:
float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->g
etBortleScaleIndex());
magFactor*= bortleIndexFactor*bortleIndexFactor; // GZ-Guess
timate for light pollution influence
// sky brightness: This is about 10 for twilight where brigh
t comet tails should already be visible. Dark night is close to 0.
float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAv
erageLuminance();
float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFacto
r<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor);
magFactor*=atmLumFactor*atmLumFactor;
}
magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical
adjustment for texture brightness.
magFactor=qMin(magFactor, 1.05f); // Limit excessively bright displa
y.
tailTexture->bind(); tailTexture->bind();
if (gas) { if (gas) {
sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magF sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (V
actor); ec2f*)tailTexCoordArr.constData(), (Vec3f*)gastailColorArr.constData());
sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (V
ec2f*)tailTexCoordArr.constData());
sPainter->drawFromArray(StelPainter::Triangles, tailIndices. size(), 0, true, tailIndices.constData()); sPainter->drawFromArray(StelPainter::Triangles, tailIndices. size(), 0, true, tailIndices.constData());
} else { } else {
sPainter->setColor(magFactor, magFactor,0.6f*magFactor); sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (
sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), ( Vec2f*)tailTexCoordArr.constData(), (Vec3f*)dusttailColorArr.constData());
Vec2f*)tailTexCoordArr.constData());
sPainter->drawFromArray(StelPainter::Triangles, tailIndices. size(), 0, true, tailIndices.constData()); sPainter->drawFromArray(StelPainter::Triangles, tailIndices. size(), 0, true, tailIndices.constData());
} }
glDisable(GL_BLEND); glDisable(GL_BLEND);
if (sPainter) if (sPainter)
delete sPainter; delete sPainter;
sPainter=NULL; sPainter=NULL;
} }
void Comet::drawComa(StelCore* core, StelProjector::ModelViewTranformP tran sfo) void Comet::drawComa(StelCore* core, StelProjector::ModelViewTranformP tran sfo)
skipping to change at line 477 skipping to change at line 555
Vec3d eclposNrm=eclipticPos - core->getObserverHeliocentricEclipticP os() ; eclposNrm.normalize(); Vec3d eclposNrm=eclipticPos - core->getObserverHeliocentricEclipticP os() ; eclposNrm.normalize();
Mat4d comarot=Mat4d::rotation(Vec3d(0.0, 0.0, 1.0)^(eclposNrm), std: :acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) ); Mat4d comarot=Mat4d::rotation(Vec3d(0.0, 0.0, 1.0)^(eclposNrm), std: :acos(Vec3d(0.0, 0.0, 1.0).dot(eclposNrm)) );
StelProjector::ModelViewTranformP transfo2 = transfo->clone(); StelProjector::ModelViewTranformP transfo2 = transfo->clone();
transfo2->combine(comarot); transfo2->combine(comarot);
StelPainter* sPainter = new StelPainter(core->getProjection(transfo2 )); StelPainter* sPainter = new StelPainter(core->getProjection(transfo2 ));
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE); glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
// GZ: For the coma, we can use extinction via atmosphere. StelToneReproducer* eye = core->getToneReproducer();
// In addition, light falloff is a bit reduced for better visibility float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVM
. Power basis should be 0.4, we use 0.6. agnitudeWithExtinction(core)+11.0f); // How to calibrate?
float minSkyMag=core->getSkyDrawer()->getLimitMagnitude(); // Get the luminance scaled between 0 and 1
float mag100pct=minSkyMag-6.0f; // should be 5, but let us draw it a float aLum =eye->adaptLuminanceScaled(lum);
bit brighter. float magFactor=qMin(qMax(aLum, 0.25f), 2.0f);
float magDrop=getVMagnitudeWithExtinction(core)-mag100pct;
float magFactor=std::pow(0.6f , magDrop);
magFactor=qMin(magFactor, 2.0f); // Limit excessively bright display
.
comaTexture->bind(); comaTexture->bind();
sPainter->setColor(magFactor,magFactor,0.6f*magFactor); sPainter->setColor(0.3f*magFactor,0.7*magFactor,magFactor);
sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaT exCoordArr.constData()); sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaT exCoordArr.constData());
sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size() /3); sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size() /3);
glDisable(GL_BLEND); glDisable(GL_BLEND);
if (sPainter) if (sPainter)
delete sPainter; delete sPainter;
sPainter=NULL; sPainter=NULL;
} }
skipping to change at line 520 skipping to change at line 595
void Comet::computeComa(const float diameter) void Comet::computeComa(const float diameter)
{ {
StelPainter::computeFanDisk(0.5f*diameter, 3, 3, comaVertexArr, coma TexCoordArr); StelPainter::computeFanDisk(0.5f*diameter, 3, 3, comaVertexArr, coma TexCoordArr);
} }
//! create parabola shell to represent a tail. Designed for slices=16, stac ks=16, but should work with other sizes as well. //! create parabola shell to represent a tail. Designed for slices=16, stac ks=16, but should work with other sizes as well.
//! (Maybe slices must be an even number.) //! (Maybe slices must be an even number.)
// Parabola equation: z=x²/2p. // Parabola equation: z=x²/2p.
// xOffset for the dust tail, this may introduce a bend. Units are x per sq rt(z). // xOffset for the dust tail, this may introduce a bend. Units are x per sq rt(z).
void Comet::computeParabola(const float parameter, const float radius, cons t float zshift, void Comet::computeParabola(const float parameter, const float radius, cons t float zshift,
QVector<double>& vertexArr, QVector<float>& texC oordArr, QVector<unsigned short> &indices, const float xOffset) { QVector<Vec3d>& vertexArr, QVector<float>& texCo ordArr, QVector<unsigned short> &indices, const float xOffset) {
// GZ: keep the array and replace contents. However, using replace() // keep the array and replace contents. However, using replace() is
is only slightly faster. only slightly faster.
if (vertexArr.length() < (3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)) if (vertexArr.length() < ((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)))
) vertexArr.resize((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
vertexArr.resize(3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
if (createTailIndices) indices.clear(); if (createTailIndices) indices.clear();
if (createTailTextureCoords) texCoordArr.clear(); if (createTailTextureCoords) texCoordArr.clear();
int i; int i;
// The parabola has triangular faces with vertices on two circles th at are rotated against each other. // The parabola has triangular faces with vertices on two circles th at are rotated against each other.
float xa[2*COMET_TAIL_SLICES]; float xa[2*COMET_TAIL_SLICES];
float ya[2*COMET_TAIL_SLICES]; float ya[2*COMET_TAIL_SLICES];
float x, y, z; float x, y, z;
// fill xa, ya with sin/cosines. TBD: make more efficient with index mirroring etc. // fill xa, ya with sin/cosines. TBD: make more efficient with index mirroring etc.
float da=M_PI/COMET_TAIL_SLICES; // full circle/2slices float da=M_PI/COMET_TAIL_SLICES; // full circle/2slices
for (i=0; i<2*COMET_TAIL_SLICES; ++i){ for (i=0; i<2*COMET_TAIL_SLICES; ++i){
xa[i]=-sin(i*da); xa[i]=-sin(i*da);
ya[i]=cos(i*da); ya[i]=cos(i*da);
} }
vertexArr.replace(0, 0.0); vertexArr.replace(1, 0.0); vertexArr.repl vertexArr.replace(0, Vec3d(0.0, 0.0, zshift));
ace(2, zshift); int vertexArrIndex=1;
int vertexArrIndex=3;
if (createTailTextureCoords) texCoordArr << 0.5f << 0.5f; if (createTailTextureCoords) texCoordArr << 0.5f << 0.5f;
// define the indices lying on circles, starting at 1: odd rings hav e 1/slices+1/2slices, even-numbered rings straight 1/slices // define the indices lying on circles, starting at 1: odd rings hav e 1/slices+1/2slices, even-numbered rings straight 1/slices
// inner ring#1 // inner ring#1
int ring; int ring;
for (ring=1; ring<=COMET_TAIL_STACKS; ++ring){ for (ring=1; ring<=COMET_TAIL_STACKS; ++ring){
z=ring*radius/COMET_TAIL_STACKS; z=z*z/(2*parameter) + zshif t; z=ring*radius/COMET_TAIL_STACKS; z=z*z/(2*parameter) + zshif t;
float xShift= xOffset*z*z; float xShift= xOffset*z*z;
for (i=ring & 1; i<2*COMET_TAIL_SLICES; i+=2) { // i.e., rin g1 has shifted vertices, ring2 has even ones. for (i=ring & 1; i<2*COMET_TAIL_SLICES; i+=2) { // i.e., rin g1 has shifted vertices, ring2 has even ones.
x=xa[i]*radius*ring/COMET_TAIL_STACKS; x=xa[i]*radius*ring/COMET_TAIL_STACKS;
y=ya[i]*radius*ring/COMET_TAIL_STACKS; y=ya[i]*radius*ring/COMET_TAIL_STACKS;
vertexArr.replace(vertexArrIndex++, x+xShift); vertexArr.replace(vertexArrIndex++, Vec3d(x+xShift,
vertexArr.replace(vertexArrIndex++, y); y, z));
vertexArr.replace(vertexArrIndex++, z);
if (createTailTextureCoords) texCoordArr << 0.5+ 0.5 *x/radius << 0.5+0.5*y/radius; if (createTailTextureCoords) texCoordArr << 0.5+ 0.5 *x/radius << 0.5+0.5*y/radius;
} }
} }
// now link the faces with indices. // now link the faces with indices.
if (createTailIndices) if (createTailIndices)
{ {
for (i=1; i<COMET_TAIL_SLICES; ++i) indices << 0 << i << i+1 ; for (i=1; i<COMET_TAIL_SLICES; ++i) indices << 0 << i << i+1 ;
indices << 0 << COMET_TAIL_SLICES << 1; // close inner fan. indices << 0 << COMET_TAIL_SLICES << 1; // close inner fan.
// The other slices are a repeating pattern of 2 possibiliti es. Index @ring always is on the inner ring (slices-agon) // The other slices are a repeating pattern of 2 possibiliti es. Index @ring always is on the inner ring (slices-agon)
for (ring=1; ring<COMET_TAIL_STACKS; ring+=2) { // odd rings for (ring=1; ring<COMET_TAIL_STACKS; ring+=2) { // odd rings
skipping to change at line 595 skipping to change at line 668
} }
createTailIndices=false; createTailIndices=false;
createTailTextureCoords=false; createTailTextureCoords=false;
} }
// These are to avoid having index arrays for each comet when all are equal . // These are to avoid having index arrays for each comet when all are equal .
bool Comet::createTailIndices=true; bool Comet::createTailIndices=true;
bool Comet::createTailTextureCoords=true; bool Comet::createTailTextureCoords=true;
StelTextureSP Comet::comaTexture; StelTextureSP Comet::comaTexture;
StelTextureSP Comet::tailTexture; StelTextureSP Comet::tailTexture;
QVector<float> Comet::tailTexCoordArr; // computed only once FOR ALL COMETS QVector<float> Comet::tailTexCoordArr; // computed only once for all Comets
! .
QVector<unsigned short> Comet::tailIndices; // computed only once FOR ALL C QVector<unsigned short> Comet::tailIndices; // computed only once for all C
OMETS! omets.
 End of changes. 33 change blocks. 
94 lines changed or deleted 179 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/