313 lines
9.8 KiB
Plaintext
313 lines
9.8 KiB
Plaintext
|
/* -*-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.
|
||
|
*
|
||
|
* 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 Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||
|
*/
|
||
|
#ifndef OSGEARTH_TERRAIN_H
|
||
|
#define OSGEARTH_TERRAIN_H 1
|
||
|
|
||
|
#include <osgEarth/Common>
|
||
|
#include <osgEarth/TileKey>
|
||
|
#include <osgEarth/Threading>
|
||
|
#include <osg/OperationThread>
|
||
|
#include <osg/View>
|
||
|
|
||
|
namespace osgEarth
|
||
|
{
|
||
|
class Terrain;
|
||
|
class TerrainTile;
|
||
|
class SpatialReference;
|
||
|
|
||
|
/**
|
||
|
* This object is passed to terrain callbacks to provide context information
|
||
|
* and a feedback interface to terrain callback consumers.
|
||
|
*/
|
||
|
class TerrainCallbackContext
|
||
|
{
|
||
|
public:
|
||
|
const Terrain* getTerrain() const { return _terrain; }
|
||
|
|
||
|
/** Indicate that the callback should be removed immediately */
|
||
|
void remove() { _remove = true; }
|
||
|
|
||
|
/** whether the user called remove(). */
|
||
|
bool markedForRemoval() const { return _remove; }
|
||
|
|
||
|
|
||
|
public:
|
||
|
TerrainCallbackContext(Terrain* terrain)
|
||
|
: _remove(false), _terrain(terrain) { }
|
||
|
|
||
|
/** dtor */
|
||
|
virtual ~TerrainCallbackContext() { }
|
||
|
|
||
|
protected:
|
||
|
bool _remove;
|
||
|
Terrain* _terrain;
|
||
|
friend class Terrain;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Callback that you can register with the Terrain in order to receive
|
||
|
* update messaged about the terrain scene graph.
|
||
|
*/
|
||
|
class TerrainCallback : public osg::Referenced
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
* A tile was added to the terrain graph.
|
||
|
* @param key
|
||
|
* Tile key of the new tile, including the geographic extents
|
||
|
* @param graph
|
||
|
* Scene graph that can be used to intersect the tile (though it
|
||
|
* may include more than just the new tile)
|
||
|
* @param context
|
||
|
* Contextual information about the callback
|
||
|
*/
|
||
|
virtual void onTileUpdate(
|
||
|
const TileKey& key,
|
||
|
osg::Node* graph,
|
||
|
TerrainCallbackContext& context)
|
||
|
{
|
||
|
// back compat only
|
||
|
onTileAdded(key, graph, context);
|
||
|
}
|
||
|
|
||
|
/** dtor */
|
||
|
virtual ~TerrainCallback() { }
|
||
|
|
||
|
public: // deprecated - exists for backwards compatibilty only
|
||
|
|
||
|
virtual void onTileAdded(
|
||
|
const TileKey& key,
|
||
|
osg::Node* graph,
|
||
|
TerrainCallbackContext& context) { }
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Convenience adapter for hooking a callback into a class. The
|
||
|
* class must be derived from osg::Referenced. When the class
|
||
|
* destructs, the callback will automatically remove itself from
|
||
|
* the Terrain object.
|
||
|
*/
|
||
|
template<typename T>
|
||
|
class TerrainCallbackAdapter : public TerrainCallback
|
||
|
{
|
||
|
public:
|
||
|
TerrainCallbackAdapter(T* t) : _t(t) { }
|
||
|
void onTileUpdate(const TileKey& key,
|
||
|
osg::Node* tile,
|
||
|
TerrainCallbackContext& context)
|
||
|
{
|
||
|
osg::ref_ptr<T> t;
|
||
|
if (_t.lock(t))
|
||
|
t->onTileUpdate(key, tile, context);
|
||
|
else
|
||
|
context.remove();
|
||
|
}
|
||
|
protected:
|
||
|
virtual ~TerrainCallbackAdapter() { }
|
||
|
osg::observer_ptr<T> _t;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Interface for an object that can resolve the terrain elevation
|
||
|
* at a given map location.
|
||
|
*/
|
||
|
class /*interface-only*/ TerrainResolver
|
||
|
{
|
||
|
public:
|
||
|
virtual bool getHeight(
|
||
|
const SpatialReference* srs,
|
||
|
double x,
|
||
|
double y,
|
||
|
double* out_heightAboveMSL,
|
||
|
double* out_heightAboveEllipsoid =0L) const =0;
|
||
|
|
||
|
virtual bool getHeight(
|
||
|
osg::Node* patch,
|
||
|
const SpatialReference* srs,
|
||
|
double x,
|
||
|
double y,
|
||
|
double* out_heightAboveMSL,
|
||
|
double* out_heightAboveEllipsoid =0L) const =0;
|
||
|
|
||
|
/** dtor */
|
||
|
virtual ~TerrainResolver() { }
|
||
|
};
|
||
|
|
||
|
// backwards compatibility
|
||
|
typedef TerrainResolver TerrainHeightProvider;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Services for interacting with the live terrain graph. This differs from
|
||
|
* the Map model; Map represents the parametric data backing the terrain,
|
||
|
* while Terrain represents the actual geometry in memory.
|
||
|
*
|
||
|
* All returned map coordinate values are in the units conveyed in the
|
||
|
* spatial reference at getSRS().
|
||
|
*/
|
||
|
class OSGEARTH_EXPORT Terrain : public osg::Referenced, public TerrainResolver
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
* Gets the profile of the map with which this terrain is associated.
|
||
|
*/
|
||
|
const Profile* getProfile() const { return _profile.get(); }
|
||
|
|
||
|
/**
|
||
|
* Gets the spatial reference of the map with which this terrain is
|
||
|
* associated.
|
||
|
*/
|
||
|
const SpatialReference* getSRS() const { return _profile->getSRS(); }
|
||
|
|
||
|
/**
|
||
|
* Returns the world coordinates under the mouse.
|
||
|
* @param view
|
||
|
* View in which to do the query
|
||
|
* @param mx, my
|
||
|
* Mouse coordinates
|
||
|
* @param out_coords
|
||
|
* Stores the world coordinates under the mouse (when returning true)
|
||
|
*/
|
||
|
bool getWorldCoordsUnderMouse(
|
||
|
osg::View* view,
|
||
|
float mx,
|
||
|
float my,
|
||
|
osg::Vec3d& out_world) const;
|
||
|
|
||
|
//! Terrain Tile node under the mouse
|
||
|
TerrainTile* getTerrainTileUnderMouse(
|
||
|
osg::View* view,
|
||
|
float mx,
|
||
|
float my) const;
|
||
|
|
||
|
|
||
|
public: // TerrainResolver interface
|
||
|
|
||
|
/**
|
||
|
* Intersects the terrain at the location x, y and returns the height data.
|
||
|
*
|
||
|
* @param srs
|
||
|
* Spatial reference system of (x,y) coordinates
|
||
|
* @param x, y
|
||
|
* Coordinates at which to query the height
|
||
|
* @param out_heightAboveMSL
|
||
|
* The resulting relative height goes here. The height is relative to MSL
|
||
|
* (mean sea level) as expressed by the map's vertical datum.
|
||
|
* @param out_heightAboveEllipsoid
|
||
|
* The resulting geodetic height goes here. The height is relative to the
|
||
|
* geodetic ellipsoid expressed by the map's SRS.
|
||
|
*/
|
||
|
bool getHeight(
|
||
|
const SpatialReference* srs,
|
||
|
double x,
|
||
|
double y,
|
||
|
double* out_heightAboveMSL,
|
||
|
double* out_heightAboveEllipsoid =0L) const;
|
||
|
|
||
|
/**
|
||
|
* Save as above, but specify a subgraph patch.
|
||
|
*/
|
||
|
bool getHeight(
|
||
|
osg::Node* patch,
|
||
|
const SpatialReference* srs,
|
||
|
double x,
|
||
|
double y,
|
||
|
double* out_heightAboveMSL,
|
||
|
double* out_heightAboveEllipsoid =0L) const;
|
||
|
|
||
|
public:
|
||
|
/**
|
||
|
* Adds a terrain callback.
|
||
|
*
|
||
|
* @param callback
|
||
|
* Terrain callback to add. This will get called whenever tile data changes in
|
||
|
* the active terrain graph
|
||
|
*/
|
||
|
void addTerrainCallback(TerrainCallback* callback);
|
||
|
|
||
|
/**
|
||
|
* Removes a terrain callback.
|
||
|
*/
|
||
|
void removeTerrainCallback(TerrainCallback* callback );
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Accept a node visitor on the terrain's scene graph.
|
||
|
*/
|
||
|
void accept( osg::NodeVisitor& nv );
|
||
|
|
||
|
// access the raw terrain graph
|
||
|
osg::Node* getGraph() const { return _graph.get(); }
|
||
|
|
||
|
// queues the onTileUpdate callback (internal)
|
||
|
void notifyTileUpdate( const TileKey& key, osg::Node* tile );
|
||
|
|
||
|
// queues the onTileRemoved callback (internal)
|
||
|
void notifyTilesRemoved(const std::vector<TileKey>& keys);
|
||
|
|
||
|
// internal
|
||
|
void notifyMapElevationChanged();
|
||
|
|
||
|
/** dtor */
|
||
|
virtual ~Terrain() { }
|
||
|
|
||
|
private:
|
||
|
//! Construct the Terrain graph interface
|
||
|
Terrain(osg::Node* graph, const Profile* profile);
|
||
|
|
||
|
/** update traversal. */
|
||
|
void update();
|
||
|
|
||
|
friend class TerrainEngineNode;
|
||
|
|
||
|
typedef std::list< osg::ref_ptr<TerrainCallback> > CallbackList;
|
||
|
|
||
|
CallbackList _callbacks;
|
||
|
Threading::ReadWriteMutex _callbacksMutex;
|
||
|
std::atomic_int _callbacksSize; // separate size tracker for MT size check w/o a lock
|
||
|
|
||
|
osg::ref_ptr<const Profile> _profile;
|
||
|
osg::observer_ptr<osg::Node> _graph;
|
||
|
|
||
|
osg::ref_ptr<osg::OperationQueue> _updateQueue;
|
||
|
|
||
|
void fireMapElevationChanged();
|
||
|
void fireTileUpdate( const TileKey& key, osg::Node* tile );
|
||
|
void fireTilesRemoved(const std::vector<TileKey>& keys);
|
||
|
|
||
|
struct onTileUpdateOperation : public osg::Operation {
|
||
|
osg::observer_ptr<Terrain> _terrain;
|
||
|
TileKey _key;
|
||
|
osg::observer_ptr<osg::Node> _node;
|
||
|
unsigned _count;
|
||
|
onTileUpdateOperation(const TileKey& key, osg::Node* node, Terrain* terrain);
|
||
|
void operator()(osg::Object*);
|
||
|
int _delay;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif // OSGEARTH_COMPOSITING_H
|