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

core/StelProjector.hpp

00001 /*
00002  * Stellarium
00003  * Copyright (C) 2003 Fabien Chereau
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018  */
00019 
00020 #ifndef _STELPROJECTOR_HPP_
00021 #define _STELPROJECTOR_HPP_
00022 
00023 #include "StelProjectorType.hpp"
00024 #include "VecMath.hpp"
00025 #include "StelSphereGeometry.hpp"
00026 
00034 class StelProjector
00035 {
00036 public:
00037     friend class StelPainter;
00038     friend class StelCore;
00039 
00040     class ModelViewTranform;
00043     typedef QSharedPointer<ModelViewTranform> ModelViewTranformP;
00044 
00047     class ModelViewTranform
00048     {
00049     public:
00050         ModelViewTranform() {;}
00051         virtual ~ModelViewTranform() {;}
00052         virtual void forward(Vec3d&) const =0;
00053         virtual void backward(Vec3d&) const =0;
00054         virtual void forward(Vec3f&) const =0;
00055         virtual void backward(Vec3f&) const =0;
00056 
00057         virtual void combine(const Mat4d&)=0;
00058         virtual ModelViewTranformP clone() const=0;
00059 
00060         virtual Mat4d getApproximateLinearTransfo() const=0;
00061     };
00062 
00063     class Mat4dTransform: public ModelViewTranform
00064     {
00065     public:
00066         Mat4dTransform(const Mat4d& m) : transfoMat(m),
00067             transfoMatf(m[0], m[1], m[2], m[3],
00068                              m[4], m[5], m[6], m[7],
00069                              m[8], m[9], m[10], m[11],
00070                              m[12], m[13], m[14], m[15]) {;}
00071 
00072         void forward(Vec3d& v) const {v.transfo4d(transfoMat);}
00073         void backward(Vec3d& v) const
00074         {
00075             // We need no matrix inversion because we always work with orthogonal matrices (where the transposed is the inverse).
00076             //v.transfo4d(inverseTransfoMat);
00077             const double x = v[0] - transfoMat.r[12];
00078             const double y = v[1] - transfoMat.r[13];
00079             const double z = v[2] - transfoMat.r[14];
00080             v[0] = transfoMat.r[0]*x + transfoMat.r[1]*y + transfoMat.r[2]*z;
00081             v[1] = transfoMat.r[4]*x + transfoMat.r[5]*y + transfoMat.r[6]*z;
00082             v[2] = transfoMat.r[8]*x + transfoMat.r[9]*y + transfoMat.r[10]*z;
00083         }
00084         void forward(Vec3f& v) const {v.transfo4d(transfoMatf);}
00085         void backward(Vec3f& v) const
00086         {
00087             // We need no matrix inversion because we always work with orthogonal matrices (where the transposed is the inverse).
00088             //v.transfo4d(inverseTransfoMat);
00089             const float x = v[0] - transfoMatf.r[12];
00090             const float y = v[1] - transfoMatf.r[13];
00091             const float z = v[2] - transfoMatf.r[14];
00092             v[0] = transfoMatf.r[0]*x + transfoMatf.r[1]*y + transfoMatf.r[2]*z;
00093             v[1] = transfoMatf.r[4]*x + transfoMatf.r[5]*y + transfoMatf.r[6]*z;
00094             v[2] = transfoMatf.r[8]*x + transfoMatf.r[9]*y + transfoMatf.r[10]*z;
00095         }
00096         void combine(const Mat4d& m)
00097         {
00098             Mat4f mf(m[0], m[1], m[2], m[3],
00099                              m[4], m[5], m[6], m[7],
00100                              m[8], m[9], m[10], m[11],
00101                              m[12], m[13], m[14], m[15]);
00102             transfoMat=transfoMat*m;
00103             transfoMatf=transfoMatf*mf;
00104         }
00105         Mat4d getApproximateLinearTransfo() const {return transfoMat;}
00106         ModelViewTranformP clone() const {return ModelViewTranformP(new Mat4dTransform(transfoMat));}
00107 
00108     private:
00110         Mat4d transfoMat;
00111         Mat4f transfoMatf;
00112     };
00113 
00116     enum StelProjectorMaskType
00117     {
00118         MaskNone,   
00119         MaskDisk    
00120     };
00121 
00124     struct StelProjectorParams
00125     {
00126         StelProjectorParams() : viewportXywh(0, 0, 256, 256), fov(60.f), gravityLabels(false), defautAngleForGravityText(0.f), maskType(MaskNone), viewportCenter(128.f, 128.f), flipHorz(false), flipVert(false) {;}
00127         Vector4<int> viewportXywh;      
00128         float fov;                      
00129         bool gravityLabels;             
00130         float defautAngleForGravityText;
00131         StelProjectorMaskType maskType; 
00132         float zNear, zFar;              
00133         Vec2f viewportCenter;           
00134         float viewportFovDiameter;      
00135         bool flipHorz, flipVert;        
00136     };
00137 
00139     virtual ~StelProjector() {}
00140 
00142     // Methods which must be reimplemented by all instance of StelProjector
00144     virtual QString getNameI18() const = 0;
00146     virtual QString getDescriptionI18() const {return "No description";}
00148     QString getHtmlSummary() const;
00150     virtual float getMaxFov() const = 0;
00157     virtual bool forward(Vec3f& v) const = 0;
00159     virtual bool backward(Vec3d& v) const = 0;
00161     virtual float deltaZoom(float fov) const = 0;
00162 
00166     bool intersectViewportDiscontinuity(const Vec3d& p1, const Vec3d& p2) const
00167     {
00168         if (hasDiscontinuity()==false)
00169             return false;
00170         Vec3d v1(p1);
00171         modelViewTransform->forward(v1);
00172         Vec3d v2(p2);
00173         modelViewTransform->forward(v2);
00174         return intersectViewportDiscontinuityInternal(v1, v2);
00175     }
00176 
00177     bool intersectViewportDiscontinuity(const SphericalCap& cap) const
00178     {
00179         if (hasDiscontinuity()==false)
00180             return false;
00181         Vec3d v1(cap.n);
00182         modelViewTransform->forward(v1);
00183         return intersectViewportDiscontinuityInternal(v1, cap.d);
00184     }
00185 
00187     virtual float fovToViewScalingFactor(float fov) const = 0;
00189     virtual float viewScalingFactorToFov(float vsf) const = 0;
00190 
00194     bool getFlagGravityLabels() const { return gravityLabels; }
00195 
00197     const Vec4i& getViewport() const {return viewportXywh;}
00198 
00200     Vec2f getViewportCenter() const
00201     {
00202         return Vec2f(viewportCenter[0]-viewportXywh[0],viewportCenter[1]-viewportXywh[1]);
00203     }
00204 
00206     int getViewportPosX() const {return viewportXywh[0];}
00208     int getViewportPosY() const {return viewportXywh[1];}
00210     int getViewportWidth() const {return viewportXywh[2];}
00212     int getViewportHeight() const {return viewportXywh[3];}
00213 
00219     SphericalRegionP getViewportConvexPolygon(float marginX=0., float marginY=0.) const;
00220 
00222     const SphericalCap& getBoundingCap() const {return boundingCap;}
00223 
00225     float getPixelPerRadAtCenter() const {return pixelPerRad;}
00226 
00228     float getFov() const {return 360.f/M_PI*viewScalingFactorToFov(0.5f*viewportFovDiameter/pixelPerRad);}
00229 
00231     bool needGlFrontFaceCW() const {return (flipHorz*flipVert < 0.f);}
00232 
00234     // Full projection methods
00237     bool checkInViewport(const Vec3d& pos) const
00238     {
00239         return (pos[1]>=viewportXywh[1] && pos[0]>=viewportXywh[0] &&
00240             pos[1]<=(viewportXywh[1] + viewportXywh[3]) && pos[0]<=(viewportXywh[0] + viewportXywh[2]));
00241     }
00242 
00245     bool checkInViewport(const Vec3f& pos) const
00246     {
00247         return (pos[1]>=viewportXywh[1] && pos[0]>=viewportXywh[0] &&
00248             pos[1]<=(viewportXywh[1] + viewportXywh[3]) && pos[0]<=(viewportXywh[0] + viewportXywh[2]));
00249     }
00250 
00253     Vec3d viewPortIntersect(const Vec3d& p1, const Vec3d& p2) const
00254     {
00255         Vec3d v1=p1;
00256         Vec3d v2=p2;
00257         Vec3d v;
00258         for (int i=0;i<8;++i)
00259         {
00260             v=(v1+v2)*0.5;
00261             if (!checkInViewport(v))
00262                 v2=v;
00263             else
00264                 v1=v;
00265         }
00266         return v;
00267     }
00268 
00273     inline bool project(const Vec3d& v, Vec3d& win) const
00274     {
00275         win = v;
00276         return projectInPlace(win);
00277     }
00278 
00283     inline bool project(const Vec3f& v, Vec3f& win) const
00284     {
00285         win = v;
00286         return projectInPlace(win);
00287     }
00288 
00289     virtual void project(int n, const Vec3d* in, Vec3f* out)
00290     {
00291         Vec3d v;
00292         for (int i = 0; i < n; ++i, ++out)
00293         {
00294             v = in[i];
00295             modelViewTransform->forward(v);
00296             out->set(v[0], v[1], v[2]);
00297             forward(*out);
00298             out->set(viewportCenter[0] + flipHorz * pixelPerRad * (*out)[0],
00299                 viewportCenter[1] + flipVert * pixelPerRad * (*out)[1],
00300                 ((*out)[2] - zNear) * oneOverZNearMinusZFar);
00301         }
00302     }
00303 
00304     virtual void project(int n, const Vec3f* in, Vec3f* out)
00305     {
00306         for (int i = 0; i < n; ++i, ++out)
00307         {
00308             *out=in[i];
00309             modelViewTransform->forward(*out);
00310             forward(*out);
00311             out->set(viewportCenter[0] + flipHorz * pixelPerRad * (*out)[0],
00312                 viewportCenter[1] + flipVert * pixelPerRad * (*out)[1],
00313                 ((*out)[2] - zNear) * oneOverZNearMinusZFar);
00314         }
00315     }
00316 
00320     inline bool projectInPlace(Vec3d& vd) const
00321     {
00322         modelViewTransform->forward(vd);
00323         Vec3f v(vd[0], vd[1], vd[2]);
00324         const bool rval = forward(v);
00325         // very important: even when the projected point comes from an
00326         // invisible region of the sky (rval=false), we must finish
00327         // reprojecting, so that OpenGl can successfully eliminate
00328         // polygons by culling.
00329         vd[0] = viewportCenter[0] + flipHorz * pixelPerRad * v[0];
00330         vd[1] = viewportCenter[1] + flipVert * pixelPerRad * v[1];
00331         vd[2] = (v[2] - zNear) * oneOverZNearMinusZFar;
00332         return rval;
00333     }
00334 
00338     inline bool projectInPlace(Vec3f& v) const
00339     {
00340         modelViewTransform->forward(v);
00341         const bool rval = forward(v);
00342         // very important: even when the projected point comes from an
00343         // invisible region of the sky (rval=false), we must finish
00344         // reprojecting, so that OpenGl can successfully eliminate
00345         // polygons by culling.
00346         v[0] = viewportCenter[0] + flipHorz * pixelPerRad * v[0];
00347         v[1] = viewportCenter[1] + flipVert * pixelPerRad * v[1];
00348         v[2] = (v[2] - zNear) * oneOverZNearMinusZFar;
00349         return rval;
00350     }
00351 
00356     bool projectCheck(const Vec3d& v, Vec3d& win) const {return (project(v, win) && checkInViewport(win));}
00357 
00362     bool projectCheck(const Vec3f& v, Vec3f& win) const {return (project(v, win) && checkInViewport(win));}
00363 
00368     bool unProject(const Vec3d& win, Vec3d& v) const {return unProject(win[0], win[1], v);}
00369     bool unProject(double x, double y, Vec3d& v) const;
00370 
00377     bool projectLineCheck(const Vec3d& v1, Vec3d& win1, const Vec3d& v2, Vec3d& win2) const
00378         {return project(v1, win1) && project(v2, win2) && (checkInViewport(win1) || checkInViewport(win2));}
00379 
00381     ModelViewTranformP getModelViewTransform() const {return modelViewTransform;}
00382 
00384     Mat4f getProjectionMatrix() const {return Mat4f(2.f/viewportXywh[2], 0, 0, 0, 0, 2.f/viewportXywh[3], 0, 0, 0, 0, -1., 0., -(2.f*viewportXywh[0] + viewportXywh[2])/viewportXywh[2], -(2.f*viewportXywh[1] + viewportXywh[3])/viewportXywh[3], 0, 1);}
00385 
00388     static const QString maskTypeToString(StelProjectorMaskType type);
00390     static StelProjectorMaskType stringToMaskType(const QString &s);
00391 
00393     StelProjectorMaskType getMaskType(void) const {return maskType;}
00394 
00395 protected:
00397     StelProjector(ModelViewTranformP amodelViewTransform) : modelViewTransform(amodelViewTransform) {;}
00398 
00400     virtual bool hasDiscontinuity() const =0;
00404     virtual bool intersectViewportDiscontinuityInternal(const Vec3d& p1, const Vec3d& p2) const = 0;
00405 
00407     virtual bool intersectViewportDiscontinuityInternal(const Vec3d& capN, double capD) const = 0;
00408 
00410     virtual void computeBoundingCap();
00411 
00412     ModelViewTranformP modelViewTransform;  // Operator to apply (if not NULL) before the modelview projection step
00413 
00414     float flipHorz,flipVert;            // Whether to flip in horizontal or vertical directions
00415     float pixelPerRad;                  // pixel per rad at the center of the viewport disk
00416     StelProjectorMaskType maskType;     // The current projector mask
00417     float zNear, oneOverZNearMinusZFar; // Near and far clipping planes
00418     Vec4i viewportXywh;                 // Viewport parameters
00419     Vec2f viewportCenter;               // Viewport center in screen pixel
00420     float viewportFovDiameter;          // diameter of the FOV disk in pixel
00421     bool gravityLabels;                 // should label text align with the horizon?
00422     float defautAngleForGravityText;    // a rotation angle to apply to gravity text (only if gravityLabels is set to false)
00423     SphericalCap boundingCap;           // Bounding cap of the whole viewport
00424 
00425 private:
00427     void init(const StelProjectorParams& param);
00428 };
00429 
00430 #endif // _STELPROJECTOR_HPP_