1/* -*-c++-*- */
2/* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2019 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>
18 */
19#ifndef OSGEARTH_UTIL_FRACTAL_ELEVATION_LAYER
20#define OSGEARTH_UTIL_FRACTAL_ELEVATION_LAYER 1
21
22#include <osgEarthUtil/Common>
23#include <osgEarth/TileSource>
24#include <osgEarth/ElevationLayer>
25#include <osgEarth/LayerListener>
26#include <osgEarth/URI>
27#include <osgEarth/LandCoverLayer>
28
29namespace osgEarth { namespace Util
30{
31    using namespace osgEarth;
32
33    struct FractalElevationLayerLandCoverMapping
34    {
35        std::string className;
36        optional<float> amplitude;
37    };
38
39    typedef std::map<std::string, FractalElevationLayerLandCoverMapping> FractalElevationLayerLandCoverMap;
40
41
42    /**
43     * Serializable options to configure a FractalElevationLayer.
44     */
45    class OSGEARTHUTIL_EXPORT FractalElevationLayerOptions : public ElevationLayerOptions
46    {
47
48    public:
49        // constructor
50        FractalElevationLayerOptions(const ConfigOptions& co = ConfigOptions());
51
52        //! Simplex noise frequency
53        optional<float>& frequency() { return _frequency; }
54        const optional<float>& frequency() const { return _frequency; }
55
56        //! Simplex noise persistence
57        optional<float>& persistence() { return _persistence; }
58        const optional<float>& persistence() const { return _persistence; }
59
60        //! Simplex noise lacunarity
61        optional<float>& lacunarity() { return _lacunarity; }
62        const optional<float>& lacunarity() const { return _lacunarity; }
63
64        //! Reference LOD
65        optional<unsigned>& baseLOD() { return _baseLOD; }
66        const optional<unsigned>& baseLOD() const { return _baseLOD; }
67
68        //! Maximum change in elevation (total)
69        optional<float>& amplitude() { return _amplitude; }
70        const optional<float>& amplitude() const { return _amplitude; }
71
72        //! Mappings from land cover classes to amplitude values (optional)
73        FractalElevationLayerLandCoverMap& landCoverMap() { return _lcMap; }
74        const FractalElevationLayerLandCoverMap& landCoverMap() const { return _lcMap; }
75
76        //! URI of a noise texture to use to augment to simplex noise
77        optional<URI>& noiseImageURI() { return _noiseImageURI; }
78        const optional<URI>& noiseImageURI() const { return _noiseImageURI; }
79
80    public:
81        Config getConfig() const;
82
83    protected:
84        void mergeConfig(const Config& conf) {
85            ElevationLayerOptions::mergeConfig(conf);
86            fromConfig(conf);
87        }
88
89        void fromConfig(const Config& conf);
90
91    private:
92        optional<float> _frequency;
93        optional<float> _persistence;
94        optional<float> _lacunarity;
95        optional<unsigned> _octaves;
96        optional<unsigned> _baseLOD;
97        optional<float> _amplitude;
98        optional<URI> _noiseImageURI;
99        FractalElevationLayerLandCoverMap _lcMap;
100
101    };
102
103
104    /**
105     * Elevation layer that adds fractal noise offset values.
106     */
107    class OSGEARTHUTIL_EXPORT FractalElevationLayer : public ElevationLayer
108    {
109    public:
110        META_Layer(osgEarth, FractalElevationLayer, FractalElevationLayerOptions, fractal_elevation);
111
112        //! Create a blank layer to be configurated through options().
113        FractalElevationLayer();
114
115        //! Create a layer with initial options.
116        FractalElevationLayer(const FractalElevationLayerOptions& options);
117
118    public: // ElevationLayer
119
120        // opens the layer and returns the status
121        virtual const Status& open();
122
123        virtual void init();
124
125    protected: // Layer
126
127        // called by the map when this layer is added/removed
128        virtual void addedToMap(const class Map*);
129
130        virtual void removedFromMap(const class Map*);
131
132        virtual void createImplementation(
133            const TileKey& key,
134            osg::ref_ptr<osg::HeightField>& out_hf,
135            osg::ref_ptr<NormalMap>& out_normalMap,
136            ProgressCallback* progress);
137
138    protected:
139
140        virtual ~FractalElevationLayer();
141
142        osg::observer_ptr<LandCoverLayer> _landCover;
143        osg::observer_ptr<LandCoverDictionary> _landCoverDict;
144
145        bool _debug;
146        osg::ref_ptr<osg::Image> _noiseImage1;
147        osg::ref_ptr<osg::Image> _noiseImage2;
148
149        const FractalElevationLayerLandCoverMapping* getMapping(const LandCoverClass*) const;
150    };
151
152} } // namespace osgEarth::Util
153
154#endif // OSGEARTH_UTIL_FRACTAL_ELEVATION_LAYER
155