Stellarium 0.12.0
Home · All Namespaces · All Classes · Functions · Coding Style · Scripting · Plugins · Renderer · File Structure

StelProjectorClasses.hpp

00001 /*
00002  * Stellarium
00003  * Copyright (C) 2008 Stellarium Developers
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
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             // Add (or enable, if already added) shader for the used modelview transform.
00116             // Not all ModelViewTranforms have GLSL implementations (e.g. Refraction)
00117             if(!projector.modelViewTransform->setupGLSLTransform(shader))
00118             {
00119                 // Failed to add the transform shader, return the shader into locked state.
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             // Add the stereographic projector shader if not yet added.
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                     // Failed to add the projector shader, return the shader into locked state.
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         // Hammer Aitoff
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;} // assume aspect ration of 4/3 for getting a full 360 degree horizon
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;} // assume aspect ration of 4/3 for getting a full 360 degree horizon
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 
Generated on Thu Jan 31 14:05:40 2013 for Stellarium by  doxygen 1.6.3