DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/TerrainEngineNode
2024-12-25 07:49:36 +08:00

382 lines
14 KiB
C++

/* -*-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/>
*/
#pragma once
#include <osgEarth/Map>
#include <osgEarth/Terrain>
#include <osgEarth/TerrainOptions>
#include <osgEarth/TerrainEffect>
#include <osgEarth/TerrainTileModelFactory>
#include <osgEarth/TerrainTileNode>
#include <osgEarth/TerrainEngineRequirements>
#include <osgEarth/TerrainResources>
#include <osgEarth/ShaderUtils>
#include <osgEarth/Progress>
#include <osgEarth/TileKey>
#include <osg/CoordinateSystemNode>
#include <osg/Geode>
#include <osg/NodeCallback>
#include <osg/BoundingBox>
#include <osgUtil/RenderBin>
#include <set>
#define OSGEARTH_ENV_TERRAIN_ENGINE_DRIVER "OSGEARTH_TERRAIN_ENGINE"
namespace osgUtil {
class CullVisitor;
}
namespace osgEarth
{
class TerrainEffect;
class VirtualProgram;
namespace Util
{
class TerrainEngineNodeFactory;
}
/**
* Terrain Engine interface. (Pure virtual)
* Access to the low-level API for the terrain engine, the node graph that
* renders the planet's surface.
*/
class /*interface*/ TerrainEngine
{
public:
/**
* Callback for customizing the TileModel.
*/
class CreateTileModelCallback : public osg::Referenced
{
public:
virtual void onCreateTileModel(
TerrainEngineNode* engine,
TerrainTileModel* model) = 0;
};
using ComputeTileRangeCallback = std::function<float(osg::Node* node, osg::NodeVisitor& nv)>;
using ComputeTilePixelSizeCallback = std::function<float(osg::Node* node, osg::NodeVisitor& nv)>;
public:
//! Unique ID of the terrain engine instance
virtual UID getUID() const = 0;
//! Create a tile data model from the map
virtual TerrainTileModel* createTileModel(
const Map* map,
const TileKey& key,
const CreateTileManifest& manifest,
ProgressCallback* progress) = 0;
//! Access the shared GL resources associated with the terrain engine
virtual TerrainResources* getResources() const = 0;
//! Map associated with this terrain engine
virtual const Map* getMap() const = 0;
//! Gets the Terrain interface for interacting with the scene graph
virtual Terrain* getTerrain() = 0;
virtual const Terrain* getTerrain() const = 0;
//! Adds a terrain effect
virtual void addEffect(TerrainEffect* effect) = 0;
//! Removes a terrain effect
virtual void removeEffect(TerrainEffect* effect) = 0;
//! Marks the terrain tiles intersecting the provied extent as invalid
virtual void invalidateRegion(const GeoExtent& extent) = 0;
//! Marks the terrain tiles intersecting the provied extent as invalid
virtual void invalidateRegion(
const GeoExtent& extent,
unsigned minLevel) = 0;
//! Marks the terrain tiles intersecting the provied extent as invalid
virtual void invalidateRegion(
const GeoExtent& extent,
unsigned minLevel,
unsigned maxLevel) = 0;
//! Marks the terrain tiles intersecting the provied extent as invalid
virtual void invalidateRegion(
const std::vector<const Layer*> layers,
const GeoExtent& extent,
unsigned minLevel,
unsigned maxLevel) = 0;
//! Marks the terrain tiles intersecting the provied extent as invalid
virtual void invalidateRegion(
const std::vector<const Layer*> layers,
const GeoExtent& extent) = 0;
//! Access the stateset used to render the entire terrain.
virtual osg::StateSet* getTerrainStateSet() = 0;
//! Access the stateset used to render terrain surface layers.
virtual osg::StateSet* getSurfaceStateSet() = 0;
//! Scene graph root of the terrain engine
virtual osg::Node* getNode() = 0;
//! Adds a TileModel creation callback, so you can add custom data
//! to the TileModel after it's created.
virtual void addCreateTileModelCallback(CreateTileModelCallback* callback) = 0;
virtual void removeCreateTileModelCallback(CreateTileModelCallback* callback) = 0;
//! Create a standalone terrain tile. This method is not used by the
//! actual terrain engine, but rather exists to support external
//! processes that need tile geometry. The terrain engine implementation
//! may or may not provide this capability and will return NULL if
//! it does not.
//! @param model Tile model for which to build a tile
//! @param flags Bitwise-OR of the CreateTileFlags enums (MAY BE IGNORED)
//! @param referenceLOD If non-zero, adjust the vertex dimensions of the returned tile
//! to match this LOD. Example: ask for a tile at tileKey.lod=15, tile is 17x17.
//! Specific a referenceLOD=16, tile will be 33x33.
//! @param area Restrict the processed area to a subarea of the tile model.
//! If not valid then the entire tile model will be used.
virtual osg::Node* createStandaloneTile(
const TerrainTileModel* model,
int createTileFlags,
unsigned referenceLOD,
const TileKey& subRegion) = 0;
//! Returns the name of the JobArena that handles terrain tile loading,
//! or an empty string if the engine does not use an arena.
virtual std::string getJobArenaName() const { return ""; }
//! Access an immutable options API
virtual TerrainOptionsAPI getOptions() = 0;
//! Number of terrain tiles resident in memory
//! (including cached dormant tiles not being rendered)
virtual unsigned getNumResidentTiles() const = 0;
//! Tell the engine you updates options.
virtual void dirtyTerrainOptions() = 0;
//! Set a function that computes the on-screen size of a tile
//! for the purposes of LOD selection.
virtual void setComputeTilePixelSizeCallback(const ComputeTilePixelSizeCallback& callback) = 0;
//! Set a function that computes the range of a tile for the purposes of culling.
virtual void setComputeTileRangeCallback(const ComputeTileRangeCallback& callback) = 0;
};
/**
* TerrainEngineNode is the base class and interface for map engine implementations.
*
* A map engine lives under a MapNode and is responsible for generating the
* actual geometry representing the Earth.
*/
class OSGEARTH_EXPORT TerrainEngineNode : public osg::CoordinateSystemNode, public TerrainEngine
{
public:
TerrainTileModel* createTileModel(
const Map* map,
const TileKey& key,
const CreateTileManifest& manifest,
ProgressCallback* progress) override;
const Map* getMap() const override { return _map.get(); }
TerrainResources* getResources() const override;
virtual const TerrainEngineRequirements& getRequirements() const = 0;
Terrain* getTerrain() override { return _terrainInterface.get(); }
const Terrain* getTerrain() const override { return _terrainInterface.get(); }
void addEffect( TerrainEffect* effect ) override;
void removeEffect( TerrainEffect* effect ) override;
void invalidateRegion(const GeoExtent& extent) override {
invalidateRegion(extent, 0, INT_MAX);
}
void invalidateRegion(const GeoExtent& extent, unsigned minLevel) override {
invalidateRegion(extent, minLevel, INT_MAX);
}
virtual void invalidateRegion(const GeoExtent& extent, unsigned minLevel, unsigned maxLevel) override {
//NOP by default
}
virtual void invalidateRegion(
const std::vector<const Layer*> layers,
const GeoExtent& extent,
unsigned minLevel,
unsigned maxLevel) override
{
//NOP by default
}
void invalidateRegion(
const std::vector<const Layer*> layers,
const GeoExtent& extent) override
{
invalidateRegion(layers, extent, 0, INT_MAX);
}
virtual osg::StateSet* getSurfaceStateSet() override { return getOrCreateStateSet(); }
//! Adds a TileModel creation callback, so you can add custom data
//! to the TileModel after it's created.
void addCreateTileModelCallback(CreateTileModelCallback* callback) override;
void removeCreateTileModelCallback(CreateTileModelCallback* callback) override;
//! Flags supporting the createStandaloneTile method
enum CreateTileFlags
{
CREATE_TILE_INCLUDE_TILES_WITH_MASKS = 1,
CREATE_TILE_INCLUDE_TILES_WITHOUT_MASKS = 2,
CREATE_TILE_INCLUDE_ALL = ~0
};
//! Create a standalone terrain tile. This method is not used by the
//! actual terrain engine, but rather exists to support external
//! processes that need tile geometry. The terrain engine implementation
//! may or may not provide this capability and will return NULL if
//! it does not.
//! @param model Tile model for which to build a tile
//! @param flags Bitwise-OR of the CreateTileFlags enums (MAY BE IGNORED)
//! @param referenceLOD If non-zero, adjust the vertex dimensions of the returned tile
//! to match this LOD. Example: ask for a tile at tileKey.lod=15, tile is 17x17.
//! Specific a referenceLOD=16, tile will be 33x33.
//! @param area Restrict the processed area to a subarea of the tile model.
//! If not valid then the entire tile model will be used.
virtual osg::Node* createStandaloneTile(
const TerrainTileModel* model,
int createTileFlags,
unsigned referenceLOD,
const TileKey& subRegion) { return nullptr; }
//! Shut down the engine
virtual void shutdown();
void setComputeTileRangeCallback(const ComputeTileRangeCallback& callback) override { _computeTileRangeCallback = callback; }
void setComputeTilePixelSizeCallback(const ComputeTilePixelSizeCallback& callback) override { _computeTilePixelSizeCallback = callback; }
ComputeTileRangeCallback& getComputeTileRangeCallback() { return _computeTileRangeCallback; }
ComputeTilePixelSizeCallback& getComputeTilePixelSizeCallback() { return _computeTilePixelSizeCallback; }
//! Return the top level node associated with the terrain.
osg::Node* getNode() override {
return this;
}
//! API for accessing or changing terrain options.
//! You should call dirtyTerrainOptions() after changing the options.
TerrainOptionsAPI getOptions() override {
return TerrainOptionsAPI(&_optionsConcrete);
}
//! Subclass may override this to do something when the terrain options change
virtual void dirtyTerrainOptions() { }
public:
class OSGEARTH_EXPORT ModifyTileBoundingBoxCallback : public osg::Referenced
{
public:
virtual void modifyBoundingBox(const TileKey& key, osg::BoundingBox& box) const =0;
};
void addModifyTileBoundingBoxCallback(ModifyTileBoundingBoxCallback* callback);
void removeModifyTileBoundingBoxCallback(ModifyTileBoundingBoxCallback* callback);
public:
static TerrainEngineNode* create(const TerrainOptions& options);
protected:
TerrainEngineNode();
virtual ~TerrainEngineNode();
public: // osg::Node overrides
virtual osg::BoundingSphere computeBound() const;
virtual void traverse( osg::NodeVisitor& );
protected:
friend class MapNode;
friend class TerrainEngineNodeFactory;
//! Assigns a map to render
void setMap(const Map* map, const TerrainOptions& options);
//! Subclass runs this after a call to setMap.
virtual void onSetMap() { }
// signals that a redraw is needed because something changed.
virtual void requestRedraw();
// Request the state setup be refreshed because something has changed that requires new
// shaders, state, etc.
virtual void dirtyState() { }
osg::ref_ptr<TerrainResources> _textureResourceTracker;
osg::ref_ptr<const Map> _map;
private:
friend struct TerrainEngineNodeCallbackProxy;
void onMapModelChanged( const MapModelChange& change );
virtual void updateTextureCombining() { }
protected:
osg::ref_ptr<Terrain> _terrainInterface;
unsigned _dirtyCount;
bool _updateScheduled;
TerrainOptions _optionsConcrete;
typedef std::vector<osg::ref_ptr<TerrainEffect> > TerrainEffectVector;
TerrainEffectVector effects_;
typedef std::vector<osg::ref_ptr<CreateTileModelCallback> > CreateTileModelCallbacks;
CreateTileModelCallbacks _createTileModelCallbacks;
mutable Threading::ReadWriteMutex _createTileModelCallbacksMutex;
typedef std::vector<osg::ref_ptr<ModifyTileBoundingBoxCallback> > ModifyTileBoundingBoxCallbacks;
ModifyTileBoundingBoxCallbacks _modifyTileBoundingBoxCallbacks;
osg::ref_ptr<TerrainTileModelFactory> _tileModelFactory;
ComputeTileRangeCallback _computeTileRangeCallback;
ComputeTilePixelSizeCallback _computeTilePixelSizeCallback;
public:
// internal
void fireModifyTileBoundingBoxCallbacks(const TileKey& key, osg::BoundingBox& box);
/** Access a typed effect. */
template<typename T>
T* getEffect() {
for(TerrainEffectVector::iterator i = effects_.begin(); i != effects_.end(); ++i ) {
T* e = dynamic_cast<T*>(i->get());
if ( e ) return e;
}
return 0L;
}
};
} // namespace osgEarth