1 /* 2 * Stellarium 3 * Copyright (C) 2003 Fabien Chereau 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 LANDSCAPE_HPP 21 #define LANDSCAPE_HPP 22 23 #include "VecMath.hpp" 24 #include "StelToneReproducer.hpp" 25 #include "StelProjector.hpp" 26 27 #include "StelFader.hpp" 28 #include "StelUtils.hpp" 29 #include "StelTextureTypes.hpp" 30 #include "StelLocation.hpp" 31 #include "StelSphereGeometry.hpp" 32 33 #include <QMap> 34 #include <QImage> 35 #include <QList> 36 #include <QFont> 37 38 class QSettings; 39 class StelLocation; 40 class StelCore; 41 class StelPainter; 42 43 //! @class Landscape 44 //! Store and manages the displaying of the Landscape. 45 //! Don't use this class directly, use the LandscapeMgr. 46 //! A landscape's most important element is a photo panorama, or at least a polygon that describes the true horizon visible from your observing location. 47 //! Optional components include: 48 //! - A fog texture that is displayed with the Fog [F] command (displayed only if atmosphere is on!). 49 //! - A location. It is possible to auto-move to the location when loading. 50 //! - Atmospheric conditions: temperature/pressure/extinction coefficients. These influence refraction and extinction. 51 //! - Light pollution information (Bortle index) 52 //! - A night texture that gets blended over the dimmed daylight panorama. (All landscapes except Polygonal.) 53 //! - A polygonal horizon line (required for PolygonalLandscape). If present, defines a measured horizon line, which can be plotted or queried for rise/set predictions. 54 //! - You can set a minimum brightness level to prevent too dark landscape. There is 55 //! a global activation setting (config.ini[landscape]flag_minimal_brightness), 56 //! a global value (config.ini[landscape]minimal_brightness), 57 //! and, if config.ini[landscape]flag_landscape_sets_minimal_brightness=true, 58 //! optional individual values given in landscape.ini[landscape]minimal_brightness are used. 59 //! 60 //! We discern: 61 //! @param LandscapeId: The directory name of the landscape. 62 //! @param name: The landscape name as specified in the LandscapeIni (may contain spaces, translatable, UTF8, ...) 63 class Landscape 64 { 65 public: 66 typedef struct 67 { 68 QString name; 69 Vec3d featurePoint; // start of the line: mountain peak, building, ... 70 Vec3d labelPoint; // end of the line, where the centered label best fits. 71 } LandscapeLabel; 72 73 Landscape(float _radius = 2.f); 74 virtual ~Landscape(); 75 //! Load landscape. 76 //! @param landscapeIni A reference to an existing QSettings object which describes the landscape 77 //! @param landscapeId The name of the directory for the landscape files (e.g. "ocean") 78 virtual void load(const QSettings& landscapeIni, const QString& landscapeId) = 0; 79 80 //! Return approximate memory footprint in bytes (required for cache cost estimate in LandscapeMgr) 81 //! The returned value is only approximate, content of QStrings and other small containers like the horizon polygon are not put in in detail. 82 //! However, texture image sizes must be computed and added in subclasses. 83 //! The value returned is a sum of RAM and texture memory requirements. getMemorySize() const84 unsigned int getMemorySize() const {return memorySize;} 85 86 //! Draw the landscape. If onlyPolygon, only draw the landscape polygon, if one is defined. If no polygon is defined, the 87 virtual void draw(StelCore* core, bool onlyPolygon) = 0; update(double deltaTime)88 void update(double deltaTime) 89 { 90 landFader.update(static_cast<int>(deltaTime*1000)); 91 fogFader.update(static_cast<int>(deltaTime*1000)); 92 illumFader.update(static_cast<int>(deltaTime*1000)); 93 labelFader.update(static_cast<int>(deltaTime*1000)); 94 } 95 96 //! Set the brightness of the landscape plus brightness of optional add-on night lightscape. 97 //! This is called in each draw(). setBrightness(const double b,const double pollutionBrightness=0.0)98 void setBrightness(const double b, const double pollutionBrightness=0.0) {landscapeBrightness = static_cast<float>(b); lightScapeBrightness=static_cast<float>(pollutionBrightness); } 99 100 //! Returns the current brightness level getBrightness() const101 double getBrightness() const { return static_cast<double>(landscapeBrightness); } 102 //! Returns the lightscape brightness getLightscapeBrightness() const103 double getLightscapeBrightness() const { return static_cast<double>(lightScapeBrightness); } 104 //! Returns the lightscape brighness modulated with the fader's target state (i.e. binary on/off) getTargetLightscapeBrightness() const105 double getTargetLightscapeBrightness() const { return static_cast<double>(lightScapeBrightness * illumFader); } 106 //! Gets the currently effective lightscape brightness (modulated by the fader) getEffectiveLightscapeBrightness() const107 double getEffectiveLightscapeBrightness() const { return static_cast<double>(lightScapeBrightness * illumFader.getInterstate()); } 108 109 //! Set whether landscape is displayed (does not concern fog) setFlagShow(const bool b)110 void setFlagShow(const bool b) {landFader=b;} 111 //! Get whether landscape is displayed (does not concern fog) getFlagShow() const112 bool getFlagShow() const {return static_cast<bool>(landFader);} 113 //! Returns the currently effective land fade value getEffectiveLandFadeValue() const114 float getEffectiveLandFadeValue() const { return landFader.getInterstate(); } 115 //! Set whether fog is displayed setFlagShowFog(const bool b)116 void setFlagShowFog(const bool b) {fogFader=b;} 117 //! Get whether fog is displayed getFlagShowFog() const118 bool getFlagShowFog() const {return static_cast<bool>(fogFader);} 119 //! Set whether illumination is displayed setFlagShowIllumination(const bool b)120 void setFlagShowIllumination(const bool b) {illumFader=b;} 121 //! Get whether illumination is displayed getFlagShowIllumination() const122 bool getFlagShowIllumination() const {return static_cast<bool>(illumFader);} 123 //! Set whether labels are displayed setFlagShowLabels(const bool b)124 void setFlagShowLabels(const bool b) {labelFader=b;} 125 //! Get whether labels are displayed getFlagShowLabels() const126 bool getFlagShowLabels() const {return static_cast<bool>(labelFader);} 127 //! change font and fontsize for landscape labels setLabelFontSize(const int size)128 void setLabelFontSize(const int size){fontSize=size;} 129 130 //! Get landscape name getName() const131 QString getName() const {return name;} 132 //! Get landscape author name getAuthorName() const133 QString getAuthorName() const {return author;} 134 //! Get landscape description getDescription() const135 QString getDescription() const {return description;} 136 //! Get landscape id. This is the landscape directory name, used for cache handling. getId() const137 QString getId() const {return id;} 138 139 //! Return the associated location (may be empty!) getLocation() const140 const StelLocation& getLocation() const {return location;} 141 //! Return if the location is valid (a valid location has a valid planetName!) hasLocation() const142 bool hasLocation() const {return (!(location.planetName.isEmpty()));} 143 //! Return default Bortle index (light pollution value) or -1 (unknown/no change) getDefaultBortleIndex() const144 int getDefaultBortleIndex() const {return defaultBortleIndex;} 145 //! Return default fog setting (0/1) or -1 (no change) getDefaultFogSetting() const146 int getDefaultFogSetting() const {return defaultFogSetting;} 147 //! Return default atmosperic extinction [mag/airmass], or -1 (no change) getDefaultAtmosphericExtinction() const148 double getDefaultAtmosphericExtinction() const {return defaultExtinctionCoefficient;} 149 //! Return configured atmospheric temperature [degrees Celsius], for refraction computation, or -1000 for "unknown/no change". getDefaultAtmosphericTemperature() const150 double getDefaultAtmosphericTemperature() const {return defaultTemperature;} 151 //! Return configured atmospheric pressure [mbar], for refraction computation. 152 //! returns -1 to signal "standard conditions" [compute from altitude], or -2 for "unknown/invalid/no change" getDefaultAtmosphericPressure() const153 double getDefaultAtmosphericPressure() const {return defaultPressure;} 154 //! Return minimal brightness for landscape 155 //! returns -1 to signal "standard conditions" (use default value from config.ini) getLandscapeMinimalBrightness() const156 double getLandscapeMinimalBrightness() const {return static_cast<double>(minBrightness);} 157 158 //! Set an additional z-axis (azimuth) rotation after landscape has been loaded. 159 //! This is intended for special uses such as when the landscape consists of 160 //! a vehicle which might change orientation over time (e.g. a ship). It is called 161 //! e.g. by the LandscapeMgr. Contrary to that, the purpose of the azimuth rotation 162 //! (landscape/[decor_]angle_rotatez) in landscape.ini is to orient the pano. 163 //! @param d the rotation angle in degrees. setZRotation(float d)164 void setZRotation(float d) {angleRotateZOffset = d * static_cast<float>(M_PI)/180.0f;} 165 166 //! Get whether the landscape is currently fully visible (i.e. opaque). getIsFullyVisible() const167 bool getIsFullyVisible() const {return landFader.getInterstate() >= 0.999f;} 168 //! Get the sine of the limiting altitude (can be used to short-cut drawing below horizon, like star fields). There is no set here, value is only from landscape.ini getSinMinAltitudeLimit() const169 double getSinMinAltitudeLimit() const {return sinMinAltitudeLimit;} 170 171 //! Find opacity in a certain direction. (New in V0.13 series) 172 //! can be used to find sunrise or visibility questions on the real-world landscape horizon. 173 //! Default implementation indicates the horizon equals math horizon. 174 // TBD: Maybe change this to azalt[2]<sinMinAltitudeLimit ? (But never called in practice, reimplemented by the subclasses...) getOpacity(Vec3d azalt) const175 virtual float getOpacity(Vec3d azalt) const { Q_ASSERT(0); return (azalt[2]<0 ? 1.0f : 0.0f); } 176 //! The list of azimuths (counted from True North towards East) and altitudes can come in various formats. We read the first two elements, which can be of formats: 177 enum horizonListMode { 178 invalid =-1, 179 azDeg_altDeg = 0, //! azimuth[degrees] altitude[degrees] 180 azDeg_zdDeg = 1, //! azimuth[degrees] zenithDistance[degrees] 181 azRad_altRad = 2, //! azimuth[radians] altitude[radians] 182 azRad_zdRad = 3, //! azimuth[radians] zenithDistance[radians] 183 azGrad_altGrad = 4, //! azimuth[new_degrees] altitude[new_degrees] (may be found on theodolites) 184 azGrad_zdGrad = 5 //! azimuth[new_degrees] zenithDistance[new_degrees] (may be found on theodolites) 185 }; 186 187 //! Load descriptive labels from optional file gazetteer.LANG.utf8. 188 void loadLabels(const QString& landscapeId); hasLandscapePolygon() const189 bool hasLandscapePolygon() const {return !horizonPolygon.isNull();} 190 191 protected: 192 //! Load attributes common to all landscapes 193 //! @param landscapeIni A reference to an existing QSettings object which describes the landscape 194 //! @param landscapeId The name of the directory for the landscape files (e.g. "ocean") 195 void loadCommon(const QSettings& landscapeIni, const QString& landscapeId); 196 197 //! Draw optional labels on the landscape 198 void drawLabels(StelCore *core, StelPainter *painter); 199 200 201 //! Create a StelSphericalPolygon that describes a measured horizon line. If present, this can be used to draw a horizon line 202 //! or simplify the functionality to discern if an object is below the horizon. 203 //! @param lineFileName A text file with lines that are either empty or comment lines starting with # or azimuth altitude [degrees] 204 //! @param polyAngleRotateZ possibility to set some final calibration offset like meridian convergence correction. 205 //! @param listMode keys which indicate angular units for the angles 206 void createPolygonalHorizon(const QString& lineFileName, const float polyAngleRotateZ=0.0f, const QString &listMode="azDeg_altDeg"); 207 208 //! search for a texture in landscape directory, else global textures directory 209 //! @param basename The name of a texture file, e.g. "fog.png" 210 //! @param landscapeId The landscape ID (directory name) to which the texture belongs 211 //! @note returns an empty string if file not found. 212 static const QString getTexturePath(const QString& basename, const QString& landscapeId); 213 double radius; 214 QString name; //! Read from landscape.ini:[landscape]name 215 QString author; //! Read from landscape.ini:[landscape]author 216 QString description; //! Read from landscape.ini:[landscape]description 217 QString id; //! Set during load. Required for consistent caching. 218 219 float minBrightness; //! Read from landscape.ini:[landscape]minimal_brightness. Allows minimum visibility that cannot be underpowered. 220 float landscapeBrightness; //! brightness [0..1] to draw the landscape. Computed by the LandscapeMgr. 221 float lightScapeBrightness; //! can be used to draw nightscape texture (e.g. city light pollution), if available. Computed by the LandscapeMgr. 222 bool validLandscape; //! was a landscape loaded properly? 223 LinearFader landFader; //! Used to slowly fade in/out landscape painting. 224 LinearFader fogFader; //! Used to slowly fade in/out fog painting. 225 LinearFader illumFader;//! Used to slowly fade in/out illumination painting. 226 LinearFader labelFader;//! Used to slowly fade in/out landscape feature labels. 227 unsigned int rows; //! horizontal rows. May be given in landscape.ini:[landscape]tesselate_rows. More indicates higher accuracy, but is slower. 228 unsigned int cols; //! vertical columns. May be given in landscape.ini:[landscape]tesselate_cols. More indicates higher accuracy, but is slower. 229 float angleRotateZ; //! [radians] if pano does not have its left border in the east, rotate in azimuth. Configured in landscape.ini[landscape]angle_rotatez (or decor_angle_rotatez for old_style landscapes) 230 float angleRotateZOffset; //! [radians] This is a rotation changeable at runtime via setZRotation (called by LandscapeMgr::setZRotation). 231 //! Not in landscape.ini: Used in special cases where the horizon may rotate, e.g. on a ship. 232 233 double sinMinAltitudeLimit; //! Minimal altitude of landscape cover. Can be used to construct bounding caps, so that e.g. no stars are drawn below this altitude. Default -0.035, i.e. sin(-2 degrees). 234 235 StelLocation location; //! OPTIONAL. If present, can be used to set location. 236 int defaultBortleIndex; //! May be given in landscape.ini:[location]light_pollution. Default: -1 (no change). 237 int defaultFogSetting; //! May be given in landscape.ini:[location]display_fog: -1(no change), 0(off), 1(on). Default: -1. 238 double defaultExtinctionCoefficient; //! May be given in landscape.ini:[location]atmospheric_extinction_coefficient. Default -1 (no change). 239 double defaultTemperature; //! [Celsius] May be given in landscape.ini:[location]atmospheric_temperature. default: -1000.0 (no change) 240 double defaultPressure; //! [mbar] May be given in landscape.ini:[location]atmospheric_pressure. Default -1.0 (compute from [location]/altitude), use -2 to indicate "no change". 241 242 // Optional elements which, if present, describe a horizon polygon. They can be used to render a line or a filled region, esp. in LandscapePolygonal 243 SphericalRegionP horizonPolygon; //! Optional element describing the horizon line. 244 //! Data shall be read from the file given as landscape.ini[landscape]polygonal_horizon_list 245 //! For LandscapePolygonal, this is the only horizon data item. 246 Vec3f horizonPolygonLineColor; //! for all horizon types, the horizonPolygon line, if specified, will be drawn in this color 247 //! specified in landscape.ini[landscape]horizon_line_color. Negative red (default) indicated "don't draw". 248 // Optional element: labels for landscape features. 249 QList<LandscapeLabel> landscapeLabels; 250 int fontSize; //! Used for landscape labels (optionally indicating landscape features) 251 Vec3f labelColor; //! Color for the landscape labels. 252 unsigned int memorySize; //!< holds an approximate value of memory consumption (for cache cost estimate) 253 }; 254 255 //! @class LandscapeOldStyle 256 //! This was the original landscape, introduced for decorative purposes. It segments the horizon in several tiles 257 //! (usually 4 or 8), therefore allowing very high resolution horizons also on limited hardware, 258 //! and closes the ground with a separate bottom piece. (You may want to configure a map with pointers to surrounding mountains or a compass rose instead!) 259 //! You can use panoramas created in equirectangular or cylindrical coordinates, for the latter case set 260 //! [landscape]tan_mode=true. 261 //! Until V0.10.5 there was an undetected bug involving vertical positioning. For historical reasons (many landscapes 262 //! were already configured and published), it was decided to keep this bug as feature, but a fix for new landscapes is 263 //! available: [landscape]calibrated=true. 264 //! As of 0.10.6, the fix is only valid for equirectangular panoramas. 265 //! As of V0.13, [landscape]calibrated=true and [landscape]tan_mode=true go together for cylindrical panoramas. 266 //! It is more involved to configure, but may still be preferred if you require the resolution, e.g. for alignment studies 267 //! for archaeoastronomy. In this case, don't forget to set calibrated=true in landscape.ini. 268 //! Since V0.13.1, also this landscape has a self-luminous (light pollution) option: Configure light<n> entries with textures overlaid the tex<n> textures. Only textures with light are necessary! 269 //! Can be easily made using layers with e.g. Photoshop or Gimp. 270 class LandscapeOldStyle : public Landscape 271 { 272 public: 273 LandscapeOldStyle(float radius = 2.0f); 274 virtual ~LandscapeOldStyle() Q_DECL_OVERRIDE; 275 virtual void load(const QSettings& landscapeIni, const QString& landscapeId) Q_DECL_OVERRIDE; 276 virtual void draw(StelCore* core, bool onlyPolygon) Q_DECL_OVERRIDE; 277 //void create(bool _fullpath, QMap<QString, QString> param); // still not implemented 278 virtual float getOpacity(Vec3d azalt) const Q_DECL_OVERRIDE; 279 protected: 280 typedef struct 281 { 282 StelTextureSP tex; 283 StelTextureSP tex_illum; // optional light texture. 284 float texCoords[4]; 285 } landscapeTexCoord; 286 287 private: 288 void drawFog(StelCore* core, StelPainter&) const; 289 // drawLight==true for illumination layer, it then selects only the self-illuminating panels. 290 void drawDecor(StelCore* core, StelPainter&, const bool drawLight=false) const; 291 void drawGround(StelCore* core, StelPainter&) const; 292 QVector<Vec3d> groundVertexArr; 293 QVector<Vec2f> groundTexCoordArr; 294 StelTextureSP* sideTexs; 295 unsigned short int nbSideTexs; 296 unsigned short int nbSide; 297 landscapeTexCoord* sides; 298 StelTextureSP fogTex; 299 StelTextureSP groundTex; 300 QVector<QImage*> sidesImages; // Required for opacity lookup 301 unsigned short int nbDecorRepeat; 302 float fogAltAngle; 303 float fogAngleShift; 304 float decorAltAngle; // vertical extent of the side panels 305 float decorAngleShift; 306 float groundAngleShift; //! [radians]: altitude of the bottom plane. Usually negative and equal to decorAngleShift 307 double groundAngleRotateZ; //! [radians]: rotation to bring top of texture away from due east. 308 bool drawGroundFirst; 309 bool tanMode; // Whether the angles should be converted using tan instead of sin, i.e., for a cylindrical pano 310 bool calibrated; // if true, the documented altitudes are indeed correct (the original code is buggy!) 311 struct LOSSide 312 { 313 StelVertexArray arr; 314 StelTextureSP tex; 315 bool light; // true if texture is self-lighting. 316 }; 317 318 QList<LOSSide> precomputedSides; 319 }; 320 321 ///////////////////////////////////////////////////////// 322 /// 323 //! @class LandscapePolygonal 324 //! This uses the list of (usually measured) horizon altitudes to define the horizon. 325 //! Define it with the following names in landscape.ini: 326 //! @param landscape/ground_color use this color below horizon 327 //! @param landscape/polygonal_horizon_list filename containing azimuths/altitudes, compatible with Carte du Ciel. 328 //! @param landscape/polygonal_angle_rotatez offset for the polygonal measurement 329 //! (different from landscape/angle_rotatez in photo panos, often photo and line are not aligned.) 330 class LandscapePolygonal : public Landscape 331 { 332 public: 333 LandscapePolygonal(float radius = 1.f); 334 virtual ~LandscapePolygonal() Q_DECL_OVERRIDE; 335 virtual void load(const QSettings& landscapeIni, const QString& landscapeId) Q_DECL_OVERRIDE; 336 virtual void draw(StelCore* core, bool onlyPolygon) Q_DECL_OVERRIDE; 337 virtual float getOpacity(Vec3d azalt) const Q_DECL_OVERRIDE; 338 private: 339 // we have inherited: horizonFileName, horizonPolygon, horizonPolygonLineColor 340 Vec3f groundColor; //! specified in landscape.ini[landscape]ground_color. 341 }; 342 343 /////////////////////////////////////////////////////////////// 344 /// 345 //! @class LandscapeFisheye 346 //! This uses a single image in fisheye projection. The image is typically square, ... 347 //! @param texFov: field of view (opening angle) of the square texture, radians. 348 //! If @param angleRotateZ==0, the top image border is due south. 349 class LandscapeFisheye : public Landscape 350 { 351 public: 352 LandscapeFisheye(float radius = 1.f); 353 virtual ~LandscapeFisheye() Q_DECL_OVERRIDE; 354 virtual void load(const QSettings& landscapeIni, const QString& landscapeId) Q_DECL_OVERRIDE; 355 virtual void draw(StelCore* core, bool onlyPolygon) Q_DECL_OVERRIDE; 356 //! Sample landscape texture for transparency/opacity. May be used for visibility, sunrise etc. 357 //! @param azalt normalized direction in alt-az frame 358 virtual float getOpacity(Vec3d azalt) const Q_DECL_OVERRIDE; 359 //! create a fisheye landscape from basic parameters (no ini file needed). 360 //! @param name Landscape name 361 //! @param maptex the fisheye texture 362 //! @param maptexIllum the fisheye texture that is overlaid in the night (streetlights, skyglow, ...) 363 //! @param texturefov field of view for the photo, degrees 364 //! @param angleRotateZ azimuth rotation angle, degrees 365 void create(const QString name, const QString& maptex, float texturefov, float angleRotateZ); 366 void create(const QString name, float texturefov, const QString& maptex, const QString &_maptexFog="", const QString& _maptexIllum="", const float angleRotateZ=0.0f); 367 368 private: 369 StelTextureSP mapTex; //!< The fisheye image, centered on the zenith. 370 StelTextureSP mapTexFog; //!< Optional panorama of identical size (create as layer over the mapTex image in your favorite image processor). 371 //!< can also be smaller, just the texture is again mapped onto the same geometry. 372 StelTextureSP mapTexIllum; //!< Optional fisheye image of identical size (create as layer in your favorite image processor) or at least, proportions. 373 //!< To simulate light pollution (skyglow), street lights, light in windows, ... at night 374 QImage *mapImage; //!< The same image as mapTex, but stored in-mem for sampling. 375 376 float texFov; 377 }; 378 379 ////////////////////////////////////////////////////////////////////////// 380 //! @class LandscapeSpherical 381 //! This uses a single panorama image in spherical (equirectangular) projection. A complete image is rectangular with the horizon forming a 382 //! horizontal line centered vertically, and vertical altitude angles linearly mapped in image height. 383 //! Since 0.13 and Qt5, large images of 8192x4096 pixels are available, but they still may not work on every hardware. 384 //! If @param angleRotateZ==0, the left/right image border is due east. 385 //! It is possible to remove empty top or bottom parts of the textures (main texture: only top part should meaningfully be cut away!) 386 //! The textures should still be power-of-two, so maybe 8192x1024 for the fog, or 8192x2048 for the light pollution. 387 //! (It's OK to stretch the textures. They just have to fit, geometrically!) 388 //! TODO: Allow a horizontal split for 2 or even 4 parts, i.e. super-large, super-accurate panos. 389 class LandscapeSpherical : public Landscape 390 { 391 public: 392 LandscapeSpherical(float radius = 1.f); 393 virtual ~LandscapeSpherical() Q_DECL_OVERRIDE; 394 virtual void load(const QSettings& landscapeIni, const QString& landscapeId) Q_DECL_OVERRIDE; 395 virtual void draw(StelCore* core, bool onlyPolygon) Q_DECL_OVERRIDE; 396 //! Sample landscape texture for transparency/opacity. May be used for visibility, sunrise etc. 397 //! @param azalt normalized direction in alt-az frame 398 //! @retval alpha (0=fully transparent, 1=fully opaque. Trees, leaves, glass etc may have intermediate values.) 399 virtual float getOpacity(Vec3d azalt) const Q_DECL_OVERRIDE; 400 //! create a spherical landscape from basic parameters (no ini file needed). 401 //! @param name Landscape name 402 //! @param maptex the equirectangular texture 403 //! @param maptexIllum the equirectangular texture that is overlaid in the night (streetlights, skyglow, ...) 404 //! @param angleRotateZ azimuth rotation angle, degrees [0] 405 //! @param _mapTexTop altitude angle of top edge of texture, degrees [90] 406 //! @param _mapTexBottom altitude angle of bottom edge of texture, degrees [-90] 407 //! @param _fogTexTop altitude angle of top edge of fog texture, degrees [90] 408 //! @param _fogTexBottom altitude angle of bottom edge of fog texture, degrees [-90] 409 //! @param _illumTexTop altitude angle of top edge of light pollution texture, degrees [90] 410 //! @param _illumTexBottom altitude angle of bottom edge of light pollution texture, degrees [-90] 411 //! @param _bottomCapColor RGB triplet for closing the hole around the nadir, if any. A color value of (-1/0/0) signals "no cap" 412 void create(const QString name, const QString& maptex, const QString &_maptexFog="", const QString& _maptexIllum="", const float _angleRotateZ=0.0f, 413 const float _mapTexTop=90.0f, const float _mapTexBottom=-90.0f, 414 const float _fogTexTop=90.0f, const float _fogTexBottom=-90.0f, 415 const float _illumTexTop=90.0f, const float _illumTexBottom=-90.0f, const Vec3f _bottomCapColor=Vec3f(-1.0f, 0.0f, 0.0f)); 416 417 private: 418 StelTextureSP mapTex; //!< The equirectangular panorama texture 419 StelTextureSP mapTexFog; //!< Optional panorama of identical size (create as layer over the mapTex image in your favorite image processor). 420 //!< can also be smaller, just the texture is again mapped onto the same geometry. 421 StelTextureSP mapTexIllum; //!< Optional panorama of identical size (create as layer over the mapTex image in your favorite image processor). 422 //!< To simulate light pollution (skyglow), street lights, light in windows, ... at night 423 SphericalCap bottomCap; //!< Geometry to close the bottom with a monochrome color when mapTexBottom is given. (Avoid hole in Nadir!) 424 // These vars are here to conserve texture memory. They must be allowed to be different: a landscape may have its highest elevations at 15°, fog may reach from -25 to +15°, 425 // light pollution may cover -5° (street lamps slightly below) plus parts of or even the whole sky. All have default values to simplify life. 426 float mapTexTop; //!< zenithal top angle of the landscape texture, radians 427 float mapTexBottom; //!< zenithal bottom angle of the landscape texture, radians 428 float fogTexTop; //!< zenithal top angle of the fog texture, radians 429 float fogTexBottom; //!< zenithal bottom angle of the fog texture, radians 430 float illumTexTop; //!< zenithal top angle of the illumination texture, radians 431 float illumTexBottom; //!< zenithal bottom angle of the illumination texture, radians 432 QImage *mapImage; //!< The same image as mapTex, but stored in-mem for opacity sampling. 433 Vec3f bottomCapColor; //!< The bottomCap, if specified, will be drawn in this color 434 }; 435 436 #endif // LANDSCAPE_HPP 437