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
1=== modified file 'src/core/StelApp.hpp'
2--- src/core/StelApp.hpp 2014-11-04 10:59:12 +0000
3+++ src/core/StelApp.hpp 2014-11-08 17:16:48 +0000
4@@ -148,7 +148,8 @@
5 void update(double deltaTime);
6
7 //! Draw all registered StelModule in the order defined by the order lists.
8- //! @return the max squared distance in pixels that any object has travelled since the last update.
9+ // 2014-11: OLD COMMENT? What does a void return?
10+ // @return the max squared distance in pixels that any object has travelled since the last update.
11 void draw();
12
13 //! Call this when the size of the GL window has changed.
14
15=== modified file 'src/core/StelPainter.cpp'
16--- src/core/StelPainter.cpp 2014-11-04 12:15:15 +0000
17+++ src/core/StelPainter.cpp 2014-11-08 17:16:48 +0000
18@@ -544,7 +544,7 @@
19
20 // Translate/rotate
21 if (!noGravity)
22- angleDeg += prj->defautAngleForGravityText;
23+ angleDeg += prj->defaultAngleForGravityText;
24
25 if (std::fabs(angleDeg)>1.f)
26 {
27@@ -1357,6 +1357,7 @@
28 break;
29 case SphericalPolygonDrawModeFill:
30 case SphericalPolygonDrawModeTextureFill:
31+ case SphericalPolygonDrawModeTextureFillColormodulated:
32 glEnable(GL_CULL_FACE);
33 // The polygon is already tesselated as triangles
34 if (doSubDivise || prj->intersectViewportDiscontinuity(poly->getBoundingCap()))
35
36=== modified file 'src/core/StelProjector.cpp'
37--- src/core/StelProjector.cpp 2013-10-01 22:05:10 +0000
38+++ src/core/StelProjector.cpp 2014-11-08 17:16:48 +0000
39@@ -116,7 +116,7 @@
40 viewportCenter = params.viewportCenter;
41 viewportCenter *= devicePixelsPerPixel;
42 gravityLabels = params.gravityLabels;
43- defautAngleForGravityText = params.defautAngleForGravityText;
44+ defaultAngleForGravityText = params.defautAngleForGravityText;
45 flipHorz = params.flipHorz ? -1.f : 1.f;
46 flipVert = params.flipVert ? -1.f : 1.f;
47 viewportFovDiameter = params.viewportFovDiameter * devicePixelsPerPixel;
48
49=== modified file 'src/core/StelProjector.hpp'
50--- src/core/StelProjector.hpp 2014-10-16 17:32:50 +0000
51+++ src/core/StelProjector.hpp 2014-11-08 17:16:48 +0000
52@@ -291,7 +291,7 @@
53 oneOverZNearMinusZFar(0.f),
54 viewportFovDiameter(0.f),
55 gravityLabels(true),
56- defautAngleForGravityText(0.f),
57+ defaultAngleForGravityText(0.f),
58 devicePixelsPerPixel(1.f) {;}
59
60 //! Return whether the projection presents discontinuities. Used for optimization.
61@@ -317,7 +317,7 @@
62 Vec2f viewportCenter; // Viewport center in screen pixel
63 float viewportFovDiameter; // diameter of the FOV disk in pixel
64 bool gravityLabels; // should label text align with the horizon?
65- float defautAngleForGravityText; // a rotation angle to apply to gravity text (only if gravityLabels is set to false)
66+ float defaultAngleForGravityText; // a rotation angle to apply to gravity text (only if gravityLabels is set to false)
67 SphericalCap boundingCap; // Bounding cap of the whole viewport
68 float devicePixelsPerPixel; // The number of device pixel per "Device Independent Pixels" (value is usually 1, but 2 for mac retina screens)
69
70
71=== modified file 'src/core/StelToneReproducer.hpp'
72--- src/core/StelToneReproducer.hpp 2014-11-04 10:59:12 +0000
73+++ src/core/StelToneReproducer.hpp 2014-11-08 17:16:48 +0000
74@@ -79,7 +79,7 @@
75 //! It is the parameter to modify to simulate aperture*exposition time
76 //! @param scale the global input scale
77 void setInputScale(float scale=1.f);
78- //! Get the global scale applied to input lumiances, i.e before the adaptation
79+ //! Get the global scale applied to input luminances, i.e before the adaptation
80 float getInputScale() const
81 {
82 return inputScale;
83@@ -125,14 +125,14 @@
84
85 //! Return adapted luminance from world to display with 1 corresponding to full display white
86 //! @param worldLuminance the world luminance to convert in cd/m^2
87- //! @return the converted display luminance with 1 corresponding to full display white. The value can be more than 1 when saturation..
88+ //! @return the converted display luminance with 1 corresponding to full display white. The value can be more than 1 when saturated.
89 float adaptLuminanceScaled(float worldLuminance) const
90 {
91 return adaptLuminance(worldLuminance)*oneOverMaxdL;
92 }
93
94 //! Return adapted luminance from display to world with 1 corresponding to full display white
95- //! @param displayLuminance the display luminance with 1 corresponding to full display white. The value can be more than 1 when saturation..
96+ //! @param displayLuminance the display luminance with 1 corresponding to full display white. The value can be more than 1 when saturated.
97 //! @return the converted world luminance in cd/m^2
98 float reverseAdaptLuminanceScaled(float displayLuminance) const
99 {
100@@ -141,8 +141,8 @@
101
102 //! Return adapted ln(luminance) from world to display with 1 corresponding to full display white
103 //! @param lnWorldLuminance the world luminance to convert in ln(cd/m^2)
104- //! @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 luminance
105- //! @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..
106+ //! @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
107+ //! @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.
108 float adaptLuminanceScaledLn(float lnWorldLuminance, float pFact=0.5f) const
109 {
110 const float lnPix0p0001 = -8.0656104861f;
111
112=== modified file 'src/core/modules/Comet.cpp'
113--- src/core/modules/Comet.cpp 2014-10-19 05:54:43 +0000
114+++ src/core/modules/Comet.cpp 2014-11-08 17:16:48 +0000
115@@ -1,6 +1,7 @@
116 /*
117 * Stellarium
118 * Copyright (C) 2010 Bogdan Marinov
119+ * Copyright (C) 2014 Georg Zotti (Tails)
120 *
121 * This program is free software; you can redistribute it and/or
122 * modify it under the terms of the GNU General Public License
123@@ -26,6 +27,7 @@
124
125 #include "StelTexture.hpp"
126 #include "StelTextureMgr.hpp"
127+#include "StelToneReproducer.hpp"
128 #include "StelTranslator.hpp"
129 #include "StelUtils.hpp"
130 #include "StelFileMgr.hpp"
131@@ -71,6 +73,7 @@
132 true, //halo
133 pTypeStr),
134 tailActive(false),
135+ tailBright(false),
136 dustTailWidthFactor(dustTailWidthFact),
137 dustTailLengthFactor(dustTailLengthFact),
138 dustTailBrightnessFactor(dustTailBrightnessFact)
139@@ -90,6 +93,8 @@
140 gastailVertexArr.clear();
141 dusttailVertexArr.clear();
142 comaVertexArr.clear();
143+ gastailColorArr.clear();
144+ dusttailColorArr.clear();
145
146 //Comet specific members
147 absoluteMagnitude = 0;
148@@ -281,19 +286,27 @@
149 return apparentMagnitude;
150 }
151
152-// Compute the position in the parent Planet coordinate system
153-// Actually call the provided function to compute the ecliptical position, and buildup the tails!
154-void Comet::computePosition(const double date)
155+void Comet::update(int deltaTime)
156 {
157- Planet::computePosition(date);
158- //GZ: I think we can make deltaJD adaptive, depending on distance to sun! For some reason though, this leads to a crash!
159- //deltaJD=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(), 20.0));
160+ Planet::update(deltaTime);
161+
162+ // The rest used to be in computePosition(), but is better in update(). Unfortunately we need date (JD).
163+ StelCore* core=StelApp::getInstance().getCore();
164+ double date=core->getJDay();
165+
166+ // The CometOrbit is in fact available in userDataPtr!
167+ CometOrbit* orbit=(CometOrbit*)userDataPtr;
168+ Q_ASSERT(orbit);
169+ if (!orbit->objectDateValid(core->getJDay())) return; // don't do anything if out of useful date range. This allows having hundreds of comet elements.
170+
171+
172+ //GZ: I think we can make deltaJDtail adaptive, depending on distance to sun! For some reason though, this leads to a crash!
173+ //deltaJDtail=StelCore::JD_SECOND * qMax(1.0, qMin(eclipticPos.length(), 20.0));
174
175 if (fabs(lastJDtail-date)>deltaJDtail)
176 {
177 lastJDtail=date;
178
179- // GZ: Moved from draw() :-)
180 // The CometOrbit is in fact available in userDataPtr!
181 CometOrbit* orbit=(CometOrbit*)userDataPtr;
182 Q_ASSERT(orbit);
183@@ -301,11 +314,10 @@
184
185 if (orbit->getUpdateTails()){
186 // Compute lengths and orientations from orbit object, but only if required.
187- // This part moved from draw() to keep draw() free from too much computation.
188 tailFactors=getComaDiameterAndTailLengthAU();
189
190 // 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.
191- computeComa(1.0f*tailFactors[0]);
192+ computeComa(1.0f*tailFactors[0]); // TBD: APPARENTLY NO SCALING? REMOVE 1.0 and note above.
193
194 tailActive = (tailFactors[1] > tailFactors[0]); // Inhibit tails drawing if too short. Would be nice to include geometric projection angle, but this is too costly.
195
196@@ -318,10 +330,10 @@
197
198 // Find valid parameters to create paraboloid vertex arrays: dustTail, gasTail.
199 computeParabola(gasparameter, gasTailEndRadius, -0.5f*gasparameter, gastailVertexArr, tailTexCoordArr, tailIndices);
200- // This was for a rotated straight parabola:
201- //computeParabola(dustparameter, 2.0f*tailFactors[0], -0.5f*dustparameter, dusttailVertexArr, dusttailTexCoordArr, dusttailIndices);
202+ //gastailColorArr.fill(Vec3f(0.3,0.3,0.3), gastailVertexArr.length());
203 // Now we make a skewed parabola. Skew factor (xOffset, last arg) is rather ad-hoc/empirical. TBD later: Find physically correct solution.
204 computeParabola(dustparameter, dustTailWidthFactor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, tailTexCoordArr, tailIndices, 25.0f*orbit->getVelocity().length());
205+ //dusttailColorArr.fill(Vec3f(0.3,0.3,0.3), dusttailVertexArr.length());
206
207
208 // 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...)
209@@ -336,7 +348,7 @@
210 // In addition, we let the dust tail already start with a light tilt.
211 dustTailRot=gasTailRot * Mat4d::zrotation(atan2(velocity[1], velocity[0]) + M_PI) * Mat4d::yrotation(5.0f*velocity.length());
212
213- // TODO: If we want to be even faster, rotate vertex arrays here and not in drawTail()!
214+ // Rotate vertex arrays:
215 Vec3d* gasVertices=(Vec3d*) (gastailVertexArr.data());
216 Vec3d* dustVertices=(Vec3d*) (dusttailVertexArr.data());
217 for (int i=0; i<COMET_TAIL_SLICES*COMET_TAIL_STACKS+1; ++i)
218@@ -345,34 +357,105 @@
219 dustVertices[i].transfo4d(dustTailRot);
220 }
221 }
222-
223 orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere
224 }
225- // Note: we can make deltaJDtail adaptive, depending on distance to sun!
226- //deltaJDtail=5.0*StelCore::JD_MINUTE * qMax(0.01, qMin(eclipticPos.length(), 20.0));
227- }
228+ }
229+
230+ // And also update magnitude and tail brightness/extinction here.
231+ const bool withAtmosphere=(core->getSkyDrawer()->getFlagHasAtmosphere());
232+
233+ StelToneReproducer* eye = core->getToneReproducer();
234+ float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVMagnitude(core)+13.0f); // How to calibrate?
235+ // Get the luminance scaled between 0 and 1
236+ float aLum =eye->adaptLuminanceScaled(lum);
237+
238+
239+ // To make comet more apparent in overviews, take field of view into account:
240+ const float fov=core->getProjection(core->getAltAzModelViewTransform())->getFov();
241+ if (fov>20)
242+ aLum*= (fov/20.0f);
243+
244+ // Now inhibit tail drawing if still too dim.
245+ if (aLum<0.002f)
246+ {
247+ // Far too dim: don't even show tail...
248+ tailBright=false;
249+ return;
250+ } else
251+ tailBright=true;
252+
253+ // Separate factors, but avoid overly bright tails. I limit to about 0.7 for overlapping both tails which should not exceed full-white.
254+ float gasMagFactor=qMin(0.9f*aLum, 0.7f);
255+ float dustMagFactor=qMin(dustTailBrightnessFactor*aLum, 0.7f);
256+
257+ Vec3f gasColor(0.15f*gasMagFactor,0.35f*gasMagFactor,0.6f*gasMagFactor); // Orig color 0.15/0.15/0.6
258+ Vec3f dustColor(dustMagFactor, dustMagFactor,0.6f*dustMagFactor);
259+
260+ if (withAtmosphere)
261+ {
262+ Extinction extinction=core->getSkyDrawer()->getExtinction();
263+
264+ // Not only correct the color values for extinction, but for twilight conditions, also make tail end less visible.
265+ // I consider sky brightness over 1cd/m^2 as reason to shorten tail.
266+ // Below this brightness, the tail brightness loss by this method is insignificant:
267+ // Just counting through the vertices might make a spiral apperance. Maybe even better than stackwise? Let's see...
268+ const float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance();
269+ const float brightnessDecreasePerVertexFromHead=1.0f/(COMET_TAIL_SLICES*COMET_TAIL_STACKS) * avgAtmLum;
270+ float brightnessPerVertexFromHead=1.0f;
271+
272+ gastailColorArr.clear();
273+ dusttailColorArr.clear();
274+ for (int i=0; i<gastailVertexArr.size(); ++i)
275+ {
276+ // Gastail extinction:
277+ Vec3d vertAltAz=core->j2000ToAltAz(gastailVertexArr.at(i), StelCore::RefractionOn);
278+ vertAltAz.normalize();
279+ Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
280+ float oneMag=0.0f;
281+ extinction.forward(vertAltAz, &oneMag);
282+ float extinctionFactor=std::pow(0.4f, oneMag); // drop of one magnitude: factor 2.5 or 40%
283+ gastailColorArr.append(gasColor*extinctionFactor* brightnessPerVertexFromHead);
284+
285+ // dusttail extinction:
286+ vertAltAz=core->j2000ToAltAz(dusttailVertexArr.at(i), StelCore::RefractionOn);
287+ vertAltAz.normalize();
288+ Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
289+ oneMag=0.0f;
290+ extinction.forward(vertAltAz, &oneMag);
291+ extinctionFactor=std::pow(0.4f, oneMag); // drop of one magnitude: factor 2.5 or 40%
292+ dusttailColorArr.append(dustColor*extinctionFactor * brightnessPerVertexFromHead);
293+
294+ brightnessPerVertexFromHead-=brightnessDecreasePerVertexFromHead;
295+ }
296+ }
297+ else // no atmosphere: set all vertices to same brightness.
298+ {
299+ gastailColorArr.fill(gasColor, gastailVertexArr.length());
300+ dusttailColorArr.fill(dustColor, dusttailVertexArr.length());
301+ }
302+ //qDebug() << "Comet " << getEnglishName() << "JD: " << date << "gasR" << gasColor[0] << " dustR" << dustColor[0];
303 }
304
305
306-// Draw the Comet and all the related infos : name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended
307+// Draw the Comet and all the related infos: name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended
308 void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont)
309 {
310 if (hidden)
311 return;
312 if (getEnglishName() == core->getCurrentLocation().planetName)
313- { // GZ: Maybe even don't do that? E.g., draw tail while riding the comet? Decide later.
314+ { // Maybe even don't do that? E.g., draw tail while riding the comet? Decide later.
315 return;
316 }
317
318- // GZ: If comet is too faint to be seen, don't bother rendering. (oops, should have been here in 2014-01... ;-)
319- if ((getVMagnitude(core)-2.0f) > core->getSkyDrawer()->getLimitMagnitude())
320+ // If comet is too faint to be seen, don't bother rendering. (Massive speedup if people have hundreds of comets!)
321+ if ((getVMagnitude(core)+2.0f) > core->getSkyDrawer()->getLimitMagnitude())
322 {
323 return;
324 }
325 // The CometOrbit is in fact available in userDataPtr!
326 CometOrbit* orbit=(CometOrbit*)userDataPtr;
327 Q_ASSERT(orbit);
328- if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all out of useful date range. This allows having hundreds of comet elements.
329+ if (!orbit->objectDateValid(core->getJDay())) return; // don't draw at all if out of useful date range. This allows having hundreds of comet elements.
330
331 Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent;
332 // This removed totally the Planet shaking bug!!!
333@@ -408,8 +491,8 @@
334
335 draw3dModel(core,transfo,screenSz);
336 }
337- // tails should also be drawn if comet core is off-screen...
338- if (tailActive)
339+ // but tails should also be drawn if comet core is off-screen...
340+ if (tailActive && tailBright)
341 {
342 drawTail(core,transfo,true); // gas tail
343 drawTail(core,transfo,false); // dust tail
344@@ -420,46 +503,24 @@
345 }
346
347 void Comet::drawTail(StelCore* core, StelProjector::ModelViewTranformP transfo, bool gas)
348-{
349+{
350 StelPainter* sPainter = new StelPainter(core->getProjection(transfo));
351 glEnable(GL_BLEND);
352 glBlendFunc(GL_ONE, GL_ONE);
353 glDisable(GL_CULL_FACE);
354
355- // GZ: If we use getVMagnitudeWithExtinction(), a head extincted in the horizon mist can completely hide an otherwise frighteningly long tail.
356- // we must use unextincted mag, but mix/dim with atmosphere/sky brightness.
357- // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6.
358- float magFactor=std::pow(0.6f , getVMagnitude(core));
359- if (core->getSkyDrawer()->getFlagHasAtmosphere())
360- {
361- // Mix with sky brightness and light pollution: This is very ad-hoc, if someone finds a better solution, please go ahead!
362- // Light pollution:
363- float bortleIndexFactor=0.1f * (11 - core->getSkyDrawer()->getBortleScaleIndex());
364- magFactor*= bortleIndexFactor*bortleIndexFactor; // GZ-Guesstimate for light pollution influence
365- // sky brightness: This is about 10 for twilight where bright comet tails should already be visible. Dark night is close to 0.
366- float avgAtmLum=GETSTELMODULE(LandscapeMgr)->getAtmosphereAverageLuminance();
367- float atmLumFactor=(15.0f-avgAtmLum)/15.0f; if (atmLumFactor<0.05f) atmLumFactor=0.05f; //atmLumFactor=std::sqrt(atmLumFactor);
368- magFactor*=atmLumFactor*atmLumFactor;
369- }
370- magFactor*=(gas? 0.9 : dustTailBrightnessFactor); // TBD: empirical adjustment for texture brightness.
371- magFactor=qMin(magFactor, 1.05f); // Limit excessively bright display.
372-
373 tailTexture->bind();
374
375 if (gas) {
376- sPainter->setColor(0.15f*magFactor,0.15f*magFactor,0.6f*magFactor);
377- sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData());
378+ sPainter->setArrays((Vec3d*)gastailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData(), (Vec3f*)gastailColorArr.constData());
379 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());
380
381 } else {
382- sPainter->setColor(magFactor, magFactor,0.6f*magFactor);
383- sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData());
384+ sPainter->setArrays((Vec3d*)dusttailVertexArr.constData(), (Vec2f*)tailTexCoordArr.constData(), (Vec3f*)dusttailColorArr.constData());
385 sPainter->drawFromArray(StelPainter::Triangles, tailIndices.size(), 0, true, tailIndices.constData());
386 }
387 glDisable(GL_BLEND);
388
389-
390-
391 if (sPainter)
392 delete sPainter;
393 sPainter=NULL;
394@@ -478,16 +539,13 @@
395 glBlendFunc(GL_ONE, GL_ONE);
396 glDisable(GL_CULL_FACE);
397
398- // GZ: For the coma, we can use extinction via atmosphere.
399- // In addition, light falloff is a bit reduced for better visibility. Power basis should be 0.4, we use 0.6.
400- float minSkyMag=core->getSkyDrawer()->getLimitMagnitude();
401- float mag100pct=minSkyMag-6.0f; // should be 5, but let us draw it a bit brighter.
402- float magDrop=getVMagnitudeWithExtinction(core)-mag100pct;
403- float magFactor=std::pow(0.6f , magDrop);
404- magFactor=qMin(magFactor, 2.0f); // Limit excessively bright display.
405-
406+ StelToneReproducer* eye = core->getToneReproducer();
407+ float lum = core->getSkyDrawer()->surfacebrightnessToLuminance(getVMagnitudeWithExtinction(core)+11.0f); // How to calibrate?
408+ // Get the luminance scaled between 0 and 1
409+ float aLum =eye->adaptLuminanceScaled(lum);
410+ float magFactor=qMin(qMax(aLum, 0.25f), 2.0f);
411 comaTexture->bind();
412- sPainter->setColor(magFactor,magFactor,0.6f*magFactor);
413+ sPainter->setColor(0.3f*magFactor,0.7*magFactor,magFactor);
414 sPainter->setArrays((Vec3d*)comaVertexArr.constData(), (Vec2f*)comaTexCoordArr.constData());
415 sPainter->drawFromArray(StelPainter::Triangles, comaVertexArr.size()/3);
416
417@@ -521,11 +579,11 @@
418 // Parabola equation: z=x²/2p.
419 // xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).
420 void Comet::computeParabola(const float parameter, const float radius, const float zshift,
421- QVector<double>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short> &indices, const float xOffset) {
422+ QVector<Vec3d>& vertexArr, QVector<float>& texCoordArr, QVector<unsigned short> &indices, const float xOffset) {
423
424- // GZ: keep the array and replace contents. However, using replace() is only slightly faster.
425- if (vertexArr.length() < (3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)))
426- vertexArr.resize(3*(COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
427+ // keep the array and replace contents. However, using replace() is only slightly faster.
428+ if (vertexArr.length() < ((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1)))
429+ vertexArr.resize((COMET_TAIL_SLICES*COMET_TAIL_STACKS+1));
430 if (createTailIndices) indices.clear();
431 if (createTailTextureCoords) texCoordArr.clear();
432 int i;
433@@ -541,8 +599,8 @@
434 ya[i]=cos(i*da);
435 }
436
437- vertexArr.replace(0, 0.0); vertexArr.replace(1, 0.0); vertexArr.replace(2, zshift);
438- int vertexArrIndex=3;
439+ vertexArr.replace(0, Vec3d(0.0, 0.0, zshift));
440+ int vertexArrIndex=1;
441 if (createTailTextureCoords) texCoordArr << 0.5f << 0.5f;
442 // define the indices lying on circles, starting at 1: odd rings have 1/slices+1/2slices, even-numbered rings straight 1/slices
443 // inner ring#1
444@@ -553,9 +611,7 @@
445 for (i=ring & 1; i<2*COMET_TAIL_SLICES; i+=2) { // i.e., ring1 has shifted vertices, ring2 has even ones.
446 x=xa[i]*radius*ring/COMET_TAIL_STACKS;
447 y=ya[i]*radius*ring/COMET_TAIL_STACKS;
448- vertexArr.replace(vertexArrIndex++, x+xShift);
449- vertexArr.replace(vertexArrIndex++, y);
450- vertexArr.replace(vertexArrIndex++, z);
451+ vertexArr.replace(vertexArrIndex++, Vec3d(x+xShift, y, z));
452 if (createTailTextureCoords) texCoordArr << 0.5+ 0.5*x/radius << 0.5+0.5*y/radius;
453 }
454 }
455@@ -591,10 +647,11 @@
456 createTailTextureCoords=false;
457 }
458
459+
460 // These are to avoid having index arrays for each comet when all are equal.
461 bool Comet::createTailIndices=true;
462 bool Comet::createTailTextureCoords=true;
463 StelTextureSP Comet::comaTexture;
464 StelTextureSP Comet::tailTexture;
465-QVector<float> Comet::tailTexCoordArr; // computed only once FOR ALL COMETS!
466-QVector<unsigned short> Comet::tailIndices; // computed only once FOR ALL COMETS!
467+QVector<float> Comet::tailTexCoordArr; // computed only once for all Comets.
468+QVector<unsigned short> Comet::tailIndices; // computed only once for all Comets.
469
470=== modified file 'src/core/modules/Comet.hpp'
471--- src/core/modules/Comet.hpp 2014-08-31 08:35:52 +0000
472+++ src/core/modules/Comet.hpp 2014-11-08 17:16:48 +0000
473@@ -32,6 +32,7 @@
474 2013-12: GZ: New algorithms for position computation following Paul Heafner: Fundamental Ephemeris Computations (Willmann-Bell 1999).
475 2014-01: GZ: Parabolic tails appropriately scaled/rotated. Much is currently empirical, leaving room for physics-based improvements.
476 2014-08: GZ: speedup in case hundreds of comets are loaded.
477+ 2014-11: GZ: tail extinction, better brightness balance.
478 */
479 class Comet : public Planet
480 {
481@@ -91,11 +92,15 @@
482 virtual double getSiderealPeriod() const;
483
484 //! GZ: override from Planet: extend with tail details.
485- virtual void computePosition(const double date);
486+ //virtual void computePosition(const double date);
487
488 //! re-implementation of Planet's draw()
489 virtual void draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont);
490
491+ // re-implementation of Planet's update() to prepare tails (extinction etc). @param deltaTime: ms (since last call)
492+ // TODO: computePosition can be removed and things added here!
493+ virtual void update(int deltaTime);
494+
495 private:
496 //! @returns estimates for (Coma diameter [AU], gas tail length [AU]).
497 //! Using the formula from Guide found by the GSoC2012 initiative at http://www.projectpluto.com/update7b.htm#comet_tail_formula
498@@ -117,7 +122,7 @@
499 //! @param colorArr vertex colors (if not textured) r0, g0, b0, r1, g1, b1, ...
500 //! @param indices into the former arrays (zero-starting), triplets forming triangles: t0,0, t0,1, t0,2, t1,0, t1,1, t1,2, ...
501 //! @param xOffset for the dust tail, this may introduce a bend. Units are x per sqrt(z).
502- 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);
503+ 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);
504
505 double absoluteMagnitude;
506 double slopeParameter;
507@@ -127,9 +132,10 @@
508
509 //GZ Tail additions
510 Vec2f tailFactors; // result of latest call to getComaDiameterAndTailLengthAU(); Results cached here for infostring. [0]=Coma diameter, [1] gas tail length.
511- bool tailActive; //! true if there is a tail worth bothering (longer than COMET_MIN_TAIL_LENGTH_AU)? Drawing tails is quite costly.
512+ bool tailActive; //! true if there is a tail long enough to be worth drawing. Drawing tails is quite costly.
513+ bool tailBright; //! true if tail is bright enough to draw.
514 double deltaJDtail; //! like deltaJD, but time difference between tail geometry updates.
515- double lastJDtail; //! like lastJD, but time of last tail geometry update.
516+ double lastJDtail; //! like lastJD, but time of last tail geometry update.
517 Mat4d gasTailRot; //! rotation matrix for gas tail parabola
518 Mat4d dustTailRot; //! rotation matrix for the skewed dust tail parabola
519 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
520@@ -142,8 +148,10 @@
521 static bool createTailIndices;
522 static bool createTailTextureCoords;
523
524- QVector<double> gastailVertexArr; // computed frequently, describes parabolic shape (along z axis) of gas tail.
525- QVector<double> dusttailVertexArr; // computed frequently, describes parabolic shape (along z axis) of dust tail.
526+ QVector<Vec3d> gastailVertexArr; // computed frequently, describes parabolic shape (along z axis) of gas tail.
527+ QVector<Vec3d> dusttailVertexArr; // computed frequently, describes parabolic shape (along z axis) of dust tail.
528+ QVector<Vec3f> gastailColorArr; // NEW computed for every 5 mins, modulates gas tail brightness for extinction
529+ QVector<Vec3f> dusttailColorArr; // NEW computed for every 5 mins, modulates dust tail brightness for extinction
530 static QVector<float> tailTexCoordArr; // computed only once for all comets!
531 static QVector<unsigned short> tailIndices; // computed only once for all comets!
532 static StelTextureSP comaTexture;
533
534=== modified file 'src/core/modules/MilkyWay.cpp'
535--- src/core/modules/MilkyWay.cpp 2014-10-27 22:40:49 +0000
536+++ src/core/modules/MilkyWay.cpp 2014-11-08 17:16:48 +0000
537@@ -128,7 +128,7 @@
538 for (int i=0; i<vertexArray->vertex.size(); ++i)
539 {
540 Vec3d vertAltAz=core->j2000ToAltAz(vertexArray->vertex.at(i), StelCore::RefractionOn);
541- Q_ASSERT(vertAltAz.lengthSquared()-1.0 < 0.001f);
542+ Q_ASSERT(fabs(vertAltAz.lengthSquared()-1.0) < 0.001);
543
544 float oneMag=0.0f;
545 extinction.forward(vertAltAz, &oneMag);
546
547=== modified file 'src/core/modules/MinorPlanet.cpp'
548--- src/core/modules/MinorPlanet.cpp 2014-08-31 10:34:41 +0000
549+++ src/core/modules/MinorPlanet.cpp 2014-11-08 17:16:48 +0000
550@@ -293,7 +293,6 @@
551 //Calculate phase angle
552 //(Code copied from Planet::getVMagnitude())
553 //(this is actually vector subtraction + the cosine theorem :))
554- // GZ Try now in float... speed difference is negligible, though.
555 const Vec3d& observerHelioPos = core->getObserverHeliocentricEclipticPos();
556 const float observerRq = observerHelioPos.lengthSquared();
557 const Vec3d& planetHelioPos = getHeliocentricEclipticPos();
558
559=== modified file 'src/core/modules/Planet.cpp'
560--- src/core/modules/Planet.cpp 2014-11-05 14:49:44 +0000
561+++ src/core/modules/Planet.cpp 2014-11-08 17:16:48 +0000
562@@ -679,7 +679,7 @@
563 double Planet::computeDistance(const Vec3d& obsHelioPos)
564 {
565 distance = (obsHelioPos-getHeliocentricEclipticPos()).length();
566- // GZ: improve fps by juggling updates for asteroids. They must be fast if close to observer, but can be slow if further away.
567+ // improve fps by juggling updates for asteroids. They must be fast if close to observer, but can be slow if further away.
568 if (pType == Planet::isAsteroid)
569 deltaJD=distance*StelCore::JD_SECOND;
570 return distance;
571@@ -928,11 +928,11 @@
572 {
573 if (hidden)
574 return;
575- // GZ: Try to improve speed for minor planets: test if visible at all.
576+ // Try to improve speed for minor planets: test if visible at all.
577 // For a full catalog of NEAs (11000 objects), with this and resetting deltaJD according to distance, rendering time went 4.5fps->12fps.
578- // AW: Apply this rule to asteroids only
579- // Note that taking away the asteroids at this stage breaks dim-asteroid occultation of stars!
580- if (((getVMagnitude(core)-1.0f) > core->getSkyDrawer()->getLimitMagnitude()) && pType==Planet::isAsteroid)
581+ // TBD: Note that taking away the asteroids at this stage breaks dim-asteroid occultation of stars!
582+ // Maybe make another configurable flag for those interested?
583+ if (((getVMagnitude(core)+1.0f) > core->getSkyDrawer()->getLimitMagnitude()) && pType==Planet::isAsteroid)
584 {
585 return;
586 }
587
588=== modified file 'src/core/modules/Planet.hpp'
589--- src/core/modules/Planet.hpp 2014-11-01 15:03:47 +0000
590+++ src/core/modules/Planet.hpp 2014-11-08 17:16:48 +0000
591@@ -192,7 +192,8 @@
592
593 // Compute the position in the parent Planet coordinate system
594 void computePositionWithoutOrbits(const double dateJD);
595- virtual void computePosition(const double dateJD);// GZ: gets overridden in Comet!
596+ //virtual void computePosition(const double dateJD);// GZ: gets overridden in Comet!
597+ void computePosition(const double dateJD);// GZ: gets overridden in Comet!
598
599 // Compute the transformation matrix from the local Planet coordinate to the parent Planet coordinate
600 void computeTransMatrix(double date);
601@@ -237,8 +238,8 @@
602 static void setLabelColor(const Vec3f& lc) {labelColor = lc;}
603 static const Vec3f& getLabelColor(void) {return labelColor;}
604
605- // update displayed elements. @param deltaTime: ms (?)
606- void update(int deltaTime);
607+ // update displayed elements. @param deltaTime: ms (since last call)
608+ virtual void update(int deltaTime);
609
610 void setFlagHints(bool b){hintFader = b;}
611 bool getFlagHints(void) const {return hintFader;}