Stellarium 0.12.4
StelProjectorClasses.hpp
1 /*
2  * Stellarium
3  * Copyright (C) 2008 Stellarium Developers
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 
20 #ifndef _STELPROJECTIONS_HPP_
21 #define _STELPROJECTIONS_HPP_
22 
23 #include <limits>
24 #include "StelProjector.hpp"
25 #include "StelSphereGeometry.hpp"
26 #include "renderer/StelGLSLShader.hpp"
27 
29 {
30 public:
32  virtual QString getNameI18() const;
33  virtual QString getDescriptionI18() const;
34  virtual float getMaxFov() const {return 120.f;}
35  bool forward(Vec3f &v) const
36  {
37  const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
38  if (v[2] < 0) {
39  v[0] /= (-v[2]);
40  v[1] /= (-v[2]);
41  v[2] = r;
42  return true;
43  }
44  if (v[2] > 0) {
45  v[0] /= v[2];
46  v[1] /= v[2];
47  v[2] = r;
48  return false;
49  }
50  v[0] = std::numeric_limits<float>::max();
51  v[1] = std::numeric_limits<float>::max();
52  v[2] = r;
53  return false;
54  }
55  bool backward(Vec3d &v) const;
56  float fovToViewScalingFactor(float fov) const;
57  float viewScalingFactorToFov(float vsf) const;
58  float deltaZoom(float fov) const;
59 protected:
60  virtual bool hasDiscontinuity() const {return false;}
61  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
62  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
63 };
64 
66 {
67 public:
69  virtual QString getNameI18() const;
70  virtual QString getDescriptionI18() const;
71  virtual float getMaxFov() const {return 360.f;}
72  bool forward(Vec3f &v) const
73  {
74  const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
75  const float f = std::sqrt(2.f/(r*(r-v[2])));
76  v[0] *= f;
77  v[1] *= f;
78  v[2] = r;
79  return true;
80  }
81  bool backward(Vec3d &v) const;
82  float fovToViewScalingFactor(float fov) const;
83  float viewScalingFactorToFov(float vsf) const;
84  float deltaZoom(float fov) const;
85 protected:
86  virtual bool hasDiscontinuity() const {return false;}
87  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
88  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
89 };
90 
92 {
93  friend class StereographicGLSLProjectorShader;
94 private:
100  class StereographicGLSLProjector : public StelProjector::GLSLProjector
101  {
102  friend class StelProjectorStereographic;
103  StelProjectorStereographic& projector;
104 
105  public:
106  virtual bool init(StelGLSLShader* shader)
107  {
108  if(projector.disableShaderProjection)
109  {
110  return false;
111  }
112 
113  shader->unlock();
114 
115  // Add (or enable, if already added) shader for the used modelview transform.
116  // Not all ModelViewTranforms have GLSL implementations (e.g. Refraction)
117  if(!projector.modelViewTransform->setupGLSLTransform(shader))
118  {
119  // Failed to add the transform shader, return the shader into locked state.
120  if(!shader->build())
121  {
122  Q_ASSERT_X(false, Q_FUNC_INFO,
123  "Failed to restore shader after failing to add a modelview "
124  "transform shader to it");
125  }
126  return false;
127  }
128 
129  // Add the stereographic projector shader if not yet added.
130  if(!shader->hasVertexShader("StereographicProjector"))
131  {
132  static const QString projectorSource(
133  "vec4 modelViewForward(in vec4 v);\n"
134  "\n"
135  "uniform vec2 viewportCenter;\n"
136  "uniform float flipHorz;\n"
137  "uniform float flipVert;\n"
138  "uniform float pixelPerRad;\n"
139  "uniform float zNear;\n"
140  "uniform float oneOverZNearMinusZFar;\n"
141  "\n"
142  "vec4 projectorForward(in vec4 v)\n"
143  "{\n"
144  " float r = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n"
145  " float h = 0.5 * (r - v.z);\n"
146  " if (h <= 0.0) \n"
147  " {\n"
148  " return vec4(1000000.0, 1000000.0, -1000000.0, 1.0);\n"
149  " }\n"
150  " float f = 1.0 / h;\n"
151  " return vec4(v.x * f, v.y * f, r, 1.0);\n"
152  "}\n"
153  "\n"
154  "vec4 project(in vec4 posIn)\n"
155  "{\n"
156  " vec4 v = posIn;\n"
157  " v = modelViewForward(v);\n"
158  " v = projectorForward(v);\n"
159  " return vec4(viewportCenter.x + flipHorz * pixelPerRad * v.x,\n"
160  " viewportCenter.y + flipVert * pixelPerRad * v.y,\n"
161  " (v.z - zNear) * oneOverZNearMinusZFar, 1.0);\n"
162  "}\n");
163 
164  if(!shader->addVertexShader("StereographicProjector", projectorSource))
165  {
166  // Failed to add the projector shader, return the shader into locked state.
167  if(!shader->build())
168  {
169  Q_ASSERT_X(false, Q_FUNC_INFO,
170  "Failed to restore shader after failing to add a stereographic "
171  "projector shader to it");
172  }
173  projector.disableShaderProjection = true;
174  return false;
175  }
176  qDebug() << "Build log after adding a stereographic projection shader: "
177  << shader->log();
178  }
179 
180  shader->disableVertexShader("DefaultProjector");
181  shader->enableVertexShader("StereographicProjector");
182  if(!shader->build())
183  {
184  qDebug() << "Failed to build with a stereographic projector shader: "
185  << shader->log();
186  projector.disableShaderProjection = true;
187  shader->enableVertexShader("DefaultProjector");
188  shader->disableVertexShader("StereographicProjector");
189  if(!shader->build())
190  {
191  Q_ASSERT_X(false, Q_FUNC_INFO,
192  "Failed to restore default projector shader after failing to link "
193  "with a (succesfully compiled) stereographic projector shader");
194  }
195 
196  }
197  return true;
198  }
199 
200  virtual void preDraw(StelGLSLShader* shader)
201  {
202  projector.modelViewTransform->setGLSLUniforms(shader);
203 
204  shader->setUniformValue("viewportCenter", projector.viewportCenter);
205  shader->setUniformValue("flipHorz", projector.flipHorz);
206  shader->setUniformValue("flipVert", projector.flipVert);
207  shader->setUniformValue("pixelPerRad", projector.pixelPerRad);
208  shader->setUniformValue("zNear", projector.zNear);
209  shader->setUniformValue("oneOverZNearMinusZFar", projector.oneOverZNearMinusZFar);
210  }
211 
212  virtual void postDraw(StelGLSLShader* shader)
213  {
214  shader->unlock();
215  projector.modelViewTransform->disableGLSLTransform(shader);
216  shader->disableVertexShader("StereographicProjector");
217  shader->enableVertexShader("DefaultProjector");
218  if(!shader->build())
219  {
220  Q_ASSERT_X(false, Q_FUNC_INFO, "Failed to disable projector shader");
221  }
222  }
223 
224  private:
226  StereographicGLSLProjector(StelProjectorStereographic& projector)
227  : projector(projector)
228  {
229  }
230  };
231 
232 public:
234  : StelProjector(func)
235  , glslProjector(*this)
236  {;}
237  virtual QString getNameI18() const;
238  virtual QString getDescriptionI18() const;
239  virtual float getMaxFov() const {return 235.f;}
240  bool forward(Vec3f &v) const
241  {
242  const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
243  const float h = 0.5f*(r-v[2]);
244  if (h <= 0.f) {
245  v[0] = std::numeric_limits<float>::max();
246  v[1] = std::numeric_limits<float>::max();
247  v[2] = -std::numeric_limits<float>::min();
248  return false;
249  }
250  const float f = 1.f / h;
251  v[0] *= f;
252  v[1] *= f;
253  v[2] = r;
254  return true;
255  }
256 
257  virtual void project(int n, const Vec3d* in, Vec3f* out)
258  {
259  Vec3d v;
260  for (int i = 0; i < n; ++i, ++out)
261  {
262  v = in[i];
263  modelViewTransform->forward(v);
264  out->set(v[0], v[1], v[2]);
266  out->set(viewportCenter[0] + flipHorz * pixelPerRad * (*out)[0],
267  viewportCenter[1] + flipVert * pixelPerRad * (*out)[1],
268  ((*out)[2] - zNear) * oneOverZNearMinusZFar);
269  }
270  }
271 
273  {
274  return &glslProjector;
275  }
276 
277  bool backward(Vec3d &v) const;
278  float fovToViewScalingFactor(float fov) const;
279  float viewScalingFactorToFov(float vsf) const;
280  float deltaZoom(float fov) const;
281 protected:
282  virtual bool hasDiscontinuity() const {return false;}
283  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
284  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
285 
286 private:
288  StereographicGLSLProjector glslProjector;
289 };
290 
292 {
293 public:
295  virtual QString getNameI18() const;
296  virtual QString getDescriptionI18() const;
297  virtual float getMaxFov() const {return 180.00001f;}
298  bool forward(Vec3f &v) const
299  {
300  const float rq1 = v[0]*v[0] + v[1]*v[1];
301  if (rq1 > 0.f) {
302  const float h = std::sqrt(rq1);
303  const float f = std::atan2(h,-v[2]) / h;
304  v[0] *= f;
305  v[1] *= f;
306  v[2] = std::sqrt(rq1 + v[2]*v[2]);
307  return true;
308  }
309  if (v[2] < 0.f) {
310  v[0] = 0.f;
311  v[1] = 0.f;
312  v[2] = 1.f;
313  return true;
314  }
315  v[0] = std::numeric_limits<float>::max();
316  v[1] = std::numeric_limits<float>::max();
317  v[2] = std::numeric_limits<float>::min();
318  return false;
319  }
320  bool backward(Vec3d &v) const;
321  float fovToViewScalingFactor(float fov) const;
322  float viewScalingFactorToFov(float vsf) const;
323  float deltaZoom(float fov) const;
324 protected:
325  virtual bool hasDiscontinuity() const {return false;}
326  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
327  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
328 };
329 
331 {
332 public:
334  virtual QString getNameI18() const;
335  virtual QString getDescriptionI18() const;
336  virtual float getMaxFov() const {return 360.f;}
337  virtual void project(int n, const Vec3d* in, Vec3f* out)
338  {
339  Vec3d v;
340  for (int i = 0; i < n; ++i)
341  {
342  v = in[i];
343  modelViewTransform->forward(v);
344  out[i].set(v[0], v[1], v[2]);
346  out[i][0] = viewportCenter[0] + flipHorz * pixelPerRad * out[i][0];
347  out[i][1] = viewportCenter[1] + flipVert * pixelPerRad * out[i][1];
348  out[i][2] = (out[i][2] - zNear) * oneOverZNearMinusZFar;
349  }
350  }
351  bool forward(Vec3f &v) const
352  {
353  // Hammer Aitoff
354  const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
355  const float alpha = std::atan2(v[0],-v[2]);
356  const float cosDelta = std::sqrt(1.f-v[1]*v[1]/(r*r));
357  float z = std::sqrt(1.+cosDelta*std::cos(alpha/2.f));
358  v[0] = 2.f*M_SQRT2*cosDelta*std::sin(alpha/2.f)/z;
359  v[1] = M_SQRT2*v[1]/r/z;
360  v[2] = r;
361  return true;
362  }
363  bool backward(Vec3d &v) const;
364  float fovToViewScalingFactor(float fov) const;
365  float viewScalingFactorToFov(float vsf) const;
366  float deltaZoom(float fov) const;
367 protected:
368  virtual bool hasDiscontinuity() const {return true;}
369  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const {return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);}
370  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
371  {
372  static const SphericalCap cap1(1,0,0);
373  static const SphericalCap cap2(-1,0,0);
374  static const SphericalCap cap3(0,0,-1);
375  SphericalCap cap(capN, capD);
376  return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
377  }
378 };
379 
381 {
382 public:
384  virtual QString getNameI18() const;
385  virtual QString getDescriptionI18() const;
386  virtual float getMaxFov() const {return 175.f * 4.f/3.f;} // assume aspect ration of 4/3 for getting a full 360 degree horizon
387  bool forward(Vec3f &win) const;
388  bool backward(Vec3d &v) const;
389  float fovToViewScalingFactor(float fov) const;
390  float viewScalingFactorToFov(float vsf) const;
391  float deltaZoom(float fov) const;
392 protected:
393  virtual bool hasDiscontinuity() const {return true;}
394  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const
395  {
396  return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);
397  }
398  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
399  {
400  static const SphericalCap cap1(1,0,0);
401  static const SphericalCap cap2(-1,0,0);
402  static const SphericalCap cap3(0,0,-1);
403  SphericalCap cap(capN, capD);
404  return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
405  }
406 };
407 
409 {
410 public:
412  virtual QString getNameI18() const;
413  virtual QString getDescriptionI18() const;
414  virtual float getMaxFov() const {return 175.f * 4.f/3.f;} // assume aspect ration of 4/3 for getting a full 360 degree horizon
415  bool forward(Vec3f &win) const;
416  bool backward(Vec3d &v) const;
417  float fovToViewScalingFactor(float fov) const;
418  float viewScalingFactorToFov(float vsf) const;
419  float deltaZoom(float fov) const;
420 protected:
421  virtual bool hasDiscontinuity() const {return true;}
422  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const
423  {
424  return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);
425  }
426  virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
427  {
428  static const SphericalCap cap1(1,0,0);
429  static const SphericalCap cap2(-1,0,0);
430  static const SphericalCap cap3(0,0,-1);
431  SphericalCap cap(capN, capD);
432  return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
433  }
434 };
435 
437 {
438 public:
440  virtual QString getNameI18() const;
441  virtual QString getDescriptionI18() const;
442  virtual float getMaxFov() const {return 179.9999f;}
443  bool forward(Vec3f &win) const;
444  bool backward(Vec3d &v) const;
445  float fovToViewScalingFactor(float fov) const;
446  float viewScalingFactorToFov(float vsf) const;
447  float deltaZoom(float fov) const;
448 protected:
449  virtual bool hasDiscontinuity() const {return false;}
450  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
451  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
452 };
453 
455 {
456 public:
458  virtual QString getNameI18() const;
459  virtual QString getDescriptionI18() const;
460  virtual float getMaxFov() const {return 360.f;}
461  bool forward(Vec3f &win) const;
462  bool backward(Vec3d &v) const;
463  float fovToViewScalingFactor(float fov) const;
464  float viewScalingFactorToFov(float vsf) const;
465  float deltaZoom(float fov) const;
466 protected:
467  virtual bool hasDiscontinuity() const {return false;}
468  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {Q_ASSERT(0); return false;}
469  virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {Q_ASSERT(0); return false;}
470  virtual void computeBoundingCap() {;}
471 };
472 
473 #endif // _STELPROJECTIONS_HPP_
474