/* * Stellarium * Copyright (C) 2003 Fabien Chereau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StelTranslator.hpp" #include "StelProjector.hpp" #include "StelProjectorClasses.hpp" #include #include const QString StelProjector::maskTypeToString(StelProjectorMaskType type) { if (type == MaskDisk ) return "disk"; else return "none"; } StelProjector::StelProjectorMaskType StelProjector::stringToMaskType(const QString &s) { if (s=="disk") return MaskDisk; return MaskNone; } void StelProjector::init(const StelProjectorParams& params) { maskType = (StelProjectorMaskType)params.maskType; zNear = params.zNear; oneOverZNearMinusZFar = 1.f/(zNear-params.zFar); viewportXywh = params.viewportXywh; viewportCenter = params.viewportCenter; gravityLabels = params.gravityLabels; flipHorz = params.flipHorz ? -1.f : 1.f; flipVert = params.flipVert ? -1.f : 1.f; viewportFovDiameter = params.viewportFovDiameter; pixelPerRad = 0.5f * viewportFovDiameter / fovToViewScalingFactor(params.fov*(M_PI/360.f)); computeBoundingCap(); } QString StelProjector::getHtmlSummary() const { return QString("

%1

%2

%3%4").arg(getNameI18()).arg(getDescriptionI18()).arg(q_("Maximum FOV: ")).arg(getMaxFov())+QChar(0x00B0); } /************************************************************************* Return a convex polygon on the sphere which includes the viewport in the current frame *************************************************************************/ SphericalRegionP StelProjector::getViewportConvexPolygon(float marginX, float marginY) const { Vec3d e0, e1, e2, e3; const Vec4i& vp = viewportXywh; bool ok = unProject(vp[0]-marginX,vp[1]-marginY,e0); ok &= unProject(vp[0]+vp[2]+marginX,vp[1]-marginY,e1); ok &= unProject(vp[0]+vp[2]+marginX,vp[1]+vp[3]+marginY,e2); ok &= unProject(vp[0]-marginX,vp[1]+vp[3]+marginY,e3); if (!ok) { // Special case for handling degenerated cases, use full sky. //qDebug() << "!ok"; return SphericalRegionP((SphericalRegion*)(new AllSkySphericalRegion())); } e0.normalize(); e1.normalize(); e2.normalize(); e3.normalize(); if (needGlFrontFaceCW()) { Vec3d v = e0; e0 = e3; e3 = v; v = e1; e1 = e2; e2 = v; } const double d = e3*((e2-e3)^(e1-e3)); if (d > 0) { SphericalConvexPolygon* res = new SphericalConvexPolygon(e0, e1, e2, e3); if (res->checkValid()) { return SphericalRegionP(res); } qDebug() << "!valid"; delete res; } //return SphericalRegionP((SphericalRegion*)(new AllSkySphericalRegion())); const SphericalCap& hp = getBoundingCap(); return SphericalRegionP(new SphericalCap(hp)); } void StelProjector::computeBoundingCap() { bool ok = unProject(viewportXywh[0]+0.5f*viewportXywh[2], viewportXywh[1]+0.5f*viewportXywh[3], boundingCap.n); Q_ASSERT(ok); // The central point should be at a valid position by definition const bool needNormalization = fabs(boundingCap.n.lengthSquared()-1.)>0.00000001; // Now need to determine the aperture Vec3d e0,e1,e2,e3,e4,e5; const Vec4i& vp = viewportXywh; ok &= unProject(vp[0],vp[1],e0); ok &= unProject(vp[0]+vp[2],vp[1],e1); ok &= unProject(vp[0]+vp[2],vp[1]+vp[3],e2); ok &= unProject(vp[0],vp[1]+vp[3],e3); ok &= unProject(vp[0],vp[1]+vp[3]/2,e4); ok &= unProject(vp[0]+vp[2],vp[1]+vp[3]/2,e5); if (!ok) { // Some points were in invalid positions, use full sky. boundingCap.d = -1.; boundingCap.n.set(1,0,0); return; } if (needNormalization) { boundingCap.n.normalize(); e0.normalize(); e1.normalize(); e2.normalize(); e3.normalize(); e4.normalize(); e5.normalize(); } boundingCap.d = boundingCap.n*e0; double h = boundingCap.n*e1; if (boundingCap.d > h) boundingCap.d=h; h = boundingCap.n*e2; if (boundingCap.d > h) boundingCap.d=h; h = boundingCap.n*e3; if (boundingCap.d > h) boundingCap.d=h; h = boundingCap.n*e4; if (boundingCap.d > h) boundingCap.d=h; h = boundingCap.n*e5; if (boundingCap.d > h) boundingCap.d=h; } /************************************************************************* Project the vector v from the viewport frame into the current frame *************************************************************************/ bool StelProjector::unProject(double x, double y, Vec3d &v) const { v[0] = flipHorz * (x - viewportCenter[0]) / pixelPerRad; v[1] = flipVert * (y - viewportCenter[1]) / pixelPerRad; v[2] = 0; const bool rval = backward(v); // Even when the reprojected point comes from a region of the screen, // where nothing is projected to (rval=false), we finish reprojecting. // This looks good for atmosphere rendering, and it helps avoiding // discontinuities when dragging around with the mouse. // We need no matrix inversion because we always work with orthogonal matrices (where the transposed is the inverse). //v.transfo4d(inverseModelViewMatrix); x = v[0] - modelViewMatrix.r[12]; y = v[1] - modelViewMatrix.r[13]; const double z = v[2] - modelViewMatrix.r[14]; v[0] = modelViewMatrix.r[0]*x + modelViewMatrix.r[1]*y + modelViewMatrix.r[2]*z; v[1] = modelViewMatrix.r[4]*x + modelViewMatrix.r[5]*y + modelViewMatrix.r[6]*z; v[2] = modelViewMatrix.r[8]*x + modelViewMatrix.r[9]*y + modelViewMatrix.r[10]*z; return rval; }