00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _STELPROJECTIONS_HPP_
00021 #define _STELPROJECTIONS_HPP_
00022
00023 #include <limits>
00024 #include "StelProjector.hpp"
00025 #include "StelSphereGeometry.hpp"
00026 #include "renderer/StelGLSLShader.hpp"
00027
00028 class StelProjectorPerspective : public StelProjector
00029 {
00030 public:
00031 StelProjectorPerspective(ModelViewTranformP func) : StelProjector(func) {;}
00032 virtual QString getNameI18() const;
00033 virtual QString getDescriptionI18() const;
00034 virtual float getMaxFov() const {return 120.f;}
00035 bool forward(Vec3f &v) const
00036 {
00037 const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00038 if (v[2] < 0) {
00039 v[0] /= (-v[2]);
00040 v[1] /= (-v[2]);
00041 v[2] = r;
00042 return true;
00043 }
00044 if (v[2] > 0) {
00045 v[0] /= v[2];
00046 v[1] /= v[2];
00047 v[2] = r;
00048 return false;
00049 }
00050 v[0] = std::numeric_limits<float>::max();
00051 v[1] = std::numeric_limits<float>::max();
00052 v[2] = r;
00053 return false;
00054 }
00055 bool backward(Vec3d &v) const;
00056 float fovToViewScalingFactor(float fov) const;
00057 float viewScalingFactorToFov(float vsf) const;
00058 float deltaZoom(float fov) const;
00059 protected:
00060 virtual bool hasDiscontinuity() const {return false;}
00061 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
00062 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
00063 };
00064
00065 class StelProjectorEqualArea : public StelProjector
00066 {
00067 public:
00068 StelProjectorEqualArea(ModelViewTranformP func) : StelProjector(func) {;}
00069 virtual QString getNameI18() const;
00070 virtual QString getDescriptionI18() const;
00071 virtual float getMaxFov() const {return 360.f;}
00072 bool forward(Vec3f &v) const
00073 {
00074 const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00075 const float f = std::sqrt(2.f/(r*(r-v[2])));
00076 v[0] *= f;
00077 v[1] *= f;
00078 v[2] = r;
00079 return true;
00080 }
00081 bool backward(Vec3d &v) const;
00082 float fovToViewScalingFactor(float fov) const;
00083 float viewScalingFactorToFov(float vsf) const;
00084 float deltaZoom(float fov) const;
00085 protected:
00086 virtual bool hasDiscontinuity() const {return false;}
00087 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
00088 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
00089 };
00090
00091 class StelProjectorStereographic : public StelProjector
00092 {
00093 friend class StereographicGLSLProjectorShader;
00094 private:
00100 class StereographicGLSLProjector : public StelProjector::GLSLProjector
00101 {
00102 friend class StelProjectorStereographic;
00103 StelProjectorStereographic& projector;
00104
00105 public:
00106 virtual bool init(StelGLSLShader* shader)
00107 {
00108 if(projector.disableShaderProjection)
00109 {
00110 return false;
00111 }
00112
00113 shader->unlock();
00114
00115
00116
00117 if(!projector.modelViewTransform->setupGLSLTransform(shader))
00118 {
00119
00120 if(!shader->build())
00121 {
00122 Q_ASSERT_X(false, Q_FUNC_INFO,
00123 "Failed to restore shader after failing to add a modelview "
00124 "transform shader to it");
00125 }
00126 return false;
00127 }
00128
00129
00130 if(!shader->hasVertexShader("StereographicProjector"))
00131 {
00132 static const QString projectorSource(
00133 "vec4 modelViewForward(in vec4 v);\n"
00134 "\n"
00135 "uniform vec2 viewportCenter;\n"
00136 "uniform float flipHorz;\n"
00137 "uniform float flipVert;\n"
00138 "uniform float pixelPerRad;\n"
00139 "uniform float zNear;\n"
00140 "uniform float oneOverZNearMinusZFar;\n"
00141 "\n"
00142 "vec4 projectorForward(in vec4 v)\n"
00143 "{\n"
00144 " float r = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n"
00145 " float h = 0.5 * (r - v.z);\n"
00146 " if (h <= 0.0) \n"
00147 " {\n"
00148 " return vec4(1000000.0, 1000000.0, -1000000.0, 1.0);\n"
00149 " }\n"
00150 " float f = 1.0 / h;\n"
00151 " return vec4(v.x * f, v.y * f, r, 1.0);\n"
00152 "}\n"
00153 "\n"
00154 "vec4 project(in vec4 posIn)\n"
00155 "{\n"
00156 " vec4 v = posIn;\n"
00157 " v = modelViewForward(v);\n"
00158 " v = projectorForward(v);\n"
00159 " return vec4(viewportCenter.x + flipHorz * pixelPerRad * v.x,\n"
00160 " viewportCenter.y + flipVert * pixelPerRad * v.y,\n"
00161 " (v.z - zNear) * oneOverZNearMinusZFar, 1.0);\n"
00162 "}\n");
00163
00164 if(!shader->addVertexShader("StereographicProjector", projectorSource))
00165 {
00166
00167 if(!shader->build())
00168 {
00169 Q_ASSERT_X(false, Q_FUNC_INFO,
00170 "Failed to restore shader after failing to add a stereographic "
00171 "projector shader to it");
00172 }
00173 projector.disableShaderProjection = true;
00174 return false;
00175 }
00176 qDebug() << "Build log after adding a stereographic projection shader: "
00177 << shader->log();
00178 }
00179
00180 shader->disableVertexShader("DefaultProjector");
00181 shader->enableVertexShader("StereographicProjector");
00182 if(!shader->build())
00183 {
00184 qDebug() << "Failed to build with a stereographic projector shader: "
00185 << shader->log();
00186 projector.disableShaderProjection = true;
00187 shader->enableVertexShader("DefaultProjector");
00188 shader->disableVertexShader("StereographicProjector");
00189 if(!shader->build())
00190 {
00191 Q_ASSERT_X(false, Q_FUNC_INFO,
00192 "Failed to restore default projector shader after failing to link "
00193 "with a (succesfully compiled) stereographic projector shader");
00194 }
00195
00196 }
00197 return true;
00198 }
00199
00200 virtual void preDraw(StelGLSLShader* shader)
00201 {
00202 projector.modelViewTransform->setGLSLUniforms(shader);
00203
00204 shader->setUniformValue("viewportCenter", projector.viewportCenter);
00205 shader->setUniformValue("flipHorz", projector.flipHorz);
00206 shader->setUniformValue("flipVert", projector.flipVert);
00207 shader->setUniformValue("pixelPerRad", projector.pixelPerRad);
00208 shader->setUniformValue("zNear", projector.zNear);
00209 shader->setUniformValue("oneOverZNearMinusZFar", projector.oneOverZNearMinusZFar);
00210 }
00211
00212 virtual void postDraw(StelGLSLShader* shader)
00213 {
00214 shader->unlock();
00215 projector.modelViewTransform->disableGLSLTransform(shader);
00216 shader->disableVertexShader("StereographicProjector");
00217 shader->enableVertexShader("DefaultProjector");
00218 if(!shader->build())
00219 {
00220 Q_ASSERT_X(false, Q_FUNC_INFO, "Failed to disable projector shader");
00221 }
00222 }
00223
00224 private:
00226 StereographicGLSLProjector(StelProjectorStereographic& projector)
00227 : projector(projector)
00228 {
00229 }
00230 };
00231
00232 public:
00233 StelProjectorStereographic(ModelViewTranformP func)
00234 : StelProjector(func)
00235 , glslProjector(*this)
00236 {;}
00237 virtual QString getNameI18() const;
00238 virtual QString getDescriptionI18() const;
00239 virtual float getMaxFov() const {return 235.f;}
00240 bool forward(Vec3f &v) const
00241 {
00242 const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00243 const float h = 0.5f*(r-v[2]);
00244 if (h <= 0.f) {
00245 v[0] = std::numeric_limits<float>::max();
00246 v[1] = std::numeric_limits<float>::max();
00247 v[2] = -std::numeric_limits<float>::min();
00248 return false;
00249 }
00250 const float f = 1.f / h;
00251 v[0] *= f;
00252 v[1] *= f;
00253 v[2] = r;
00254 return true;
00255 }
00256
00257 virtual void project(int n, const Vec3d* in, Vec3f* out)
00258 {
00259 Vec3d v;
00260 for (int i = 0; i < n; ++i, ++out)
00261 {
00262 v = in[i];
00263 modelViewTransform->forward(v);
00264 out->set(v[0], v[1], v[2]);
00265 StelProjectorStereographic::forward(*out);
00266 out->set(viewportCenter[0] + flipHorz * pixelPerRad * (*out)[0],
00267 viewportCenter[1] + flipVert * pixelPerRad * (*out)[1],
00268 ((*out)[2] - zNear) * oneOverZNearMinusZFar);
00269 }
00270 }
00271
00272 virtual GLSLProjector* getGLSLProjector()
00273 {
00274 return &glslProjector;
00275 }
00276
00277 bool backward(Vec3d &v) const;
00278 float fovToViewScalingFactor(float fov) const;
00279 float viewScalingFactorToFov(float vsf) const;
00280 float deltaZoom(float fov) const;
00281 protected:
00282 virtual bool hasDiscontinuity() const {return false;}
00283 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
00284 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
00285
00286 private:
00288 StereographicGLSLProjector glslProjector;
00289 };
00290
00291 class StelProjectorFisheye : public StelProjector
00292 {
00293 public:
00294 StelProjectorFisheye(ModelViewTranformP func) : StelProjector(func) {;}
00295 virtual QString getNameI18() const;
00296 virtual QString getDescriptionI18() const;
00297 virtual float getMaxFov() const {return 180.00001f;}
00298 bool forward(Vec3f &v) const
00299 {
00300 const float rq1 = v[0]*v[0] + v[1]*v[1];
00301 if (rq1 > 0.f) {
00302 const float h = std::sqrt(rq1);
00303 const float f = std::atan2(h,-v[2]) / h;
00304 v[0] *= f;
00305 v[1] *= f;
00306 v[2] = std::sqrt(rq1 + v[2]*v[2]);
00307 return true;
00308 }
00309 if (v[2] < 0.f) {
00310 v[0] = 0.f;
00311 v[1] = 0.f;
00312 v[2] = 1.f;
00313 return true;
00314 }
00315 v[0] = std::numeric_limits<float>::max();
00316 v[1] = std::numeric_limits<float>::max();
00317 v[2] = std::numeric_limits<float>::min();
00318 return false;
00319 }
00320 bool backward(Vec3d &v) const;
00321 float fovToViewScalingFactor(float fov) const;
00322 float viewScalingFactorToFov(float vsf) const;
00323 float deltaZoom(float fov) const;
00324 protected:
00325 virtual bool hasDiscontinuity() const {return false;}
00326 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
00327 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
00328 };
00329
00330 class StelProjectorHammer : public StelProjector
00331 {
00332 public:
00333 StelProjectorHammer(ModelViewTranformP func) : StelProjector(func) {;}
00334 virtual QString getNameI18() const;
00335 virtual QString getDescriptionI18() const;
00336 virtual float getMaxFov() const {return 360.f;}
00337 virtual void project(int n, const Vec3d* in, Vec3f* out)
00338 {
00339 Vec3d v;
00340 for (int i = 0; i < n; ++i)
00341 {
00342 v = in[i];
00343 modelViewTransform->forward(v);
00344 out[i].set(v[0], v[1], v[2]);
00345 StelProjectorHammer::forward(out[i]);
00346 out[i][0] = viewportCenter[0] + flipHorz * pixelPerRad * out[i][0];
00347 out[i][1] = viewportCenter[1] + flipVert * pixelPerRad * out[i][1];
00348 out[i][2] = (out[i][2] - zNear) * oneOverZNearMinusZFar;
00349 }
00350 }
00351 bool forward(Vec3f &v) const
00352 {
00353
00354 const float r = std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00355 const float alpha = std::atan2(v[0],-v[2]);
00356 const float cosDelta = std::sqrt(1.f-v[1]*v[1]/(r*r));
00357 float z = std::sqrt(1.+cosDelta*std::cos(alpha/2.f));
00358 v[0] = 2.f*M_SQRT2*cosDelta*std::sin(alpha/2.f)/z;
00359 v[1] = M_SQRT2*v[1]/r/z;
00360 v[2] = r;
00361 return true;
00362 }
00363 bool backward(Vec3d &v) const;
00364 float fovToViewScalingFactor(float fov) const;
00365 float viewScalingFactorToFov(float vsf) const;
00366 float deltaZoom(float fov) const;
00367 protected:
00368 virtual bool hasDiscontinuity() const {return true;}
00369 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const {return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);}
00370 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
00371 {
00372 static const SphericalCap cap1(1,0,0);
00373 static const SphericalCap cap2(-1,0,0);
00374 static const SphericalCap cap3(0,0,-1);
00375 SphericalCap cap(capN, capD);
00376 return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
00377 }
00378 };
00379
00380 class StelProjectorCylinder : public StelProjector
00381 {
00382 public:
00383 StelProjectorCylinder(ModelViewTranformP func) : StelProjector(func) {;}
00384 virtual QString getNameI18() const;
00385 virtual QString getDescriptionI18() const;
00386 virtual float getMaxFov() const {return 175.f * 4.f/3.f;}
00387 bool forward(Vec3f &win) const;
00388 bool backward(Vec3d &v) const;
00389 float fovToViewScalingFactor(float fov) const;
00390 float viewScalingFactorToFov(float vsf) const;
00391 float deltaZoom(float fov) const;
00392 protected:
00393 virtual bool hasDiscontinuity() const {return true;}
00394 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const
00395 {
00396 return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);
00397 }
00398 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
00399 {
00400 static const SphericalCap cap1(1,0,0);
00401 static const SphericalCap cap2(-1,0,0);
00402 static const SphericalCap cap3(0,0,-1);
00403 SphericalCap cap(capN, capD);
00404 return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
00405 }
00406 };
00407
00408 class StelProjectorMercator : public StelProjector
00409 {
00410 public:
00411 StelProjectorMercator(ModelViewTranformP func) : StelProjector(func) {;}
00412 virtual QString getNameI18() const;
00413 virtual QString getDescriptionI18() const;
00414 virtual float getMaxFov() const {return 175.f * 4.f/3.f;}
00415 bool forward(Vec3f &win) const;
00416 bool backward(Vec3d &v) const;
00417 float fovToViewScalingFactor(float fov) const;
00418 float viewScalingFactorToFov(float vsf) const;
00419 float deltaZoom(float fov) const;
00420 protected:
00421 virtual bool hasDiscontinuity() const {return true;}
00422 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const
00423 {
00424 return p1[0]*p2[0]<0 && !(p1[2]<0 && p2[2]<0);
00425 }
00426 virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const
00427 {
00428 static const SphericalCap cap1(1,0,0);
00429 static const SphericalCap cap2(-1,0,0);
00430 static const SphericalCap cap3(0,0,-1);
00431 SphericalCap cap(capN, capD);
00432 return cap.intersects(cap1) && cap.intersects(cap2) && cap.intersects(cap2);
00433 }
00434 };
00435
00436 class StelProjectorOrthographic : public StelProjector
00437 {
00438 public:
00439 StelProjectorOrthographic(ModelViewTranformP func) : StelProjector(func) {;}
00440 virtual QString getNameI18() const;
00441 virtual QString getDescriptionI18() const;
00442 virtual float getMaxFov() const {return 179.9999f;}
00443 bool forward(Vec3f &win) const;
00444 bool backward(Vec3d &v) const;
00445 float fovToViewScalingFactor(float fov) const;
00446 float viewScalingFactorToFov(float vsf) const;
00447 float deltaZoom(float fov) const;
00448 protected:
00449 virtual bool hasDiscontinuity() const {return false;}
00450 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {return false;}
00451 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {return false;}
00452 };
00453
00454 class StelProjector2d : public StelProjector
00455 {
00456 public:
00457 StelProjector2d() : StelProjector(ModelViewTranformP(new StelProjector::Mat4dTransform(Mat4d::identity()))) {;}
00458 virtual QString getNameI18() const;
00459 virtual QString getDescriptionI18() const;
00460 virtual float getMaxFov() const {return 360.f;}
00461 bool forward(Vec3f &win) const;
00462 bool backward(Vec3d &v) const;
00463 float fovToViewScalingFactor(float fov) const;
00464 float viewScalingFactorToFov(float vsf) const;
00465 float deltaZoom(float fov) const;
00466 protected:
00467 virtual bool hasDiscontinuity() const {return false;}
00468 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, const Vec3d&) const {Q_ASSERT(0); return false;}
00469 virtual bool intersectViewportDiscontinuityInternal(const Vec3d&, double) const {Q_ASSERT(0); return false;}
00470 virtual void computeBoundingCap() {;}
00471 };
00472
00473 #endif // _STELPROJECTIONS_HPP_
00474