Merge lp:~georg-zotti/stellarium/gz_comet-tail-extinction into lp:stellarium

Proposed by gzotti
Status: Merged
Merged at revision: 7129
Proposed branch: lp:~georg-zotti/stellarium/gz_comet-tail-extinction
Merge into: lp:stellarium
Diff against target: 611 lines (+161/-94)
11 files modified
src/core/StelApp.hpp (+2/-1)
src/core/StelPainter.cpp (+2/-1)
src/core/StelProjector.cpp (+1/-1)
src/core/StelProjector.hpp (+2/-2)
src/core/StelToneReproducer.hpp (+5/-5)
src/core/modules/Comet.cpp (+125/-68)
src/core/modules/Comet.hpp (+14/-6)
src/core/modules/MilkyWay.cpp (+1/-1)
src/core/modules/MinorPlanet.cpp (+0/-1)
src/core/modules/Planet.cpp (+5/-5)
src/core/modules/Planet.hpp (+4/-3)
To merge this branch: bzr merge lp:~georg-zotti/stellarium/gz_comet-tail-extinction
Reviewer Review Type Date Requested Status
Fabien Chéreau Approve
Review via email: mp+241181@code.launchpad.net

Commit message

Improved brightness control and colors for comet tails: extinction and twilight mixing.

Description of the change

My original comet tails of winter 2013/14 had one big flaw: brightness was computed globally. This made them almost pop out of twilight in full length, and bright comets were just too bright.

This branch has I think much better brightness balancing (query atmosphere and eye adaptation), and can reduce/influence tail brightness not only by vertex-wise extinction, but also by vertex-wise adaptation of tail length visibility to overall sky brightness. The increase in quality can at least be called "significant" IMHO.

To test, I recommend you copy ssystem_1000comets.ini to your ssystem.ini and have a look at e.g. comets Hale-Bopp (best in March/April 1997), Hyakutake (March 1996), PanSTARRS (March 2013), Halley (1986, 1910, 837), Bennett (1970), 1680, 1882, Donati (1858).

To post a comment you must log in.
Revision history for this message
Fabien Chéreau (xalioth) wrote :

Looks good to me :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/core/StelApp.hpp'
--- src/core/StelApp.hpp 2014-11-04 10:59:12 +0000
+++ src/core/StelApp.hpp 2014-11-08 17:16:48 +0000
@@ -148,7 +148,8 @@
148 void update(double deltaTime);148 void update(double deltaTime);
149149
150 //! Draw all registered StelModule in the order defined by the order lists.150 //! Draw all registered StelModule in the order defined by the order lists.
151 //! @return the max squared distance in pixels that any object has travelled since the last update.151 // 2014-11: OLD COMMENT? What does a void return?
152 // @return the max squared distance in pixels that any object has travelled since the last update.
152 void draw();153 void draw();
153154
154 //! Call this when the size of the GL window has changed.155 //! Call this when the size of the GL window has changed.
155156
=== modified file 'src/core/StelPainter.cpp'
--- src/core/StelPainter.cpp 2014-11-04 12:15:15 +0000
+++ src/core/StelPainter.cpp 2014-11-08 17:16:48 +0000
@@ -544,7 +544,7 @@
544544
545 // Translate/rotate545 // Translate/rotate
546 if (!noGravity)546 if (!noGravity)
547 angleDeg += prj->defautAngleForGravityText;547 angleDeg += prj->defaultAngleForGravityText;
548548
549 if (std::fabs(angleDeg)>1.f)549 if (std::fabs(angleDeg)>1.f)
550 {550 {
@@ -1357,6 +1357,7 @@
1357 break;1357 break;
1358 case SphericalPolygonDrawModeFill:1358 case SphericalPolygonDrawModeFill:
1359 case SphericalPolygonDrawModeTextureFill:1359 case SphericalPolygonDrawModeTextureFill:
1360 case SphericalPolygonDrawModeTextureFillColormodulated:
1360 glEnable(GL_CULL_FACE);1361 glEnable(GL_CULL_FACE);
1361 // The polygon is already tesselated as triangles1362 // The polygon is already tesselated as triangles
1362 if (doSubDivise || prj->intersectViewportDiscontinuity(poly->getBoundingCap()))1363 if (doSubDivise || prj->intersectViewportDiscontinuity(poly->getBoundingCap()))
13631364
=== modified file 'src/core/StelProjector.cpp'
--- src/core/StelProjector.cpp 2013-10-01 22:05:10 +0000
+++ src/core/StelProjector.cpp 2014-11-08 17:16:48 +0000
@@ -116,7 +116,7 @@
116 viewportCenter = params.viewportCenter;116 viewportCenter = params.viewportCenter;
117 viewportCenter *= devicePixelsPerPixel;117 viewportCenter *= devicePixelsPerPixel;
118 gravityLabels = params.gravityLabels;118 gravityLabels = params.gravityLabels;
119 defautAngleForGravityText = params.defautAngleForGravityText;119 defaultAngleForGravityText = params.defautAngleForGravityText;
120 flipHorz = params.flipHorz ? -1.f : 1.f;120 flipHorz = params.flipHorz ? -1.f : 1.f;
121 flipVert = params.flipVert ? -1.f : 1.f;121 flipVert = params.flipVert ? -1.f : 1.f;
122 viewportFovDiameter = params.viewportFovDiameter * devicePixelsPerPixel;122 viewportFovDiameter = params.viewportFovDiameter * devicePixelsPerPixel;
123123
=== modified file 'src/core/StelProjector.hpp'
--- src/core/StelProjector.hpp 2014-10-16 17:32:50 +0000
+++ src/core/StelProjector.hpp 2014-11-08 17:16:48 +0000
@@ -291,7 +291,7 @@
291 oneOverZNearMinusZFar(0.f),291 oneOverZNearMinusZFar(0.f),
292 viewportFovDiameter(0.f),292 viewportFovDiameter(0.f),
293 gravityLabels(true),293 gravityLabels(true),
294 defautAngleForGravityText(0.f),294 defaultAngleForGravityText(0.f),
295 devicePixelsPerPixel(1.f) {;}295 devicePixelsPerPixel(1.f) {;}
296296
297 //! Return whether the projection presents discontinuities. Used for optimization.297 //! Return whether the projection presents discontinuities. Used for optimization.
@@ -317,7 +317,7 @@
317 Vec2f viewportCenter; // Viewport center in screen pixel317 Vec2f viewportCenter; // Viewport center in screen pixel
318 float viewportFovDiameter; // diameter of the FOV disk in pixel318 float viewportFovDiameter; // diameter of the FOV disk in pixel
319 bool gravityLabels; // should label text align with the horizon?319 bool gravityLabels; // should label text align with the horizon?
320 float defautAngleForGravityText; // a rotation angle to apply to gravity text (only if gravityLabels is set to false)320 float defaultAngleForGravityText; // a rotation angle to apply to gravity text (only if gravityLabels is set to false)
321 SphericalCap boundingCap; // Bounding cap of the whole viewport321 SphericalCap boundingCap; // Bounding cap of the whole viewport
322 float devicePixelsPerPixel; // The number of device pixel per "Device Independent Pixels" (value is usually 1, but 2 for mac retina screens)322 float devicePixelsPerPixel; // The number of device pixel per "Device Independent Pixels" (value is usually 1, but 2 for mac retina screens)
323323
324324
=== modified file 'src/core/StelToneReproducer.hpp'
--- src/core/StelToneReproducer.hpp 2014-11-04 10:59:12 +0000
+++ src/core/StelToneReproducer.hpp 2014-11-08 17:16:48 +0000
@@ -79,7 +79,7 @@
79 //! It is the parameter to modify to simulate aperture*exposition time79 //! It is the parameter to modify to simulate aperture*exposition time
80 //! @param scale the global input scale80 //! @param scale the global input scale
81 void setInputScale(float scale=1.f);81 void setInputScale(float scale=1.f);
82 //! Get the global scale applied to input lumiances, i.e before the adaptation82 //! Get the global scale applied to input luminances, i.e before the adaptation
83 float getInputScale() const83 float getInputScale() const
84 {84 {
85 return inputScale;85 return inputScale;
@@ -125,14 +125,14 @@
125 125
126 //! Return adapted luminance from world to display with 1 corresponding to full display white126 //! Return adapted luminance from world to display with 1 corresponding to full display white
127 //! @param worldLuminance the world luminance to convert in cd/m^2127 //! @param worldLuminance the world luminance to convert in cd/m^2
128 //! @return the converted display luminance with 1 corresponding to full display white. The value can be more than 1 when saturation..128 //! @return the converted display luminance with 1 corresponding to full display white. The value can be more than 1 when saturated.
129 float adaptLuminanceScaled(float worldLuminance) const129 float adaptLuminanceScaled(float worldLuminance) const
130 {130 {
131 return adaptLuminance(worldLuminance)*oneOverMaxdL;131 return adaptLuminance(worldLuminance)*oneOverMaxdL;
132 }132 }
133 133
134 //! Return adapted luminance from display to world with 1 corresponding to full display white134 //! Return adapted luminance from display to world with 1 corresponding to full display white
135 //! @param displayLuminance the display luminance with 1 corresponding to full display white. The value can be more than 1 when saturation..135 //! @param displayLuminance the display luminance with 1 corresponding to full display white. The value can be more than 1 when saturated.
136 //! @return the converted world luminance in cd/m^2136 //! @return the converted world luminance in cd/m^2
137 float reverseAdaptLuminanceScaled(float displayLuminance) const137 float reverseAdaptLuminanceScaled(float displayLuminance) const
138 {138 {
@@ -141,8 +141,8 @@
141 141
142 //! Return adapted ln(luminance) from world to display with 1 corresponding to full display white142 //! Return adapted ln(luminance) from world to display with 1 corresponding to full display white
143 //! @param lnWorldLuminance the world luminance to convert in ln(cd/m^2)143 //! @param lnWorldLuminance the world luminance to convert in ln(cd/m^2)
144 //! @param pFact the power at whihc the result should be set. The default is 0.5 and therefore return the square root of the adapted luminance144 //! @param pFact the power at which the result should be set. The default is 0.5 and therefore return the square root of the adapted luminance
145 //! @return the converted display set at the pFact power. Luminance with 1 corresponding to full display white. The value can be more than 1 when saturation..145 //! @return the converted display set at the pFact power. Luminance with 1 corresponding to full display white. The value can be more than 1 when saturated.
146 float adaptLuminanceScaledLn(float lnWorldLuminance, float pFact=0.5f) const146 float adaptLuminanceScaledLn(float lnWorldLuminance, float pFact=0.5f) const
147 {147 {
148 const float lnPix0p0001 = -8.0656104861f;148 const float lnPix0p0001 = -8.0656104861f;
149149
=== modified file 'src/core/modules/Comet.cpp'
--- src/core/modules/Comet.cpp 2014-10-19 05:54:43 +0000
+++ src/core/modules/Comet.cpp 2014-11-08 17:16:48 +0000
@@ -1,6 +1,7 @@
1/*1/*
2 * Stellarium2 * Stellarium
3 * Copyright (C) 2010 Bogdan Marinov3 * Copyright (C) 2010 Bogdan Marinov
4 * Copyright (C) 2014 Georg Zotti (Tails)
4 *5 *
5 * This program is free software; you can redistribute it and/or6 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License7 * modify it under the terms of the GNU General Public License
@@ -26,6 +27,7 @@
2627
27#include "StelTexture.hpp"28#include "StelTexture.hpp"
28#include "StelTextureMgr.hpp"29#include "StelTextureMgr.hpp"
30#include "StelToneReproducer.hpp"
29#include "StelTranslator.hpp"31#include "StelTranslator.hpp"
30#include "StelUtils.hpp"32#include "StelUtils.hpp"
31#include "StelFileMgr.hpp"33#include "StelFileMgr.hpp"
@@ -71,6 +73,7 @@
71 true, //halo73 true, //halo
72 pTypeStr),74 pTypeStr),
73 tailActive(false),75 tailActive(false),
76 tailBright(false),
74 dustTailWidthFactor(dustTailWidthFact),77 dustTailWidthFactor(dustTailWidthFact),
75 dustTailLengthFactor(dustTailLengthFact),78 dustTailLengthFactor(dustTailLengthFact),
76 dustTailBrightnessFactor(dustTailBrightnessFact)79 dustTailBrightnessFactor(dustTailBrightnessFact)
@@ -90,6 +93,8 @@
90 gastailVertexArr.clear();93 gastailVertexArr.clear();
91 dusttailVertexArr.clear();94 dusttailVertexArr.clear();
92 comaVertexArr.clear();95 comaVertexArr.clear();
96 gastailColorArr.clear();
97 dusttailColorArr.clear();
9398
94 //Comet specific members99 //Comet specific members
95 absoluteMagnitude = 0;100 absoluteMagnitude = 0;
@@ -281,19 +286,27 @@
281 return apparentMagnitude;286 return apparentMagnitude;
282}287}
283288
284// Compute the position in the parent Planet coordinate system289void Comet::update(int deltaTime)
285// Actually call the provided function to compute the ecliptical position, and buildup the tails!
286void Comet::computePosition(const double date)
287{290{
288 Planet::computePosition(date);291 Planet::update(deltaTime);
289 //GZ: I think we can make deltaJD adaptive, depending on distance to sun! For some reason though, this leads to a crash!292
290 //deltaJD=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(), 20.0));293 // The rest used to be in computePosition(), but is better in update(). Unfortunately we need date (JD).
294 StelCore* core=StelApp::getInstance().getCore();
295 double date=core->getJDay();
296
297 // The CometOrbit is in fact available in userDataPtr!
298 CometOrbit* orbit=(CometOrbit*)userDataPtr;
299 Q_ASSERT(orbit);
300 if (!orbit->objectDateValid(core->getJDay())) return; // don't do anything if out of useful date range. This allows having hundreds of comet elements.
301
302
303 //GZ: I think we can make deltaJDtail adaptive, depending on distance to sun! For some reason though, this leads to a crash!
304 //deltaJDtail=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(), 20.0));
291305
292 if (fabs(lastJDtail-date)>deltaJDtail)306 if (fabs(lastJDtail-date)>deltaJDtail)
293 {307 {
294 lastJDtail=date;308 lastJDtail=date;
295309
296 // GZ: Moved from draw() :-)
297 // The CometOrbit is in fact available in userDataPtr!310 // The CometOrbit is in fact available in userDataPtr!
298 CometOrbit* orbit=(CometOrbit*)userDataPtr;311 CometOrbit* orbit=(CometOrbit*)userDataPtr;
299 Q_ASSERT(orbit);312 Q_ASSERT(orbit);
@@ -301,11 +314,10 @@
301314
302 if (orbit->getUpdateTails()){315 if (orbit->getUpdateTails()){
303 // Compute lengths and orientations from orbit object, but only if required.316 // Compute lengths and orientations from orbit object, but only if required.
304 // This part moved from draw() to keep draw() free from too much computation.
305 tailFactors=getComaDiameterAndTailLengthAU();317 tailFactors=getComaDiameterAndTailLengthAU();
306318
307 // 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 better.319 // 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 better.
308 computeComa(1.0f*tailFactors[0]);320 computeComa(1.0f*tailFactors[0]); // TBD: APPARENTLY NO SCALING? REMOVE 1.0 and note above.
309321
310 tailActive = (tailFactors[1] > tailFactors[0]); // Inhibit tails drawing if too short. Would be nice to include geometric projection angle, but this is too costly.322 tailActive = (tailFactors[1] > tailFactors[0]); // Inhibit tails drawing if too short. Would be nice to include geometric projection angle, but this is too costly.
311323
@@ -318,10 +330,10 @@
318330
319 // Find valid parameters to create paraboloid vertex arrays: dustTail, gasTail.331 // Find valid parameters to create paraboloid vertex arrays: dustTail, gasTail.
320 computeParabola(gasparameter, gasTailEndRadius, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices);332 computeParabola(gasparameter, gasTailEndRadius, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices);
321 // This was for a rotated straight parabola:333 //gastailColorArr.fill(Vec3f(0.3,0.3,0.3), gastailVertexArr.length());
322 //computeParabola(dustparameter, 2.0f*tailFactors[0], -0.5f*dustparameter, dusttailVertexArr, dusttailTexCoordArr, dusttailIndices);
323 // Now we make a skewed parabola. Skew factor (xOffset, last arg) is rather ad-hoc/empirical. TBD later: Find physically correct solution.334 // Now we make a skewed parabola. Skew factor (xOffset, last arg) is rather ad-hoc/empirical. TBD later: Find physically correct solution.
324 computeParabola(dustparameter, dustTailWidthFactor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoordArr, tailIndices, 25.0f*orbit->getVelocity().length());335 computeParabola(dustparameter, dustTailWidthFactor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoordArr, tailIndices, 25.0f*orbit->getVelocity().length());
336 //dusttailColorArr.fill(Vec3f(0.3,0.3,0.3), dusttailVertexArr.length());
325337
326338
327 // 2014-08 for 0.13.1 Moved from drawTail() to save lots of computation per frame (There *are* folks downloading all 730 MPC current comet elements...)339 // 2014-08 for 0.13.1 Moved from drawTail() to save lots of computation per frame (There *are* folks downloading all 730 MPC current comet elements...)
@@ -336,7 +348,7 @@
336 // In addition, we let the dust tail already start with a light tilt.348 // In addition, we let the dust tail already start with a light tilt.
337 dustTailRot=gasTailRot * Mat4d::zrotation(atan2(velocity[1], velocity[0]) + M_PI) * Mat4d::yrotation(5.0f*velocity.length());349 dustTailRot=gasTailRot * Mat4d::zrotation(atan2(velocity[1], velocity[0]) + M_PI) * Mat4d::yrotation(5.0f*velocity.length());
338350
339 // TODO: If we want to be even faster, rotate vertex arrays here and not in drawTail()!351 // Rotate vertex arrays:
340 Vec3d* gasVertices=(Vec3d*) (gastailVertexArr.data());352 Vec3d* gasVertices=(Vec3d*) (gastailVertexArr.data());
341 Vec3d* dustVertices=(Vec3d*) (dusttailVertexArr.data());353 Vec3d* dustVertices=(Vec3d*) (dusttailVertexArr.data());
342 for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL_STACKS+1; ++i)354 for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL_STACKS+1; ++i)
@@ -345,34 +357,105 @@
345 dustVertices[i].transfo4d(dustTailRot);357 dustVertices[i].transfo4d(dustTailRot);
346 }358 }
347 }359 }
348
349 orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere360 orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere
350 }361 }
351 // Note: we can make deltaJDtail adaptive, depending on distance to sun!362 }
352 //deltaJDtail=5.0*StelCore::JD_MINUTE * qMax(0.01, qMin(eclipticPos.length(), 20.0));363
353 }364 // And also update magnitude and tail brightness/extinction here.
365 const bool withAtmosphere=(core->getSkyDrawer()->getFlagHasAtmosphere());
366
367 StelToneReproducer* eye = core->getToneReproducer();
368 float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVMagnitude(core)+13.0f); // How to calibrate?
369 // Get the luminance scaled between 0 and 1
370 float aLum =eye->adaptLuminanceScaled(lum);
371
372
373 // To make comet more apparent in overviews, take field of view into account:
374 const float fov=core->getProjection(core->getAltAzModelViewTransform())->getFov();
375 if (fov>20)
376 aLum*= (fov/20.0f);
377
378 // Now inhibit tail drawing if still too dim.
379 if (aLum<0.002f)
380 {
381 // Far too dim: don't even show tail...
382 tailBright=false;
383 return;
384 } else
385 tailBright=true;
386
387 // Separate factors, but avoid overly bright tails. I limit to about 0.7 for overlapping both tails which should not exceed full-white.
388 float gasMagFactor=qMin(0.9f*aLum, 0.7f);
389 float dustMagFactor=qMin(dustTailBrightnessFactor*aLum, 0.7f);
390
391 Vec3f gasColor(0.15f*gasMagFactor,0.35f*gasMagFactor,0.6f*gasMagFactor); // Orig color 0.15/0.15/0.6
392 Vec3f dustColor(dustMagFactor, dustMagFactor,0.6f*dustMagFactor);
393
394 if (withAtmosphere)
395 {
396 Extinction extinction=core->getSkyDrawer()->getExtinction();
397
398 // Not only correct the color values for extinction, but for twilight conditions, also make tail end less visible.
399 // I consider sky brightness over 1cd/m^2 as reason to shorten tail.
400 // Below this brightness, the tail brightness loss by this method is insignificant:
401 // Just counting through the vertices might make a spiral apperance. Maybe even better than stackwise? Let's see...
402 const float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance();
403 const float brightnessDecreasePerVertexFromHead=1.0f/(COMET_TAIL_SLICES*COMET_TAIL_STACKS) * avgAtmLum;
404 float brightnessPerVertexFromHead=1.0f;
405
406 gastailColorArr.clear();
407 dusttailColorArr.clear();
408 for (int i=0; i<gastailVertexArr.size(); ++i)
409 {
410 // Gastail extinction:
411 Vec3d vertAltAz=core->j2000ToAltAz(gastailVertexArr.at(i), StelCore::RefractionOn);
412 vertAltAz.normalize();
413 Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
414 float oneMag=0.0f;
415 extinction.forward(vertAltAz, &oneMag);
416 float extinctionFactor=std::pow(0.4f, oneMag); // drop of one magnitude: factor 2.5 or 40%
417 gastailColorArr.append(gasColor*extinctionFactor* brightnessPerVertexFromHead);
418
419 // dusttail extinction:
420 vertAltAz=core->j2000ToAltAz(dusttailVertexArr.at(i), StelCore::RefractionOn);
421 vertAltAz.normalize();
422 Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
423 oneMag=0.0f;
424 extinction.forward(vertAltAz, &oneMag);
425 extinctionFactor=std::pow(0.4f, oneMag); // drop of one magnitude: factor 2.5 or 40%
426 dusttailColorArr.append(dustColor*extinctionFactor * brightnessPerVertexFromHead);
427
428 brightnessPerVertexFromHead-=brightnessDecreasePerVertexFromHead;
429 }
430 }
431 else // no atmosphere: set all vertices to same brightness.
432 {
433 gastailColorArr.fill(gasColor, gastailVertexArr.length());
434 dusttailColorArr.fill(dustColor, dusttailVertexArr.length());
435 }
436 //qDebug() << "Comet " << getEnglishName() << "JD: " << date << "gasR" << gasColor[0] << " dustR" << dustColor[0];
354}437}
355438
356439
357// Draw the Comet and all the related infos : name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended440// Draw the Comet and all the related infos: name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended
358void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont)441void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont)
359{442{
360 if (hidden)443 if (hidden)
361 return;444 return;
362 if (getEnglishName() == core->getCurrentLocation().planetName)445 if (getEnglishName() == core->getCurrentLocation().planetName)
363 { // GZ: Maybe even don't do that? E.g., draw tail while riding the comet? Decide later.446 { // Maybe even don't do that? E.g., draw tail while riding the comet? Decide later.
364 return;447 return;
365 }448 }
366449
367 // GZ: If comet is too faint to be seen, don't bother rendering. (oops, should have been here in 2014-01... ;-)450 // If comet is too faint to be seen, don't bother rendering. (Massive speedup if people have hundreds of comets!)
368 if ((getVMagnitude(core)-2.0f) > core->getSkyDrawer()->getLimitMagnitude())451 if ((getVMagnitude(core)+2.0f) > core->getSkyDrawer()->getLimitMagnitude())
369 {452 {
370 return;453 return;
371 }454 }
372 // The CometOrbit is in fact available in userDataPtr!455 // The CometOrbit is in fact available in userDataPtr!
373 CometOrbit* orbit=(CometOrbit*)userDataPtr;456 CometOrbit* orbit=(CometOrbit*)userDataPtr;
374 Q_ASSERT(orbit);457 Q_ASSERT(orbit);
375 if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all out of useful date range. This allows having hundreds of comet elements.458 if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all if out of useful date range. This allows having hundreds of comet elements.
376459
377 Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;460 Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
378 // This removed totally the Planet shaking bug!!!461 // This removed totally the Planet shaking bug!!!
@@ -408,8 +491,8 @@
408491
409 draw3dModel(core,transfo,screenSz);492 draw3dModel(core,transfo,screenSz);
410 }493 }
411 // tails should also be drawn if comet core is off-screen...494 // but tails should also be drawn if comet core is off-screen...
412 if (tailActive)495 if (tailActive && tailBright)
413 {496 {
414 drawTail(core,transfo,true); // gas tail497 drawTail(core,transfo,true); // gas tail
415 drawTail(core,transfo,false); // dust tail498 drawTail(core,transfo,false); // dust tail
@@ -420,46 +503,24 @@
420}503}
421504
422void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP transfo, bool gas)505void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP transfo, bool gas)
423{506{
424 StelPainter* sPainter = new StelPainter(core->getProjection(transfo));507 StelPainter* sPainter = new StelPainter(core->getProjection(transfo));
425 glEnable(GL_BLEND);508 glEnable(GL_BLEND);
426 glBlendFunc(GL_ONE, GL_ONE);509 glBlendFunc(GL_ONE, GL_ONE);
427 glDisable(GL_CULL_FACE);510 glDisable(GL_CULL_FACE);
428511
429 // GZ: If we use getVMagnitudeWithExtinction(), a head extincted in the horizon mist can completely hide an otherwise frighteningly long tail.
430 // we must use unextincted mag, but mix/dim with atmosphere/sky brightness.
431 // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6.
432 float magFactor=std::pow(0.6f , getVMagnitude(core));
433 if (core->getSkyDrawer()->getFlagHasAtmosphere())
434 {
435 // Mix with sky brightness and light pollution: This is very ad-hoc, if someone finds a better solution, please go ahead!
436 // Light pollution:
437 float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->getBortleScaleIndex());
438 magFactor*= bortleIndexFactor*bortleIndexFactor; // GZ-Guesstimate for light pollution influence
439 // sky brightness: This is about 10 for twilight where bright comet tails should already be visible. Dark night is close to 0.
440 float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance();
441 float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFactor<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor);
442 magFactor*=atmLumFactor*atmLumFactor;
443 }
444 magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical adjustment for texture brightness.
445 magFactor=qMin(magFactor, 1.05f); // Limit excessively bright display.
446
447 tailTexture->bind();512 tailTexture->bind();
448513
449 if (gas) {514 if (gas) {
450 sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magFactor);515 sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData(), (Vec3f*)gastailColorArr.constData());
451 sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData());
452 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());516 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());
453517
454 } else {518 } else {
455 sPainter->setColor(magFactor, magFactor,0.6f*magFactor);519 sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData(), (Vec3f*)dusttailColorArr.constData());
456 sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData());
457 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());520 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());
458 }521 }
459 glDisable(GL_BLEND);522 glDisable(GL_BLEND);
460523
461
462
463 if (sPainter)524 if (sPainter)
464 delete sPainter;525 delete sPainter;
465 sPainter=NULL;526 sPainter=NULL;
@@ -478,16 +539,13 @@
478 glBlendFunc(GL_ONE, GL_ONE);539 glBlendFunc(GL_ONE, GL_ONE);
479 glDisable(GL_CULL_FACE);540 glDisable(GL_CULL_FACE);
480541
481 // GZ: For the coma, we can use extinction via atmosphere.542 StelToneReproducer* eye = core->getToneReproducer();
482 // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6.543 float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVMagnitudeWithExtinction(core)+11.0f); // How to calibrate?
483 float minSkyMag=core->getSkyDrawer()->getLimitMagnitude();544 // Get the luminance scaled between 0 and 1
484 float mag100pct=minSkyMag-6.0f; // should be 5, but let us draw it a bit brighter.545 float aLum =eye->adaptLuminanceScaled(lum);
485 float magDrop=getVMagnitudeWithExtinction(core)-mag100pct;546 float magFactor=qMin(qMax(aLum, 0.25f), 2.0f);
486 float magFactor=std::pow(0.6f , magDrop);
487 magFactor=qMin(magFactor, 2.0f); // Limit excessively bright display.
488
489 comaTexture->bind();547 comaTexture->bind();
490 sPainter->setColor(magFactor,magFactor,0.6f*magFactor);548 sPainter->setColor(0.3f*magFactor,0.7*magFactor,magFactor);
491 sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaTexCoordArr.constData());549 sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaTexCoordArr.constData());
492 sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size()/3);550 sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size()/3);
493551
@@ -521,11 +579,11 @@
521// Parabola equation: z=x²/2p.579// Parabola equation: z=x²/2p.
522// xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).580// xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).
523void Comet::computeParabola(const float parameter, const float radius, const float zshift,581void Comet::computeParabola(const float parameter, const float radius, const float zshift,
524 QVector<double>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short> &indices, const float xOffset) {582 QVector<Vec3d>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short> &indices, const float xOffset) {
525583
526 // GZ: keep the array and replace contents. However, using replace() is only slightly faster.584 // keep the array and replace contents. However, using replace() is only slightly faster.
527 if (vertexArr.length() < (3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)))585 if (vertexArr.length() < ((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)))
528 vertexArr.resize(3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));586 vertexArr.resize((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
529 if (createTailIndices) indices.clear();587 if (createTailIndices) indices.clear();
530 if (createTailTextureCoords) texCoordArr.clear();588 if (createTailTextureCoords) texCoordArr.clear();
531 int i;589 int i;
@@ -541,8 +599,8 @@
541 ya[i]=cos(i*da);599 ya[i]=cos(i*da);
542 }600 }
543 601
544 vertexArr.replace(0, 0.0); vertexArr.replace(1, 0.0); vertexArr.replace(2, zshift);602 vertexArr.replace(0, Vec3d(0.0, 0.0, zshift));
545 int vertexArrIndex=3;603 int vertexArrIndex=1;
546 if (createTailTextureCoords) texCoordArr << 0.5f << 0.5f;604 if (createTailTextureCoords) texCoordArr << 0.5f << 0.5f;
547 // define the indices lying on circles, starting at 1: odd rings have 1/slices+1/2slices, even-numbered rings straight 1/slices605 // define the indices lying on circles, starting at 1: odd rings have 1/slices+1/2slices, even-numbered rings straight 1/slices
548 // inner ring#1606 // inner ring#1
@@ -553,9 +611,7 @@
553 for (i=ring & 1; i<2*COMET_TAIL_SLICES; i+=2) { // i.e., ring1 has shifted vertices, ring2 has even ones.611 for (i=ring & 1; i<2*COMET_TAIL_SLICES; i+=2) { // i.e., ring1 has shifted vertices, ring2 has even ones.
554 x=xa[i]*radius*ring/COMET_TAIL_STACKS;612 x=xa[i]*radius*ring/COMET_TAIL_STACKS;
555 y=ya[i]*radius*ring/COMET_TAIL_STACKS;613 y=ya[i]*radius*ring/COMET_TAIL_STACKS;
556 vertexArr.replace(vertexArrIndex++, x+xShift);614 vertexArr.replace(vertexArrIndex++, Vec3d(x+xShift, y, z));
557 vertexArr.replace(vertexArrIndex++, y);
558 vertexArr.replace(vertexArrIndex++, z);
559 if (createTailTextureCoords) texCoordArr << 0.5+ 0.5*x/radius << 0.5+0.5*y/radius;615 if (createTailTextureCoords) texCoordArr << 0.5+ 0.5*x/radius << 0.5+0.5*y/radius;
560 }616 }
561 }617 }
@@ -591,10 +647,11 @@
591 createTailTextureCoords=false;647 createTailTextureCoords=false;
592}648}
593649
650
594// These are to avoid having index arrays for each comet when all are equal.651// These are to avoid having index arrays for each comet when all are equal.
595bool Comet::createTailIndices=true;652bool Comet::createTailIndices=true;
596bool Comet::createTailTextureCoords=true;653bool Comet::createTailTextureCoords=true;
597StelTextureSP Comet::comaTexture;654StelTextureSP Comet::comaTexture;
598StelTextureSP Comet::tailTexture;655StelTextureSP Comet::tailTexture;
599QVector<float> Comet::tailTexCoordArr; // computed only once FOR ALL COMETS!656QVector<float> Comet::tailTexCoordArr; // computed only once for all Comets.
600QVector<unsigned short> Comet::tailIndices; // computed only once FOR ALL COMETS!657QVector<unsigned short> Comet::tailIndices; // computed only once for all Comets.
601658
=== modified file 'src/core/modules/Comet.hpp'
--- src/core/modules/Comet.hpp 2014-08-31 08:35:52 +0000
+++ src/core/modules/Comet.hpp 2014-11-08 17:16:48 +0000
@@ -32,6 +32,7 @@
32 2013-12: GZ: New algorithms for position computation following Paul Heafner: Fundamental Ephemeris Computations (Willmann-Bell 1999).32 2013-12: GZ: New algorithms for position computation following Paul Heafner: Fundamental Ephemeris Computations (Willmann-Bell 1999).
33 2014-01: GZ: Parabolic tails appropriately scaled/rotated. Much is currently empirical, leaving room for physics-based improvements.33 2014-01: GZ: Parabolic tails appropriately scaled/rotated. Much is currently empirical, leaving room for physics-based improvements.
34 2014-08: GZ: speedup in case hundreds of comets are loaded.34 2014-08: GZ: speedup in case hundreds of comets are loaded.
35 2014-11: GZ: tail extinction, better brightness balance.
35 */36 */
36class Comet : public Planet37class Comet : public Planet
37{38{
@@ -91,11 +92,15 @@
91 virtual double getSiderealPeriod() const;92 virtual double getSiderealPeriod() const;
9293
93 //! GZ: override from Planet: extend with tail details.94 //! GZ: override from Planet: extend with tail details.
94 virtual void computePosition(const double date);95 //virtual void computePosition(const double date);
9596
96 //! re-implementation of Planet's draw()97 //! re-implementation of Planet's draw()
97 virtual void draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont);98 virtual void draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont);
9899
100 // re-implementation of Planet's update() to prepare tails (extinction etc). @param deltaTime: ms (since last call)
101 // TODO: computePosition can be removed and things added here!
102 virtual void update(int deltaTime);
103
99private:104private:
100 //! @returns estimates for (Coma diameter [AU], gas tail length [AU]).105 //! @returns estimates for (Coma diameter [AU], gas tail length [AU]).
101 //! Using the formula from Guide found by the GSoC2012 initiative at http://www.projectpluto.com/update7b.htm#comet_tail_formula106 //! Using the formula from Guide found by the GSoC2012 initiative at http://www.projectpluto.com/update7b.htm#comet_tail_formula
@@ -117,7 +122,7 @@
117 //! @param colorArr vertex colors (if not textured) r0, g0, b0, r1, g1, b1, ...122 //! @param colorArr vertex colors (if not textured) r0, g0, b0, r1, g1, b1, ...
118 //! @param indices into the former arrays (zero-starting), triplets forming triangles: t0,0, t0,1, t0,2, t1,0, t1,1, t1,2, ...123 //! @param indices into the former arrays (zero-starting), triplets forming triangles: t0,0, t0,1, t0,2, t1,0, t1,1, t1,2, ...
119 //! @param xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).124 //! @param xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).
120 void computeParabola(const float parameter, const float topradius, const float zshift, QVector<double>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short>& indices, const float xOffset=0.0f);125 void computeParabola(const float parameter, const float topradius, const float zshift, QVector<Vec3d>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short>& indices, const float xOffset=0.0f);
121126
122 double absoluteMagnitude;127 double absoluteMagnitude;
123 double slopeParameter;128 double slopeParameter;
@@ -127,9 +132,10 @@
127132
128 //GZ Tail additions133 //GZ Tail additions
129 Vec2f tailFactors; // result of latest call to getComaDiameterAndTailLengthAU(); Results cached here for infostring. [0]=Coma diameter, [1] gas tail length.134 Vec2f tailFactors; // result of latest call to getComaDiameterAndTailLengthAU(); Results cached here for infostring. [0]=Coma diameter, [1] gas tail length.
130 bool tailActive; //! true if there is a tail worth bothering (longer than COMET_MIN_TAIL_LENGTH_AU)? Drawing tails is quite costly.135 bool tailActive; //! true if there is a tail long enough to be worth drawing. Drawing tails is quite costly.
136 bool tailBright; //! true if tail is bright enough to draw.
131 double deltaJDtail; //! like deltaJD, but time difference between tail geometry updates.137 double deltaJDtail; //! like deltaJD, but time difference between tail geometry updates.
132 double lastJDtail; //! like lastJD, but time of last tail geometry update.138 double lastJDtail; //! like lastJD, but time of last tail geometry update.
133 Mat4d gasTailRot; //! rotation matrix for gas tail parabola139 Mat4d gasTailRot; //! rotation matrix for gas tail parabola
134 Mat4d dustTailRot; //! rotation matrix for the skewed dust tail parabola140 Mat4d dustTailRot; //! rotation matrix for the skewed dust tail parabola
135 float dustTailWidthFactor; //!< empirical individual broadening of the dust tail end, compared to the gas tail end. Actually, dust tail width=2*comaWidth*dustTailWidthFactor. Default 1.5141 float dustTailWidthFactor; //!< empirical individual broadening of the dust tail end, compared to the gas tail end. Actually, dust tail width=2*comaWidth*dustTailWidthFactor. Default 1.5
@@ -142,8 +148,10 @@
142 static bool createTailIndices;148 static bool createTailIndices;
143 static bool createTailTextureCoords;149 static bool createTailTextureCoords;
144150
145 QVector<double> gastailVertexArr; // computed frequently, describes parabolic shape (along z axis) of gas tail.151 QVector<Vec3d> gastailVertexArr; // computed frequently, describes parabolic shape (along z axis) of gas tail.
146 QVector<double> dusttailVertexArr; // computed frequently, describes parabolic shape (along z axis) of dust tail.152 QVector<Vec3d> dusttailVertexArr; // computed frequently, describes parabolic shape (along z axis) of dust tail.
153 QVector<Vec3f> gastailColorArr; // NEW computed for every 5 mins, modulates gas tail brightness for extinction
154 QVector<Vec3f> dusttailColorArr; // NEW computed for every 5 mins, modulates dust tail brightness for extinction
147 static QVector<float> tailTexCoordArr; // computed only once for all comets!155 static QVector<float> tailTexCoordArr; // computed only once for all comets!
148 static QVector<unsigned short> tailIndices; // computed only once for all comets!156 static QVector<unsigned short> tailIndices; // computed only once for all comets!
149 static StelTextureSP comaTexture;157 static StelTextureSP comaTexture;
150158
=== modified file 'src/core/modules/MilkyWay.cpp'
--- src/core/modules/MilkyWay.cpp 2014-10-27 22:40:49 +0000
+++ src/core/modules/MilkyWay.cpp 2014-11-08 17:16:48 +0000
@@ -128,7 +128,7 @@
128 for (int i=0; i<vertexArray->vertex.size(); ++i)128 for (int i=0; i<vertexArray->vertex.size(); ++i)
129 {129 {
130 Vec3d vertAltAz=core->j2000ToAltAz(vertexArray->vertex.at(i), StelCore::RefractionOn);130 Vec3d vertAltAz=core->j2000ToAltAz(vertexArray->vertex.at(i), StelCore::RefractionOn);
131 Q_ASSERT(vertAltAz.lengthSquared()-1.0 < 0.001f);131 Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
132132
133 float oneMag=0.0f;133 float oneMag=0.0f;
134 extinction.forward(vertAltAz, &oneMag);134 extinction.forward(vertAltAz, &oneMag);
135135
=== modified file 'src/core/modules/MinorPlanet.cpp'
--- src/core/modules/MinorPlanet.cpp 2014-08-31 10:34:41 +0000
+++ src/core/modules/MinorPlanet.cpp 2014-11-08 17:16:48 +0000
@@ -293,7 +293,6 @@
293 //Calculate phase angle293 //Calculate phase angle
294 //(Code copied from Planet::getVMagnitude())294 //(Code copied from Planet::getVMagnitude())
295 //(this is actually vector subtraction + the cosine theorem :))295 //(this is actually vector subtraction + the cosine theorem :))
296 // GZ Try now in float... speed difference is negligible, though.
297 const Vec3d& observerHelioPos = core->getObserverHeliocentricEclipticPos();296 const Vec3d& observerHelioPos = core->getObserverHeliocentricEclipticPos();
298 const float observerRq = observerHelioPos.lengthSquared();297 const float observerRq = observerHelioPos.lengthSquared();
299 const Vec3d& planetHelioPos = getHeliocentricEclipticPos();298 const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
300299
=== modified file 'src/core/modules/Planet.cpp'
--- src/core/modules/Planet.cpp 2014-11-05 14:49:44 +0000
+++ src/core/modules/Planet.cpp 2014-11-08 17:16:48 +0000
@@ -679,7 +679,7 @@
679double Planet::computeDistance(const Vec3d& obsHelioPos)679double Planet::computeDistance(const Vec3d& obsHelioPos)
680{680{
681 distance = (obsHelioPos-getHeliocentricEclipticPos()).length();681 distance = (obsHelioPos-getHeliocentricEclipticPos()).length();
682 // GZ: improve fps by juggling updates for asteroids. They must be fast if close to observer, but can be slow if further away.682 // improve fps by juggling updates for asteroids. They must be fast if close to observer, but can be slow if further away.
683 if (pType == Planet::isAsteroid)683 if (pType == Planet::isAsteroid)
684 deltaJD=distance*StelCore::JD_SECOND;684 deltaJD=distance*StelCore::JD_SECOND;
685 return distance;685 return distance;
@@ -928,11 +928,11 @@
928{928{
929 if (hidden)929 if (hidden)
930 return;930 return;
931 // GZ: Try to improve speed for minor planets: test if visible at all.931 // Try to improve speed for minor planets: test if visible at all.
932 // For a full catalog of NEAs (11000 objects), with this and resetting deltaJD according to distance, rendering time went 4.5fps->12fps. 932 // For a full catalog of NEAs (11000 objects), with this and resetting deltaJD according to distance, rendering time went 4.5fps->12fps.
933 // AW: Apply this rule to asteroids only933 // TBD: Note that taking away the asteroids at this stage breaks dim-asteroid occultation of stars!
934 // Note that taking away the asteroids at this stage breaks dim-asteroid occultation of stars!934 // Maybe make another configurable flag for those interested?
935 if (((getVMagnitude(core)-1.0f) > core->getSkyDrawer()->getLimitMagnitude()) && pType==Planet::isAsteroid)935 if (((getVMagnitude(core)+1.0f) > core->getSkyDrawer()->getLimitMagnitude()) && pType==Planet::isAsteroid)
936 {936 {
937 return;937 return;
938 }938 }
939939
=== modified file 'src/core/modules/Planet.hpp'
--- src/core/modules/Planet.hpp 2014-11-01 15:03:47 +0000
+++ src/core/modules/Planet.hpp 2014-11-08 17:16:48 +0000
@@ -192,7 +192,8 @@
192192
193 // Compute the position in the parent Planet coordinate system193 // Compute the position in the parent Planet coordinate system
194 void computePositionWithoutOrbits(const double dateJD);194 void computePositionWithoutOrbits(const double dateJD);
195 virtual void computePosition(const double dateJD);// GZ: gets overridden in Comet!195 //virtual void computePosition(const double dateJD);// GZ: gets overridden in Comet!
196 void computePosition(const double dateJD);// GZ: gets overridden in Comet!
196197
197 // Compute the transformation matrix from the local Planet coordinate to the parent Planet coordinate198 // Compute the transformation matrix from the local Planet coordinate to the parent Planet coordinate
198 void computeTransMatrix(double date);199 void computeTransMatrix(double date);
@@ -237,8 +238,8 @@
237 static void setLabelColor(const Vec3f& lc) {labelColor = lc;}238 static void setLabelColor(const Vec3f& lc) {labelColor = lc;}
238 static const Vec3f& getLabelColor(void) {return labelColor;}239 static const Vec3f& getLabelColor(void) {return labelColor;}
239240
240 // update displayed elements. @param deltaTime: ms (?)241 // update displayed elements. @param deltaTime: ms (since last call)
241 void update(int deltaTime);242 virtual void update(int deltaTime);
242243
243 void setFlagHints(bool b){hintFader = b;}244 void setFlagHints(bool b){hintFader = b;}
244 bool getFlagHints(void) const {return hintFader;}245 bool getFlagHints(void) const {return hintFader;}