Stellarium 0.12.1
RefractionExtinction.hpp
1 /*
2  * Stellarium
3  * Copyright (C) 2010 Fabien Chereau
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  *
19  * Refraction and extinction computations.
20  * Implementation: 2010-03-23 GZ=Georg Zotti, Georg.Zotti@univie.ac.at
21  * 2010-12 FC split into 2 classes, implemented Refraction */
22 
23 #ifndef _REFRACTIONEXTINCTION_HPP_
24 #define _REFRACTIONEXTINCTION_HPP_
25 // USABILITY: added 3 more flags/switches in GUI:
26 // Temperature [C] [influences refraction]
27 // Pressure [mbar] [influences refraction]
28 // extinction Coeff. k=0...(0.01)...1, [if k=0, no ext. effect]
29 // SUGGESTION: Allow Temperature/Pressure/ex.Coeff./LightPollution set in the landscape files
30 
31 #include "VecMath.hpp"
32 #include "StelProjector.hpp"
33 
46 {
47 public:
48  Extinction();
54  void forward(const Vec3d *altAzPos, float *mag, const int num=1) const;
55  void forward(const Vec3f *altAzPos, float *mag, const int num=1) const;
56  void forward(const double *sinAlt, float *mag, const int num) const;
57  void forward(const float *sinAlt, float *mag, const int num) const;
58  void forward(const double *sinAlt, float *mag) const;
59  void forward(const float *sinAlt, float *mag) const;
60 
65  void backward(const Vec3d *altAzPos, float *mag, const int num=1) const;
66  void backward(const Vec3f *altAzPos, float *mag, const int num=1) const;
67  void backward(const double *sinAlt, float *mag, const int num=1) const;
68  void backward(const float *sinAlt, float *mag, const int num=1) const;
69 
72  void setExtinctionCoefficient(float k) { ext_coeff=k; }
73  float getExtinctionCoefficient() const {return ext_coeff;}
74 
75 private:
83  float airmass(const float cosZ, const bool apparent_z=true) const;
84 
86  float ext_coeff;
89  static float SUBHORIZONTAL_AIRMASS;
90 };
91 
101 
103 {
104 public:
105  Refraction();
106 
110  virtual void forward(Vec3d& altAzPos) const;
111 
115  virtual void backward(Vec3d& altAzPos) const;
116 
120  virtual void forward(Vec3f& altAzPos) const;
121 
125  virtual void backward(Vec3f& altAzPos) const;
126 
127  virtual void combine(const Mat4d& m)
128  {
129  setPreTransfoMat(preTransfoMat*m);
130  }
131 
132  virtual Mat4d getApproximateLinearTransfo() const {return postTransfoMat*preTransfoMat;}
133 
134  virtual StelProjector::ModelViewTranformP clone() const {Refraction* refr = new Refraction(); *refr=*this; return StelProjector::ModelViewTranformP(refr);}
135 
136  virtual bool setupGLSLTransform(StelGLSLShader* shader)
137  {
138  Q_UNUSED(shader);
139  return false;
140 
141  // GL-REFACTOR:
142  //
143  // I reimplemented the forward() member function in GLSL, but the result is
144  // not usable at the moment.
145  //
146  // On Intel drivers, the projection gets completely messed up.
147  // On AMD, most of the time, the coordinates are projected in slightly
148  // different locations (e.g. a planet is slightly above/below where it's
149  // supposed to be), and there is very nasty jitter on the individual vertex
150  // positions.
151  // NVidia behaves the same, _and_ the viewport borders are messed up.
152  //
153  //
154  // The most likely cause of the problem is the imprecision of GLSL
155  // sin, asin and tan (which AFAIK are implemented through low-resolution
156  // lookup tables in hardware).
157  //
158  // However, it is also possible that I incorrectly translated forward() to
159  // GLSL.
160  //
161  //
162  // Different possible ways to implement refraction in GLSL would be
163  // to use custom, higher-resolution lookup tables (textures), or to use
164  // a different, maybe simpler (less trig) algorithm for refraction.
165 
166  // if(!shader->hasVertexShader("RefractionTransform"))
167  // {
168  // static const QString source(
169  // "uniform mat4 preTransfoMat;\n"
170  // "uniform mat4 postTransfoMat;\n"
171  // "uniform float press_temp_corr_Saemundson;\n"
172  // "// These values must match the C++ code.\n"
173  // "const float MIN_GEO_ALTITUDE_DEG = -3.54;\n"
174  // "const float TRANSITION_WIDTH_GEO_DEG = 1.46;\n"
175  // "\n"
176  // "vec4 modelViewForward(in vec4 altAzPos)\n"
177  // "{\n"
178  // " vec4 localAltAzPos = preTransfoMat * altAzPos;\n"
179  // " float len = length(localAltAzPos.xyz);\n"
180  // " float geom_alt_deg = degrees(asin(localAltAzPos.z / len));\n"
181  // " if(geom_alt_deg > MIN_GEO_ALTITUDE_DEG)\n"
182  // " {\n"
183  // " // refraction from Saemundsson, S&T1986 p70 / in Meeus, Astr.Alg.\n"
184  // " float r = press_temp_corr_Saemundson / \n"
185  // " tan(radians(geom_alt_deg + 10.3 / (geom_alt_deg + 5.11))) + 0.0019279;\n"
186  // " geom_alt_deg += r;\n"
187  // " geom_alt_deg = min(geom_alt_deg, 90.0); // SAFETY\n"
188  // " localAltAzPos.z = sin(radians(geom_alt_deg)) * len;\n"
189  // " }\n"
190  // " else if(geom_alt_deg > (MIN_GEO_ALTITUDE_DEG - TRANSITION_WIDTH_GEO_DEG))\n"
191  // " {\n"
192  // " // Avoids the jump below -5 by interpolating linearly between\n"
193  // " // MIN_GEO_ALTITUDE_DEG and bottom of transition zone\n"
194  // " float r_m5 = press_temp_corr_Saemundson / \n"
195  // " tan(radians(MIN_GEO_ALTITUDE_DEG + 10.3 / (MIN_GEO_ALTITUDE_DEG + 5.11)))\n"
196  // " + 0.0019279;\n"
197  // " geom_alt_deg += r_m5 * \n"
198  // " (geom_alt_deg - (MIN_GEO_ALTITUDE_DEG - TRANSITION_WIDTH_GEO_DEG)) /\n"
199  // " TRANSITION_WIDTH_GEO_DEG;\n"
200  // " localAltAzPos.z = sin(radians(geom_alt_deg)) * len;\n"
201  // " }\n"
202  // " return postTransfoMat * localAltAzPos;\n"
203  // "}\n");
204 
205  // if(!shader->addVertexShader("RefractionTransform", source))
206  // {
207  // return false;
208  // }
209  // qDebug() << "Build log after adding a refraction shader: " << shader->log();
210  // }
211  // shader->enableVertexShader("RefractionTransform");
212  // return true;
213  }
214 
215  virtual void setGLSLUniforms(StelGLSLShader* shader)
216  {
217  Q_UNUSED(shader);
218  // shader->setUniformValue("preTransfoMat", preTransfoMatf);
219  // shader->setUniformValue("postTransfoMat", postTransfoMatf);
220  // shader->setUniformValue("press_temp_corr_Saemundson", press_temp_corr_Saemundson);
221  }
222 
223  virtual void disableGLSLTransform(StelGLSLShader* shader)
224  {
225  Q_UNUSED(shader);
226  // shader->disableVertexShader("RefractionTransform");
227  }
228 
230  void setPressure(float p_mbar);
231  float getPressure() const {return pressure;}
232 
234  void setTemperature(float t_C);
235  float getTemperature() const {return temperature;}
236 
238  void setPreTransfoMat(const Mat4d& m);
239  void setPostTransfoMat(const Mat4d& m);
240 
241 private:
243  void updatePrecomputed();
244 
247  float pressure;
249  float temperature;
251  float press_temp_corr_Saemundson;
253  float press_temp_corr_Bennett;
254 
256  static const double MIN_GEO_ALTITUDE_DEG;
257  static const double MIN_GEO_ALTITUDE_RAD;
258  static const double MIN_GEO_ALTITUDE_SIN;
259  static const double MIN_APP_ALTITUDE_DEG;
260  static const double MIN_APP_ALTITUDE_RAD;
261  static const double MIN_APP_ALTITUDE_SIN;
262  static const float MIN_GEO_ALTITUDE_DEG_F;
263  static const float MIN_GEO_ALTITUDE_RAD_F;
264  static const float MIN_GEO_ALTITUDE_SIN_F;
265  static const float MIN_APP_ALTITUDE_DEG_F;
266  static const float MIN_APP_ALTITUDE_RAD_F;
267  static const float MIN_APP_ALTITUDE_SIN_F;
268  static const double TRANSITION_WIDTH_GEO_DEG;
269  static const double TRANSITION_WIDTH_GEO_DEG_F;
270  static const double TRANSITION_WIDTH_APP_DEG;
271  static const double TRANSITION_WIDTH_APP_DEG_F;
272 
274  Mat4d preTransfoMat;
275  Mat4d invertPreTransfoMat;
276  Mat4f preTransfoMatf;
277  Mat4f invertPreTransfoMatf;
278 
280  Mat4d postTransfoMat;
281  Mat4d invertPostTransfoMat;
282  Mat4f postTransfoMatf;
283  Mat4f invertPostTransfoMatf;
284 };
285 
286 #endif // _REFRACTIONEXTINCTION_HPP_