/* -*-c++-*- */ /* osgEarth - Geospatial SDK for OpenSceneGraph * Copyright 2020 Pelican Mapping * http://osgearth.org * * osgEarth is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTHUTIL_SKY #define OSGEARTHUTIL_SKY #include #include #include #include #include #include #include #include #include #include #include namespace osgDB { class Options; } namespace osgEarth { /** * Base Options structure for loading an environment node from * a plugin. */ class SkyOptions : public DriverConfigOptions { public: enum CoordinateSystem { COORDSYS_ECEF, COORDSYS_ECI }; enum Quality { QUALITY_UNSET, QUALITY_DEFAULT, QUALITY_LOW, QUALITY_MEDIUM, QUALITY_HIGH, QUALITY_BEST }; static Quality parseQuality(osg::ArgumentParser& args) { return args.read("--sky") ? QUALITY_DEFAULT : args.read("--sky-low") ? QUALITY_LOW : args.read("--sky-medium") ? QUALITY_MEDIUM : args.read("--sky-high") ? QUALITY_HIGH : args.read("--sky-best") ? QUALITY_BEST : QUALITY_UNSET; } //! Coordinate system for whole-earth maps (default = ECEF) OE_OPTION(CoordinateSystem, coordinateSystem); /** Time of day - Hours [0..24] component of DateTime */ OE_OPTION(float, hours); OE_OPTION(float, ambient); OE_OPTION(Quality, quality); public: SkyOptions( const ConfigOptions& options =ConfigOptions() ) : DriverConfigOptions(options) { coordinateSystem().setDefault(COORDSYS_ECEF); quality().setDefault(QUALITY_DEFAULT); ambient().setDefault(0.033f); hours().setDefault(12.0f); fromConfig(_conf); } virtual ~SkyOptions() { } virtual Config getConfig() const { Config conf = DriverConfigOptions::getConfig(); conf.set("coordsys", "ecef", coordinateSystem(), COORDSYS_ECEF); conf.set("coordsys", "eci", coordinateSystem(), COORDSYS_ECI); conf.set("hours", hours()); conf.set("ambient", ambient()); conf.set("quality", "default", quality(), QUALITY_DEFAULT); conf.set("quality", "low", quality(), QUALITY_LOW); conf.set("quality", "medium", quality(), QUALITY_MEDIUM); conf.set("quality", "high", quality(), QUALITY_HIGH); conf.set("quality", "best", quality(), QUALITY_BEST); return conf; } protected: virtual void mergeConfig( const Config& conf ) { ConfigOptions::mergeConfig( conf ); fromConfig( conf ); } private: void fromConfig( const Config& conf ) { conf.get("coordsys", "ecef", coordinateSystem(), COORDSYS_ECEF); conf.get("coordsys", "eci", coordinateSystem(), COORDSYS_ECI); conf.get("hours", hours()); conf.get("ambient", ambient()); conf.get("quality", "default", quality(), QUALITY_DEFAULT); conf.get("quality", "low", quality(), QUALITY_LOW); conf.get("quality", "medium", quality(), QUALITY_MEDIUM); conf.get("quality", "high", quality(), QUALITY_HIGH); conf.get("quality", "best", quality(), QUALITY_BEST); } }; /** * Interface for classes that provide sky, lighting, and other * environmental effect. */ class OSGEARTH_EXPORT SkyNode : public osg::Group { public: //! Creates a SkyNode with the default implementation. static SkyNode* create(); //! Creates a SkyNode with custom options. static SkyNode* create(const SkyOptions&); //! Creates a SkyNode from a raw driver name. static SkyNode* create(const std::string& driver); protected: // CTOR (abstract base class) SkyNode(); // CTOR (abstract base class) SkyNode(const SkyOptions& options); // protected DTOR (heap-only) virtual ~SkyNode(); public: /** * The ephemeris reference point for projected maps. Not applicable * for geocentric maps. Setting this also informs the skynode that is * should operate in projected-map mode if possible. */ void setReferencePoint(const GeoPoint& point); const GeoPoint& getReferencePoint() const { return *_refpoint; } /** * Gets/Sets the Ephemeris used to position the sun and the moon * based on date/time. */ void setEphemeris(Ephemeris* ephemeris); const Ephemeris* getEphemeris() const; /** * Whether the sky lights its subgraph. */ void setLighting(osg::StateAttribute::OverrideValue value); osg::StateAttribute::OverrideValue getLighting() const { return _lightingValue; } /** * Gets the date/time for which the environment is configured. * Pass in an optional View to get the date/time specific to * that View. */ void setDateTime(const DateTime& dt); const DateTime& getDateTime() const { return _dateTime; } //! Whether the traversal framestamp simulation time should //! be set to the sky's date time. Default is false. void setSimulationTimeTracksDateTime(bool value); bool getSimulationTimeTracksDateTime() const; /** Whether the sun is visible */ void setSunVisible(bool value); bool getSunVisible() const { return _sunVisible; } /** Whether the moon is visible */ void setMoonVisible(bool value); bool getMoonVisible() const { return _moonVisible; } /** Whether the stars are visible */ void setStarsVisible(bool value); bool getStarsVisible() const { return _starsVisible; } /** Whether the atmosphere is visible */ void setAtmosphereVisible(bool value); bool getAtmosphereVisible() const { return _atmosphereVisible; } /** Access the osg::Light representing the sun */ virtual osg::Light* getSunLight() const = 0; public: /** Attaches this sky node to a view (placing a sky light). Optional */ virtual void attach(osg::View* view, int lightNum) { } void attach(osg::View* view) { attach(view, 0); } public: // osg::Node virtual void traverse(osg::NodeVisitor& nv) override; protected: // impl class can override these events. virtual void onSetEphemeris() { } virtual void onSetDateTime() { } virtual void onSetReferencePoint() { } virtual void onSetMoonVisible() { } virtual void onSetStarsVisible() { } virtual void onSetSunVisible() { } virtual void onSetAtmosphereVisible() { } private: osg::ref_ptr _ephemeris; DateTime _dateTime; bool _sunVisible; bool _moonVisible; bool _starsVisible; bool _atmosphereVisible; osg::Vec4f _minimumAmbient; optional _refpoint; bool _simTimeTracksDateTime; osg::StateAttribute::OverrideValue _lightingValue; osg::ref_ptr _lightingUniform; void baseInit(const SkyOptions&); }; namespace Util { /** * Base class for an sky driver plugin implementation. */ class OSGEARTH_EXPORT SkyDriver : public osgDB::ReaderWriter { protected: const SkyOptions& getSkyOptions(const osgDB::Options* opt) const; }; /** * Factory interface that sky extensions need to implement. Someday we will * convert the sky extensions into proper NodeKits, at which point this method * will probably be no longer necessary since you can just link with the library * and create the SkyNode normally. */ class /*header-only*/ SkyNodeFactory { public: virtual SkyNode* createSkyNode() =0; }; } } #endif // OSGEARTHUTIL_SKY