Comet.cpp   Comet.cpp 
skipping to change at line 55 skipping to change at line 55
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,
const QString& pType, const QString& pTypeStr,
float dustTailWidthFact, float dustTailLengthFact, float du stTailBrightnessFact) float dustTailWidthFact, float dustTailLengthFact, float du stTailBrightnessFact)
: Planet (englishName, : Planet (englishName,
flagLighting, flagLighting,
radius, radius,
oblateness, oblateness,
color, color,
albedo, albedo,
atexMapName, atexMapName,
"", "",
coordFunc, coordFunc,
auserDataPtr, auserDataPtr,
osculatingFunc, osculatingFunc,
acloseOrbit, acloseOrbit,
hidden, hidden,
false, //No atmosphere false, //No atmosphere
true, //halo true, //halo
pType), pTypeStr),
tailActive(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
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();
gastailTexCoordArr.clear();
//dusttailTexCoordArr.clear();
gastailIndices.clear();
//dusttailIndices.clear();
comaVertexArr.clear(); comaVertexArr.clear();
comaTexCoordArr.clear();
comaTexture = StelApp::getInstance().getTextureManager().createTextu
reThread(StelFileMgr::getInstallationDir()+"/textures/cometComa.png", StelT
exture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
//GZ: tail textures. We use a paraboloid tail body, textured like a
fisheye sphere, i.e. center=head. The texture should be something like a mo
ttled star to give some structure.
gasTailTexture = StelApp::getInstance().getTextureManager().createTe
xtureThread(StelFileMgr::getInstallationDir()+"/textures/cometTail.png", St
elTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
// GZ: I think we need only one texture for the tails.
//dusttailTexture = StelApp::getInstance().getTextureManager().creat
eTextureThread(StelFileMgr::getInstallationDir()+"/textures/cometTail.png",
StelTexture::StelTextureParams(true, GL_LINEAR, GL_CLAMP_TO_EDGE));
//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 154 skipping to change at line 146
oss << q_(englishName); // UI translation can differ from s ky translation oss << q_(englishName); // UI translation can differ from s ky 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)
{ {
if (pType.length()>0) oss << q_("Type: <b>%1</b>").arg(q_(getPlanetTypeString()))
oss << q_("Type: <b>%1</b>").arg(q_(pType)) << "<br << "<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
oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(core), 0 , 'f', 2) << "<br>"; oss << q_("Magnitude: <b>%1</b>").arg(getVMagnitude(core), 0 , 'f', 2) << "<br>";
} }
skipping to change at line 215 skipping to change at line 206
.arg(distanceKm, 0, 'f', 3); .arg(distanceKm, 0, 'f', 3);
} }
else else
{ {
// xgettext:no-c-format // xgettext:no-c-format
oss << QString(q_("Distance: %1AU (%2 Mio km)")) oss << QString(q_("Distance: %1AU (%2 Mio km)"))
.arg(distanceAu, 0, 'f', 3) .arg(distanceAu, 0, 'f', 3)
.arg(distanceKm / 1.0e6, 0, 'f', 3); .arg(distanceKm / 1.0e6, 0, 'f', 3);
} }
oss << "<br>"; oss << "<br>";
// GZ: Add speed. I don't know where to place that bit of in }
formation. if (flags&Extra)
{
// GZ: Add speed. I don't know where else to place that bit
of information.
// xgettext:no-c-format // xgettext:no-c-format
oss << QString(q_("Speed: %1 km/s")) oss << QString(q_("Speed: %1 km/s"))
.arg(((CometOrbit*)userDataPtr)->getVelocity().le ngth()*AU/86400.0, 0, 'f', 3); .arg(((CometOrbit*)userDataPtr)->getVelocity().le ngth()*AU/86400.0, 0, 'f', 3);
oss << "<br>"; oss << "<br>";
} }
/*
if (flags&Size) if (flags&Size)
oss << q_("Apparent diameter: %1").arg(StelUtils::radToDmsSt {
r(2.*getAngularSize(core)*M_PI/180., true)); // GZ: Add estimates for coma diameter and tail length.
*/ // xgettext:no-c-format
oss << QString(q_("Coma diameter (estimate): %1 km"))
.arg(floor(tailFactors[0]*AU/1000.0f)*1000.0f, 0,
'f', 0);
oss << "<br>";
// xgettext:no-c-format
oss << QString(q_("Gas tail length (estimate): %1 Mio km"))
.arg(tailFactors[1]*AU*1e-6, 0, 'G', 3);
oss << "<br>";
}
// If semi-major axis not zero then calculate and display orbital pe riod for comet in days // If semi-major axis not zero then calculate and display orbital pe riod for comet in days
double siderealPeriod = getSiderealPeriod(); double siderealPeriod = getSiderealPeriod();
if ((flags&Extra) && (siderealPeriod>0)) if ((flags&Extra) && (siderealPeriod>0))
{ {
// TRANSLATORS: Sidereal (orbital) period for solar system b odies in days and in Julian years (symbol: a) // 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>"; oss << q_("Sidereal period: %1 days (%2 a)").arg(QString::nu mber(siderealPeriod, 'f', 2)).arg(QString::number(siderealPeriod/365.25, 'f ', 3)) << "<br>";
} }
postProcessInfoString(str, flags); postProcessInfoString(str, flags);
skipping to change at line 282 skipping to change at line 284
//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
// Actually call the provided function to compute the ecliptical position,
and buildup the tails!
void Comet::computePosition(const double date)
{
Planet::computePosition(date);
//GZ: I think we can make deltaJD adaptive, depending on distance to
sun! For some reason though, this leads to a crash!
//deltaJD=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(),
20.0));
if (fabs(lastJDtail-date)>deltaJDtail)
{
lastJDtail=date;
// GZ: Moved from draw() :-)
// The CometOrbit is in fact available in userDataPtr!
CometOrbit* orbit=(CometOrbit*)userDataPtr;
Q_ASSERT(orbit);
if (!orbit->objectDateValid(date)) return; // out of useful
date range. This should allow having hundreds of comet elements.
if (orbit->getUpdateTails()){
// 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();
// 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]);
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)
{
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
// 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]);
// Find valid parameters to create paraboloi
d vertex arrays: dustTail, gasTail.
computeParabola(gasparameter, gasTailEndRadi
us, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices);
// This was for a rotated straight parabola:
//computeParabola(dustparameter, 2.0f*tailFa
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.
computeParabola(dustparameter, dustTailWidth
Factor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoo
rdArr, tailIndices, 25.0f*orbit->getVelocity().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...)
// Find rotation matrix from 0/0/1 to eclipt
icPosition: crossproduct for axis (normal vector), dotproduct for angle.
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)) );
Vec3d velocity=orbit->getVelocity(); // [AU/
d]
// 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.
// 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.
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()!
Vec3d* gasVertices=(Vec3d*) (gastailVertexAr
r.data());
Vec3d* dustVertices=(Vec3d*) (dusttailVertex
Arr.data());
for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL
_STACKS+1; ++i)
{
gasVertices[i].transfo4d(gasTailRot)
;
dustVertices[i].transfo4d(dustTailRo
t);
}
}
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));
}
}
// 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 moved this up. Maybe even don't do that? E.g., draw tail whi le riding the comet? Decide later. { // GZ: Maybe even don't do that? E.g., draw tail while riding the comet? Decide later.
return; return;
} }
// GZ: If comet is too faint to be seen, don't bother rendering. (oo
ps, should have been here in 2014-01... ;-)
if ((getVMagnitude(core)-2.0f) > core->getSkyDrawer()->getLimitMagni
tude())
{
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; // out of usef if (!orbit->objectDateValid(core->getJDay())) return; // don't draw
ul date range. This allows having hundreds of comet elements. at all out of useful date range. This allows having hundreds of comet eleme
nts.
if (orbit->getUpdateTails()){
// Compute lengths and orientations from orbit object, but o
nly if required.
// TODO: This part should possibly be moved to another threa
d to keep draw() free from too much computation.
Vec2f tailFactors=getComaDiameterAndTailLengthAU();
float gasTailEndRadius=qMax(tailFactors[0], 0.025f*tailFacto
rs[1]) ; // This avoids too slim gas tails for bright comets like Hale-Bopp
.
float gasparameter=gasTailEndRadius*gasTailEndRadius/(2.0f*t
ailFactors[1]); // parabola formula: z=r²/2p, so p=r²/2z
// The dust tail is thicker and usually shorter. The factors
can be configured in the elements.
float dustparameter=gasTailEndRadius*gasTailEndRadius*dustTa
ilWidthFactor*dustTailWidthFactor/(2.0f*dustTailLengthFactor*tailFactors[1]
);
// Find valid parameters to create paraboloid vertex arrays:
dustTail, gasTail.
computeParabola(gasparameter, gasTailEndRadius, -0.5f*gaspar
ameter, gastailVertexArr, gastailTexCoordArr, gastailIndices);
// This was for a rotated straight parabola:
//computeParabola(dustparameter, 2.0f*tailFactors[0], -0.5f*
dustparameter, dusttailVertexArr, dusttailTexCoordArr, dusttailIndices);
// Now we make a skewed parabola. Skew factor 15 (last arg)
ad-hoc/empirical. TBD later: Find physically correct solution.
computeParabola(dustparameter, dustTailWidthFactor*gasTailEn
dRadius, -0.5f*dustparameter, dusttailVertexArr, gastailTexCoordArr, gastai
lIndices, 25.0f*orbit->getVelocity().length());
// 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 look bette
r.
computeComa(1.0f*tailFactors[0]);
orbit->setUpdateTails(false); // don't update until position
has been recalculated elsewhere
}
Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
/* // We can remove that - a Comet has no parent except for the sun...
PlanetP p = parent;
while (p && p->parent)
{
mat = Mat4d::translation(p->eclipticPos) * mat * p->rotLocal
ToParent;
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);
// 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)
skipping to change at line 361 skipping to change at line 409
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 core is off-screen... // tails should also be drawn if comet core is off-screen...
drawTail(core,transfo,true); // gas tail if (tailActive)
drawTail(core,transfo,false); // dust tail {
drawTail(core,transfo,true); // gas 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)
{ {
// Find rotation matrix from 0/0/1 to eclipticPosition: crossproduct StelPainter* sPainter = new StelPainter(core->getProjection(transfo)
for axis (normal vector), dotproduct for angle. );
Vec3d eclposNrm=eclipticPos; eclposNrm.normalize();
Mat4d tailrot=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();
transfo2->combine(tailrot);
if (!gas) {
CometOrbit* orbit=(CometOrbit*)userDataPtr;
Vec3d velocity=orbit->getVelocity(); // [AU/d]
// This was a try to rotate a straight parabola somewhat awa
y from the antisolar direction.
//Mat4d dustTailRot=Mat4d::rotation(eclposNrm^(-velocity), 0
.15f*std::acos(eclposNrm.dot(-velocity))); // GZ: This scale factor of 0.15
is empirical from photos of Halley and Hale-Bopp.
// The curved tail is curved towards positive X. We first ro
tate around the Z axis into a direction opposite of the motion vector, then
again the antisolar rotation applies.
Mat4d dustTailRot=Mat4d::zrotation(atan2(velocity[1], veloci
ty[0]) + M_PI);
transfo2->combine(dustTailRot);
// In addition, we let the dust tail already start with a li
ght tilt.
Mat4d dustTailYrot=Mat4d::yrotation(5.0f*velocity.length());
// again, this is pretty ad-hoc, feel free to improve!
transfo2->combine(dustTailYrot);
}
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: If we use getVMagnitudeWithExtinction(), a head extincted in the horizon mist can completely hide an otherwise frighteningly long tail. // 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. // 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. // 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.4f , getVMagnitudeWithExtinction(core)) ;
float magFactor=std::pow(0.6f , getVMagnitude(core)); float magFactor=std::pow(0.6f , getVMagnitude(core));
if (core->getSkyDrawer()->getFlagHasAtmosphere()) 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! // Mix with sky brightness and light pollution: This is very ad-hoc, if someone finds a better solution, please go ahead!
// Light pollution: // Light pollution:
float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->g etBortleScaleIndex()); float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->g etBortleScaleIndex());
magFactor*= bortleIndexFactor*bortleIndexFactor; // GZ-Guess timate for light pollution influence 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. // 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 avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAv erageLuminance();
float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFacto r<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor); float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFacto r<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor);
magFactor*=atmLumFactor*atmLumFactor; magFactor*=atmLumFactor*atmLumFactor;
} }
magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical adjustment for texture brightness. magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical adjustment for texture brightness.
magFactor=qMin(magFactor, 1.05f); // Limit excessively bright displa y. magFactor=qMin(magFactor, 1.05f); // Limit excessively bright displa y.
gasTailTexture->bind(); tailTexture->bind();
if (gas) { if (gas) {
//gasTailTexture->bind();
sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magF actor); sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magF actor);
sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (V sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (V
ec2f*)gastailTexCoordArr.constData()); ec2f*)tailTexCoordArr.constData());
sPainter->drawFromArray(StelPainter::Triangles, gastailIndic sPainter->drawFromArray(StelPainter::Triangles, tailIndices.
es.size(), 0, true, gastailIndices.constData()); size(), 0, true, tailIndices.constData());
} else { } else {
//dustTailTexture->bind();
sPainter->setColor(magFactor, magFactor,0.6f*magFactor); sPainter->setColor(magFactor, magFactor,0.6f*magFactor);
//sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (
(Vec2f*)dusttailTexCoordArr.constData()); Vec2f*)tailTexCoordArr.constData());
//sPainter->drawFromArray(StelPainter::Triangles, dusttailIn sPainter->drawFromArray(StelPainter::Triangles, tailIndices.
dices.size(), 0, true, dusttailIndices.constData()); size(), 0, true, tailIndices.constData());
sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (
Vec2f*)gastailTexCoordArr.constData());
sPainter->drawFromArray(StelPainter::Triangles, gastailIndic
es.size(), 0, true, gastailIndices.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 471 skipping to change at line 498
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;
} }
// Formula found at http://www.projectpluto.com/update7b.htm#comet_tail_for mula // Formula found at http://www.projectpluto.com/update7b.htm#comet_tail_for mula
Vec2f Comet::getComaDiameterAndTailLengthAU() const Vec2f Comet::getComaDiameterAndTailLengthAU()
{ {
float r = getHeliocentricEclipticPos().length(); float r = getHeliocentricEclipticPos().length();
float mhelio = absoluteMagnitude + slopeParameter * log10(r); float mhelio = absoluteMagnitude + slopeParameter * log10(r);
float Do = pow(10.0f, ((-0.0033f*mhelio - 0.07f) * mhelio + 3.25f)); float Do = pow(10.0f, ((-0.0033f*mhelio - 0.07f) * mhelio + 3.25f));
float common = 1.0f - pow(10.0f, (-2.0f*r)); float common = 1.0f - pow(10.0f, (-2.0f*r));
float D = Do * common * (1.0f - pow(10.0f, -r)) * (1000.0f*AU_KM); float D = Do * common * (1.0f - pow(10.0f, -r)) * (1000.0f*AU_KM);
float Lo = pow(10.0f, ((-0.0075f*mhelio - 0.19f) * mhelio + 2.1f)); float Lo = pow(10.0f, ((-0.0075f*mhelio - 0.19f) * mhelio + 2.1f));
float L = Lo*(1.0f-pow(10.0f, -4.0f*r)) * common * (1e6*AU_KM); float L = Lo*(1.0f-pow(10.0f, -4.0f*r)) * common * (1e6*AU_KM);
return Vec2f(D, L); return Vec2f(D, L);
} }
skipping to change at line 494 skipping to change at line 521
{ {
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<double>& vertexArr, QVector<float>& texC oordArr, QVector<unsigned short> &indices, const float xOffset) {
vertexArr.clear();
//texCoordArr.clear(); // GZ: keep the array and replace contents. However, using replace()
//indices.clear(); is only slightly faster.
bool createIndices= indices.empty(); if (vertexArr.length() < (3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1))
bool createTexcoords= texCoordArr.empty(); )
vertexArr.resize(3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
if (createTailIndices) indices.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);
} }
// center point, vertex0 vertexArr.replace(0, 0.0); vertexArr.replace(1, 0.0); vertexArr.repl
vertexArr << 0.0f << 0.0f << zshift; ace(2, zshift);
if (createTexcoords) texCoordArr << 0.5f << 0.5f; int vertexArrIndex=3;
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 << x+xShift << y << z; vertexArr.replace(vertexArrIndex++, x+xShift);
if (createTexcoords) texCoordArr << 0.5+ 0.5*x/radiu vertexArr.replace(vertexArrIndex++, y);
s << 0.5+0.5*y/radius; vertexArr.replace(vertexArrIndex++, z);
if (createTailTextureCoords) texCoordArr << 0.5+ 0.5
*x/radius << 0.5+0.5*y/radius;
} }
} }
// now link the faces with indices. That's fun... ;-) // now link the faces with indices.
if (createIndices) 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
const int first=(ring-1)*COMET_TAIL_SLICES+1; const int first=(ring-1)*COMET_TAIL_SLICES+1;
for (i=0; i<COMET_TAIL_SLICES-1; ++i){ for (i=0; i<COMET_TAIL_SLICES-1; ++i){
indices << first+i << first+COMET_TAIL_SLICE S+i << first+COMET_TAIL_SLICES+1+i; indices << first+i << first+COMET_TAIL_SLICE S+i << first+COMET_TAIL_SLICES+1+i;
indices << first+i << first+COMET_TAIL_SLICE S+1+i << first+1+i; indices << first+i << first+COMET_TAIL_SLICE S+1+i << first+1+i;
} }
skipping to change at line 556 skipping to change at line 586
const int first=(ring-1)*COMET_TAIL_SLICES+1; const int first=(ring-1)*COMET_TAIL_SLICES+1;
for (i=0; i<COMET_TAIL_SLICES-1; ++i){ for (i=0; i<COMET_TAIL_SLICES-1; ++i){
indices << first+i << first+COMET_TAIL_SLICE S+i << first+1+i; indices << first+i << first+COMET_TAIL_SLICE S+i << first+1+i;
indices << first+1+i << first+COMET_TAIL_SLI CES+i << first+COMET_TAIL_SLICES+1+i; indices << first+1+i << first+COMET_TAIL_SLI CES+i << first+COMET_TAIL_SLICES+1+i;
} }
// closing slice: mesh with other indices... // closing slice: mesh with other indices...
indices << ring*COMET_TAIL_SLICES << (ring+1)*COMET_ TAIL_SLICES << first; indices << ring*COMET_TAIL_SLICES << (ring+1)*COMET_ TAIL_SLICES << first;
indices << first << (ring+1)*COMET_TAIL_SLICES << ri ng*COMET_TAIL_SLICES+1; indices << first << (ring+1)*COMET_TAIL_SLICES << ri ng*COMET_TAIL_SLICES+1;
} }
} }
// qDebug() << "Parabola: Vertex index dump\n"; createTailIndices=false;
// for (int i=0; i<indices.length(); i+=3) createTailTextureCoords=false;
// qDebug() << indices[i] << "-" << indices[i+1] << "-" << indi
ces[i+2] << ":"
// << vertexArr[3*indices[i]] << vertexArr[3
*indices[i]+1] << vertexArr[3*indices[i]+2] << "/"
// << vertexArr[3*indices[i+1]] << vertexArr[3
*indices[i+1]+1] << vertexArr[3*indices[i+1]+2] << "/"
// << vertexArr[3*indices[i+2]] << vertexArr[3
*indices[i+2]+1] << vertexArr[3*indices[i+2]+2];
} }
// These are to avoid having index arrays for each comet when all are equal
.
bool Comet::createTailIndices=true;
bool Comet::createTailTextureCoords=true;
StelTextureSP Comet::comaTexture;
StelTextureSP Comet::tailTexture;
QVector<float> Comet::tailTexCoordArr; // computed only once FOR ALL COMETS
!
QVector<unsigned short> Comet::tailIndices; // computed only once FOR ALL C
OMETS!
 End of changes. 29 change blocks. 
156 lines changed or deleted 193 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/