1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSGTERRAIN_TERRAINTILE
15#define OSGTERRAIN_TERRAINTILE 1
16
17#include <osg/Group>
18#include <osg/CoordinateSystemNode>
19
20#include <osgDB/ReaderWriter>
21
22#include <osgTerrain/TerrainTechnique>
23#include <osgTerrain/Layer>
24#include <osgTerrain/Locator>
25
26namespace osgTerrain {
27
28class Terrain;
29
30class OSGTERRAIN_EXPORT TileID
31{
32    public:
33
34        TileID();
35
36        TileID(int in_level, int in_x, int in_y);
37
38        bool operator == (const TileID& rhs) const
39        {
40            return (level==rhs.level) && (x==rhs.x) && (y==rhs.y);
41        }
42
43        bool operator != (const TileID& rhs) const
44        {
45            return (level!=rhs.level) || (x!=rhs.x) || (y!=rhs.y);
46        }
47
48        bool operator < (const TileID& rhs) const
49        {
50            if (level<rhs.level) return true;
51            if (level>rhs.level) return false;
52            if (x<rhs.x) return true;
53            if (x>rhs.x) return false;
54            return y<rhs.y;
55        }
56
57        bool valid() const { return level>=0; }
58
59        int level;
60        int x;
61        int y;
62};
63
64
65/** Terrain provides a framework for loosely coupling height field data with height rendering algorithms.
66  * This allows TerrainTechnique's to be plugged in at runtime.*/
67class OSGTERRAIN_EXPORT TerrainTile : public osg::Group
68{
69    public:
70
71        TerrainTile();
72
73        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
74        TerrainTile(const TerrainTile&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
75
76        META_Node(osgTerrain, TerrainTile);
77
78        virtual void traverse(osg::NodeVisitor& nv);
79
80        /** Call init on any attached TerrainTechnique.*/
81        void init(int dirtyMask, bool assumeMultiThreaded);
82
83        /** Set the Terrain that this Terrain tile is a member of.*/
84        void setTerrain(Terrain* ts);
85
86        /** Get the Terrain that this Terrain tile is a member of.*/
87        Terrain* getTerrain() { return _terrain; }
88
89        /** Get the const Terrain that this Terrain tile is a member of.*/
90        const Terrain* getTerrain() const { return _terrain; }
91
92
93        /** Set the TileID (layer, x,y) of the TerrainTile.
94          * The TileID is used so it can be located by its neighbours
95          * via the enclosing Terrain node that manages a map of TileID to TerraiTiles.*/
96        void setTileID(const TileID& tileID);
97
98        /** Get the TileID (layer, x,y) of the TerrainTile.*/
99        const TileID& getTileID() const { return _tileID; }
100
101
102        /** Set the TerrainTechnique*/
103        void setTerrainTechnique(TerrainTechnique* terrainTechnique);
104
105        template<class T> void setTerrainTechnique(const osg::ref_ptr<T>& terrainTechnique) { setTerrainTechnique(terrainTechnique.get()); }
106
107        /** Get the TerrainTechnique*/
108        TerrainTechnique* getTerrainTechnique() { return _terrainTechnique.get(); }
109
110        /** Get the const TerrainTechnique*/
111        const TerrainTechnique* getTerrainTechnique() const { return _terrainTechnique.get(); }
112
113
114        /** Set the coordinate frame locator of the terrain node.
115          * The locator takes non-dimensional s,t coordinates into the X,Y,Z world coords and back.*/
116        void setLocator(Locator* locator) { _locator = locator; }
117
118        template<class T> void setLocator(const osg::ref_ptr<T>& locator) { setLocator(locator.get()); }
119
120        /** Get the coordinate frame locator of the terrain node.*/
121        Locator* getLocator() { return _locator.get(); }
122
123        /** Get the const coordinate frame locator of the terrain node.*/
124        const Locator* getLocator() const { return _locator.get(); }
125
126        /** Set the layer to use to define the elevations of the terrain.*/
127        void setElevationLayer(Layer* layer);
128
129        template<class T> void setElevationLayer(const osg::ref_ptr<T>& layer) { setElevationLayer(layer.get()); }
130
131        /** Get the layer to use to define the elevations of the terrain.*/
132        Layer* getElevationLayer() { return _elevationLayer.get(); }
133
134        /** Get the const layer to use to define the elevations of the terrain.*/
135        const Layer* getElevationLayer() const { return _elevationLayer.get(); }
136
137
138        /** Set a color layer with specified layer number.*/
139        void setColorLayer(unsigned int i, Layer* layer);
140
141        template<class T> void setColorLayer(unsigned int i, const osg::ref_ptr<T>& layer) { setColorLayer(i, layer.get()); }
142
143        /** Get color layer with specified layer number.*/
144        Layer* getColorLayer(unsigned int i) { return i<_colorLayers.size() ? _colorLayers[i].get() : 0; }
145
146        /** Set const color layer with specified layer number.*/
147        const Layer* getColorLayer(unsigned int i) const { return i<_colorLayers.size() ? _colorLayers[i].get() : 0; }
148
149        /** Get the number of colour layers.*/
150        unsigned int getNumColorLayers() const { return _colorLayers.size(); }
151
152
153        /** Set hint to whether the TerrainTechnique should create per vertex normals for lighting purposes.*/
154        void setRequiresNormals(bool flag) { _requiresNormals = flag; }
155
156        /** Get whether the TerrainTechnique should create per vertex normals for lighting purposes.*/
157        bool getRequiresNormals() const { return _requiresNormals; }
158
159
160        /** Set the hint to whether the TerrainTechnique should treat the invalid Layer entries that at are neighbours to valid entries with the default value.*/
161        void setTreatBoundariesToValidDataAsDefaultValue(bool flag) { _treatBoundariesToValidDataAsDefaultValue = flag; }
162
163        /** Get whether the TeatBoundariesToValidDataAsDefaultValue hint.*/
164        bool getTreatBoundariesToValidDataAsDefaultValue() const { return _treatBoundariesToValidDataAsDefaultValue; }
165
166
167        enum BlendingPolicy
168        {
169            INHERIT, /** Default - check for the any BlendingPolicy set on the enclosing osgTerrain::Terrain node, and if it's also INHERIT then assume ENABLE_BLENDING_WHEN_ALPHA_PRESENT. */
170            DO_NOT_SET_BLENDING,
171            ENABLE_BLENDING,
172            ENABLE_BLENDING_WHEN_ALPHA_PRESENT /** check colour layers for alpha value and if present enable blending. */
173        };
174
175        /** Set the policy to use when deciding whether to enable/disable blending and use of transparent bin.*/
176        void setBlendingPolicy(BlendingPolicy policy) { _blendingPolicy = policy; }
177
178        /** Get the policy to use when deciding whether to enable/disable blending and use of transparent bin.*/
179        BlendingPolicy getBlendingPolicy() const { return _blendingPolicy; }
180
181
182        enum DirtyMask
183        {
184            NOT_DIRTY = 0,
185            IMAGERY_DIRTY = 1<<0,
186            ELEVATION_DIRTY = 1<<1,
187            LEFT_EDGE_DIRTY = 1<<2,
188            RIGHT_EDGE_DIRTY = 1<<3,
189            TOP_EDGE_DIRTY = 1<<4,
190            TOP_LEFT_CORNER_DIRTY = 1<<5,
191            TOP_RIGHT_CORNER_DIRTY = 1<<6,
192            BOTTOM_EDGE_DIRTY = 1<<7,
193            BOTTOM_LEFT_CORNER_DIRTY = 1<<8,
194            BOTTOM_RIGHT_CORNER_DIRTY = 1<<9,
195            EDGES_DIRTY = LEFT_EDGE_DIRTY | RIGHT_EDGE_DIRTY | TOP_EDGE_DIRTY | BOTTOM_EDGE_DIRTY |
196                          TOP_LEFT_CORNER_DIRTY | TOP_RIGHT_CORNER_DIRTY | BOTTOM_LEFT_CORNER_DIRTY | BOTTOM_RIGHT_CORNER_DIRTY,
197            ALL_DIRTY = IMAGERY_DIRTY | ELEVATION_DIRTY | EDGES_DIRTY
198        };
199
200        /** Set the dirty flag on/off.*/
201        void setDirty(bool dirty) { setDirtyMask(dirty ? ALL_DIRTY : NOT_DIRTY); }
202
203        /** return true if the any of the DirtyMask are set.*/
204        int getDirty() const { return _dirtyMask!=NOT_DIRTY; }
205
206
207        /** Set the dirty flag on/off.*/
208        void setDirtyMask(int dirtyMask);
209
210        /** return true if the tile is dirty and needs to be updated,*/
211        int getDirtyMask() const { return _dirtyMask; }
212
213
214        /** Compute the bounding volume of the terrain by computing the union of the bounding volumes of all layers.*/
215        virtual osg::BoundingSphere computeBound() const;
216
217        /** Callback for post processing loaded TerrainTile, and for filling in missing elements such as external external imagery.*/
218        struct TileLoadedCallback : public osg::Referenced
219        {
220            virtual bool deferExternalLayerLoading() const = 0;
221            virtual void loaded(osgTerrain::TerrainTile* tile, const osgDB::ReaderWriter::Options* options) const = 0;
222        };
223
224        static void setTileLoadedCallback(TileLoadedCallback* lc);
225        static osg::ref_ptr<TileLoadedCallback>& getTileLoadedCallback();
226
227        /** If State is non-zero, this function releases any associated OpenGL objects for
228        * the specified graphics context. Otherwise, releases OpenGL objects
229        * for all graphics contexts. */
230        virtual void releaseGLObjects(osg::State* = 0) const;
231
232
233    protected:
234
235        virtual ~TerrainTile();
236
237        typedef std::vector< osg::ref_ptr<Layer> > Layers;
238
239        friend class Terrain;
240
241        Terrain*                            _terrain;
242
243        int                                 _dirtyMask;
244        bool                                _hasBeenTraversal;
245
246        TileID                              _tileID;
247
248        osg::ref_ptr<TerrainTechnique>      _terrainTechnique;
249        osg::ref_ptr<Locator>               _locator;
250
251        osg::ref_ptr<Layer>                 _elevationLayer;
252
253        Layers                              _colorLayers;
254
255        bool                                _requiresNormals;
256        bool                                _treatBoundariesToValidDataAsDefaultValue;
257        BlendingPolicy                      _blendingPolicy;
258};
259
260/** Helper callback for managing optional sets of layers, that loading of is deffered to this callback,
261  * with this callback working out which layers to load, and how to create fallback versions of the layers.
262*/
263class OSGTERRAIN_EXPORT WhiteListTileLoadedCallback : public TerrainTile::TileLoadedCallback
264{
265    public:
266
267        WhiteListTileLoadedCallback();
268
269        void allow(const std::string& setname) { _setWhiteList.insert(setname); }
270
271        void setMinimumNumOfLayers(unsigned int numLayers) { _minumumNumberOfLayers = numLayers; }
272        unsigned int getMinimumNumOfLayers() const { return _minumumNumberOfLayers; }
273
274        void setReplaceSwitchLayer(bool replaceSwitchLayer) { _replaceSwitchLayer = replaceSwitchLayer; }
275        bool getReplaceSwitchLayer() const { return _replaceSwitchLayer; }
276
277        void setAllowAll(bool allowAll) { _allowAll = allowAll; }
278        bool getAllowAll() const { return _allowAll; }
279
280        bool layerAcceptable(const std::string& setname) const;
281        bool readImageLayer(osgTerrain::ImageLayer* imageLayer, const osgDB::ReaderWriter::Options* options) const;
282
283        virtual bool deferExternalLayerLoading() const;
284
285        virtual void loaded(osgTerrain::TerrainTile* tile, const osgDB::ReaderWriter::Options* options) const;
286
287    protected:
288
289        virtual ~WhiteListTileLoadedCallback();
290
291        typedef std::set<std::string> SetWhiteList;
292        SetWhiteList    _setWhiteList;
293        unsigned int    _minumumNumberOfLayers;
294        bool            _replaceSwitchLayer;
295        bool            _allowAll;
296
297};
298
299}
300
301#endif
302