Splitting tile providers back into individual files

This commit is contained in:
Alexander Bock
2021-12-30 11:52:34 +01:00
parent 4c9337a465
commit cd2fc3f88a
32 changed files with 2853 additions and 2355 deletions
+10 -10
View File
@@ -286,13 +286,13 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
_reset.onChange([&]() {
if (_tileProvider) {
tileprovider::reset(*_tileProvider);
_tileProvider->reset();
}
});
_remove.onChange([&]() {
if (_tileProvider) {
tileprovider::reset(*_tileProvider);
_tileProvider->reset();
_parent.deleteLayer(identifier());
}
});
@@ -360,13 +360,13 @@ void Layer::initialize() {
ZoneScoped
if (_tileProvider) {
tileprovider::initialize(*_tileProvider);
_tileProvider->initialize();
}
}
void Layer::deinitialize() {
if (_tileProvider) {
tileprovider::deinitialize(*_tileProvider);
_tileProvider->deinitialize();
}
}
@@ -374,7 +374,7 @@ ChunkTilePile Layer::chunkTilePile(const TileIndex& tileIndex, int pileSize) con
ZoneScoped
if (_tileProvider) {
return tileprovider::chunkTilePile(*_tileProvider, tileIndex, pileSize);
return _tileProvider->chunkTilePile(tileIndex, pileSize);
}
else {
ChunkTilePile chunkTilePile;
@@ -390,7 +390,7 @@ ChunkTilePile Layer::chunkTilePile(const TileIndex& tileIndex, int pileSize) con
Tile::Status Layer::tileStatus(const TileIndex& index) const {
return _tileProvider ?
tileprovider::tileStatus(*_tileProvider, index) :
_tileProvider->tileStatus(index) :
Tile::Status::Unavailable;
}
@@ -404,7 +404,7 @@ layergroupid::BlendModeID Layer::blendMode() const {
TileDepthTransform Layer::depthTransform() const {
return _tileProvider ?
tileprovider::depthTransform(*_tileProvider) :
_tileProvider->depthTransform() :
TileDepthTransform{ 1.f, 0.f };
}
@@ -416,7 +416,7 @@ bool Layer::enabled() const {
return _enabled;
}
tileprovider::TileProvider* Layer::tileProvider() const {
TileProvider* Layer::tileProvider() const {
return _tileProvider.get();
}
@@ -440,7 +440,7 @@ void Layer::update() {
ZoneScoped
if (_tileProvider) {
tileprovider::update(*_tileProvider);
_tileProvider->update();
}
}
@@ -483,7 +483,7 @@ void Layer::initializeBasedOnType(layergroupid::TypeID id, ghoul::Dictionary ini
std::string name = initDict.value<std::string>(KeyName);
LDEBUG("Initializing tile provider for layer: '" + name + "'");
}
_tileProvider = tileprovider::createFromDictionary(id, std::move(initDict));
_tileProvider = TileProvider::createFromDictionary(id, std::move(initDict));
break;
}
case layergroupid::TypeID::SolidColor: {
+4 -5
View File
@@ -30,7 +30,7 @@
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/layeradjustment.h>
#include <modules/globebrowsing/src/layerrendersettings.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
@@ -40,8 +40,7 @@ namespace openspace::globebrowsing {
struct LayerGroup;
struct TileIndex;
namespace tileprovider { struct TileProvider; }
struct TileProvider;
class Layer : public properties::PropertyOwner {
public:
@@ -59,7 +58,7 @@ public:
TileDepthTransform depthTransform() const;
void setEnabled(bool enabled);
bool enabled() const;
tileprovider::TileProvider* tileProvider() const;
TileProvider* tileProvider() const;
glm::vec3 solidColor() const;
const LayerRenderSettings& renderSettings() const;
const LayerAdjustment& layerAdjustment() const;
@@ -89,7 +88,7 @@ private:
properties::StringProperty _guiDescription;
layergroupid::TypeID _type;
std::unique_ptr<tileprovider::TileProvider> _tileProvider;
std::unique_ptr<TileProvider> _tileProvider;
properties::Vec3Property _solidColor;
LayerRenderSettings _renderSettings;
LayerAdjustment _layerAdjustment;
@@ -36,8 +36,6 @@ namespace openspace::documentation { struct Documentation; }
namespace openspace::globebrowsing {
namespace tileprovider { struct TileProvider; }
class LayerAdjustment : public properties::PropertyOwner {
public:
LayerAdjustment();
+1 -2
View File
@@ -33,8 +33,7 @@
namespace openspace::globebrowsing {
class Layer;
namespace tileprovider { struct TileProvider; }
struct TileProvider;
/**
* Convenience class for dealing with multiple <code>Layer</code>s.
+2 -2
View File
@@ -26,7 +26,7 @@
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
@@ -155,7 +155,7 @@ void LayerManager::reset(bool includeDisabled) {
for (std::unique_ptr<LayerGroup>& layerGroup : _layerGroups) {
for (Layer* layer : layerGroup->layers()) {
if ((layer->enabled() || includeDisabled) && layer->tileProvider()) {
tileprovider::reset(*layer->tileProvider());
layer->tileProvider()->reset();
}
}
}
+10 -11
View File
@@ -30,7 +30,7 @@
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
@@ -322,7 +322,7 @@ ChunkTileVector tilesAndSettingsUnsorted(const LayerGroup& layerGroup,
for (Layer* layer : layerGroup.activeLayers()) {
if (layer->tileProvider()) {
tilesAndSettings.emplace_back(
tileprovider::chunkTile(*layer->tileProvider(), tileIndex),
layer->tileProvider()->chunkTile(tileIndex),
&layer->renderSettings()
);
}
@@ -403,7 +403,7 @@ bool colorAvailableForChunk(const Chunk& chunk, const LayerManager& lm) {
for (Layer* lyr : colorLayers.activeLayers()) {
if (lyr->tileProvider()) {
ChunkTile t = tileprovider::chunkTile(*lyr->tileProvider(), chunk.tileIndex);
ChunkTile t = lyr->tileProvider()->chunkTile(chunk.tileIndex);
if (t.tile.status == Tile::Status::Unavailable) {
return false;
}
@@ -1886,16 +1886,15 @@ float RenderableGlobe::getHeight(const glm::dvec3& position) const {
_layerManager.layerGroup(layergroupid::GroupID::HeightLayers).activeLayers();
for (Layer* layer : heightMapLayers) {
tileprovider::TileProvider* tileProvider = layer->tileProvider();
TileProvider* tileProvider = layer->tileProvider();
if (!tileProvider) {
continue;
}
// Transform the uv coordinates to the current tile texture
const ChunkTile chunkTile = tileprovider::chunkTile(*tileProvider, tileIndex);
const ChunkTile chunkTile = tileProvider->chunkTile(tileIndex);
const Tile& tile = chunkTile.tile;
const TileUvTransform& uvTransform = chunkTile.uvTransform;
const TileDepthTransform& depthTransform =
tileprovider::depthTransform(*tileProvider);
const TileDepthTransform& depthTransform = tileProvider->depthTransform();
if (tile.status != Tile::Status::OK) {
return 0;
}
@@ -1953,10 +1952,10 @@ float RenderableGlobe::getHeight(const glm::dvec3& position) const {
std::isnan(sample11);
const bool anySampleIsNoData =
sample00 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample01 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample10 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample11 == tileprovider::noDataValueAsFloat(*tileProvider);
sample00 == tileProvider->noDataValueAsFloat() ||
sample01 == tileProvider->noDataValueAsFloat() ||
sample10 == tileProvider->noDataValueAsFloat() ||
sample11 == tileProvider->noDataValueAsFloat();
if (anySampleIsNaN || anySampleIsNoData) {
continue;
File diff suppressed because it is too large Load Diff
-292
View File
@@ -1,292 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILE_PROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_PROVIDER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/ellipsoid.h>
#include <modules/globebrowsing/src/layergroupid.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <modules/globebrowsing/src/timequantizer.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <unordered_map>
#include <ghoul/opengl/programobject.h>
struct CPLXMLNode;
namespace ghoul::fontrendering {
class Font;
class FontRenderer;
} // namespace ghoul::fontrendering
namespace openspace { class PixelBuffer; }
namespace openspace::globebrowsing {
class AsyncTileDataProvider;
struct RawTile;
struct TileIndex;
namespace cache { class MemoryAwareTileCache; }
} // namespace openspace::globebrowsing
namespace openspace::globebrowsing::tileprovider {
enum class Type {
DefaultTileProvider = 0,
SingleImageTileProvider,
ImageSequenceTileProvider,
SizeReferenceTileProvider,
TemporalTileProvider,
TileIndexTileProvider,
ByIndexTileProvider,
ByLevelTileProvider,
InterpolateTileProvider
};
struct TileProvider : public properties::PropertyOwner {
static unsigned int NumTileProviders;
Type type;
TileProvider();
virtual ~TileProvider() = default;
std::string name;
uint16_t uniqueIdentifier = 0;
bool isInitialized = false;
};
struct DefaultTileProvider : public TileProvider {
DefaultTileProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<AsyncTileDataProvider> asyncTextureDataProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
properties::StringProperty filePath;
properties::IntProperty tilePixelSize;
layergroupid::GroupID layerGroupID = layergroupid::GroupID::Unknown;
bool performPreProcessing = false;
bool padTiles = true;
};
struct SingleImageProvider : public TileProvider {
SingleImageProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<ghoul::opengl::Texture> tileTexture;
Tile tile;
properties::StringProperty filePath;
};
struct InterpolateTileProvider : public TileProvider {
InterpolateTileProvider(const ghoul::Dictionary&);
virtual ~InterpolateTileProvider();
Tile calculateTile(const TileIndex&);
TileProvider* before = nullptr;
TileProvider* t1 = nullptr;
TileProvider* t2 = nullptr;
TileProvider* future = nullptr;
float factor = 1.f;
GLuint vaoQuad = 0;
GLuint vboQuad = 0;
GLuint fbo = 0;
std::string colormap;
std::unique_ptr<ghoul::opengl::ProgramObject> shaderProgram;
std::unique_ptr<SingleImageProvider> singleImageProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
};
struct TextTileProvider : public TileProvider {
TextTileProvider(TileTextureInitData initData, size_t fontSize = 48);
const TileTextureInitData initData;
std::unique_ptr<ghoul::fontrendering::FontRenderer> fontRenderer;
std::shared_ptr<ghoul::fontrendering::Font> font;
size_t fontSize = 0;
std::string text;
glm::vec2 textPosition = glm::vec2(0.f);
glm::vec4 textColor = glm::vec4(0.f);
GLuint fbo = 0;
cache::MemoryAwareTileCache* tileCache;
};
struct SizeReferenceTileProvider : public TextTileProvider {
SizeReferenceTileProvider(const ghoul::Dictionary& dictionary);
Ellipsoid ellipsoid;
};
struct TileIndexTileProvider : public TextTileProvider {
TileIndexTileProvider(const ghoul::Dictionary& dictionary);
};
struct TileProviderByIndex : public TileProvider {
TileProviderByIndex(const ghoul::Dictionary& dictionary);
std::unordered_map<
TileIndex::TileHashKey, std::unique_ptr<TileProvider>
> tileProviderMap;
std::unique_ptr<TileProvider> defaultTileProvider;
};
struct TileProviderByLevel : public TileProvider {
TileProviderByLevel(const ghoul::Dictionary& dictionary);
std::vector<int> providerIndices;
std::vector<std::unique_ptr<TileProvider>> levelTileProviders;
};
struct ImageSequenceTileProvider : public TileProvider {
ImageSequenceTileProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<DefaultTileProvider> currentTileProvider = nullptr;
properties::IntProperty index;
properties::StringProperty currentImage;
properties::StringProperty folderPath;
ghoul::Dictionary initDict;
bool isImageDirty = true;
std::vector<std::filesystem::path> imagePaths;
};
/**
* Provide <code>Tile</code>s from web map services that have temporal resolution.
*
* TemporalTileProviders are instantiated using a ghoul::Dictionary,
* and must define a filepath to a Openspace Temporal dataset description file.
* This is an xml-file that defines the same meta data as the GDAL wms description
* (http://www.gdal.org/frmt_wms.html), but augmented with some
* extra tags describing the temporal properties of the dataset. See
* <code>TemporalTileProvider::TemporalXMLTags</code>
*
*/
struct TemporalTileProvider : public TileProvider {
enum class TimeFormatType {
YYYY_MM_DD = 0,
YYYYMMDD_hhmmss,
YYYYMMDD_hhmm,
YYYY_MM_DDThhColonmmColonssZ,
YYYY_MM_DDThh_mm_ssZ
};
using TimeKey = std::string;
TemporalTileProvider(const ghoul::Dictionary& dictionary);
ghoul::Dictionary initDict;
properties::StringProperty filePath;
properties::BoolProperty useFixedTime;
properties::StringProperty fixedTime;
std::string gdalXmlTemplate;
std::unordered_map<TimeKey, std::unique_ptr<TileProvider>> tileProviderMap;
bool interpolation = false;
TileProvider* currentTileProvider = nullptr;
double startTimeJ2000;
double endTimeJ2000;
TimeFormatType timeFormat;
TimeQuantizer timeQuantizer;
std::string colormap;
std::string myResolution;
std::unique_ptr<InterpolateTileProvider> interpolateTileProvider;
};
void initializeDefaultTile();
void deinitializeDefaultTile();
std::unique_ptr<TileProvider> createFromDictionary(layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary);
bool initialize(TileProvider& tp);
bool deinitialize(TileProvider& tp);
Tile tile(TileProvider& tp, const TileIndex& tileIndex);
ChunkTile chunkTile(TileProvider& tp, TileIndex tileIndex, int parents = 0,
int maxParents = 1337);
ChunkTilePile chunkTilePile(TileProvider& tp, TileIndex tileIndex, int pileSize);
/**
* Returns the status of a <code>Tile</code>. The <code>Tile::Status</code>
* corresponds the <code>Tile</code> that would be returned
* if the function <code>tile</code> would be invoked with the same
* <code>TileIndex</code> argument at this point in time.
*/
Tile::Status tileStatus(TileProvider& tp, const TileIndex& index);
/**
* Get the associated depth transform for this TileProvider.
* This is necessary for TileProviders serving height map
* data, in order to correcly map pixel values to meters.
*/
TileDepthTransform depthTransform(TileProvider& tp);
/**
* This method should be called once per frame. Here, TileProviders
* are given the opportunity to update their internal state.
*/
void update(TileProvider& tp);
/**
* Provides a uniform way of all TileProviders to reload or
* restore all of its internal state. This is mainly useful
* for debugging purposes.
*/
void reset(TileProvider& tp);
/**
* \returns The maximum level as defined by <code>TileIndex</code>
* that this TileProvider is able provide.
*/
int maxLevel(TileProvider& tp);
/**
* \returns the no data value for the dataset. Default is the minimum float avalue.
*/
float noDataValueAsFloat(TileProvider& tp);
} // namespace openspace::globebrowsing::tileprovider
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE_PROVIDER___H__
@@ -0,0 +1,221 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/asynctiledataprovider.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
namespace {
constexpr const char* KeyFilePath = "FilePath";
constexpr const char* KeyPerformPreProcessing = "PerformPreProcessing";
constexpr const char* KeyTilePixelSize = "TilePixelSize";
constexpr const char* KeyPadTiles = "PadTiles";
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"The path of the GDAL file or the image file that is to be used in this tile "
"provider."
};
constexpr openspace::properties::Property::PropertyInfo TilePixelSizeInfo = {
"TilePixelSize",
"Tile Pixel Size",
"This value is the preferred size (in pixels) for each tile. Choosing the right "
"value is a tradeoff between more efficiency (larger images) and better quality "
"(smaller images). The tile pixel size has to be smaller than the size of the "
"complete image if a single image is used."
};
} // namespace
namespace openspace::globebrowsing {
DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary)
: filePath(FilePathInfo, "")
, tilePixelSize(TilePixelSizeInfo, 32, 32, 2048)
{
ZoneScoped
tileCache = global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
name = "Name unspecified";
if (dictionary.hasValue<std::string>("Name")) {
name = dictionary.value<std::string>("Name");
}
std::string _loggerCat = "DefaultTileProvider (" + name + ")";
// 1. Get required Keys
filePath = dictionary.value<std::string>(KeyFilePath);
layerGroupID =
static_cast<layergroupid::GroupID>(dictionary.value<int>("LayerGroupID"));
// 2. Initialize default values for any optional Keys
// getValue does not work for integers
int pixelSize = 0;
if (dictionary.hasValue<double>(KeyTilePixelSize)) {
pixelSize = static_cast<int>(dictionary.value<double>(KeyTilePixelSize));
LDEBUG(fmt::format("Default pixel size overridden: {}", pixelSize));
}
if (dictionary.hasValue<bool>(KeyPadTiles)) {
padTiles = dictionary.value<bool>(KeyPadTiles);
}
TileTextureInitData initData(
tileTextureInitData(layerGroupID, padTiles, pixelSize)
);
tilePixelSize = initData.dimensions.x;
// Only preprocess height layers by default
switch (layerGroupID) {
case layergroupid::GroupID::HeightLayers: performPreProcessing = true; break;
default: performPreProcessing = false; break;
}
if (dictionary.hasValue<bool>(KeyPerformPreProcessing)) {
performPreProcessing = dictionary.value<bool>(KeyPerformPreProcessing);
LDEBUG(fmt::format(
"Default PerformPreProcessing overridden: {}", performPreProcessing
));
}
initAsyncTileDataReader(initData);
addProperty(filePath);
addProperty(tilePixelSize);
}
void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData) {
ZoneScoped
asyncTextureDataProvider = std::make_unique<AsyncTileDataProvider>(
name,
std::make_unique<RawTileDataReader>(
filePath,
initData,
RawTileDataReader::PerformPreprocessing(performPreProcessing)
)
);
}
Tile DefaultTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
if (asyncTextureDataProvider) {
if (tileIndex.level > maxLevel()) {
return Tile{ nullptr, std::nullopt, Tile::Status::OutOfRange };
}
const cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
Tile tile = tileCache->get(key);
if (!tile.texture) {
//TracyMessage("Enqueuing tile", 32);
asyncTextureDataProvider->enqueueTileIO(tileIndex);
}
return tile;
}
else {
return Tile{ nullptr, std::nullopt, Tile::Status::Unavailable };
}
}
Tile::Status DefaultTileProvider::tileStatus(const TileIndex& index) {
if (asyncTextureDataProvider) {
const RawTileDataReader& reader = asyncTextureDataProvider->rawTileDataReader();
if (index.level > reader.maxChunkLevel()) {
return Tile::Status::OutOfRange;
}
const cache::ProviderTileKey key = { index, uniqueIdentifier };
return tileCache->get(key).status;
}
else {
return Tile::Status::Unavailable;
}
}
TileDepthTransform DefaultTileProvider::depthTransform() {
if (asyncTextureDataProvider) {
return asyncTextureDataProvider->rawTileDataReader().depthTransform();
}
else {
return { 1.f, 0.f };
}
}
void DefaultTileProvider::update() {
if (!asyncTextureDataProvider) {
return;
}
asyncTextureDataProvider->update();
std::optional<RawTile> tile = asyncTextureDataProvider->popFinishedRawTile();
if (tile) {
const cache::ProviderTileKey key = { tile->tileIndex, uniqueIdentifier };
ghoul_assert(!tileCache->exist(key), "Tile must not be existing in cache");
tileCache->createTileAndPut(key, std::move(*tile));
}
if (asyncTextureDataProvider->shouldBeDeleted()) {
asyncTextureDataProvider = nullptr;
initAsyncTileDataReader(
tileTextureInitData(layerGroupID, padTiles, tilePixelSize)
);
}
}
void DefaultTileProvider::reset() {
tileCache->clear();
if (asyncTextureDataProvider) {
asyncTextureDataProvider->prepareToBeDeleted();
}
else {
initAsyncTileDataReader(
tileTextureInitData(layerGroupID, padTiles, tilePixelSize)
);
}
}
int DefaultTileProvider::maxLevel() {
// 22 is the current theoretical maximum based on the number of hashes that are
// possible to uniquely identify a tile. See ProviderTileHasher in
// memoryawaretilecache.h
return asyncTextureDataProvider ?
asyncTextureDataProvider->rawTileDataReader().maxChunkLevel() :
22;
}
float DefaultTileProvider::noDataValueAsFloat() {
return asyncTextureDataProvider ?
asyncTextureDataProvider->noDataValueAsFloat() :
std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,59 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
struct DefaultTileProvider : public TileProvider {
DefaultTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
std::unique_ptr<AsyncTileDataProvider> asyncTextureDataProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
properties::StringProperty filePath;
properties::IntProperty tilePixelSize;
layergroupid::GroupID layerGroupID = layergroupid::GroupID::Unknown;
bool performPreProcessing = false;
bool padTiles = true;
private:
void initAsyncTileDataReader(TileTextureInitData initData);
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
@@ -0,0 +1,159 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
namespace {
constexpr const char* KeyFilePath = "FilePath";
constexpr openspace::properties::Property::PropertyInfo IndexInfo = {
"Index",
"Index",
"The index into the list of images that is used to pick the currently displayed "
"image"
};
constexpr openspace::properties::Property::PropertyInfo CurrentImageInfo = {
"CurrentImage",
"Current Image",
"The read-only value of the currently selected image"
};
constexpr openspace::properties::Property::PropertyInfo FolderPathInfo = {
"FolderPath",
"Folder Path",
"The path that is used to look for images for this image provider. The path must "
"point to an existing folder that contains images"
};
} // namespace
namespace openspace::globebrowsing {
ImageSequenceTileProvider::ImageSequenceTileProvider(const ghoul::Dictionary& dictionary)
: index(IndexInfo, 0)
, currentImage(CurrentImageInfo)
, folderPath(FolderPathInfo)
, initDict(dictionary)
{
ZoneScoped
if (dictionary.hasValue<int>(IndexInfo.identifier)) {
index = dictionary.value<int>(IndexInfo.identifier);
}
index.setMinValue(0);
index.onChange([this]() { isImageDirty = true; });
addProperty(index);
folderPath.setReadOnly(true);
addProperty(folderPath);
folderPath = dictionary.value<std::string>(FolderPathInfo.identifier);
addProperty(folderPath);
reset();
}
Tile ImageSequenceTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
if (currentTileProvider) {
return currentTileProvider->tile(tileIndex);
}
else {
return Tile();
}
}
Tile::Status ImageSequenceTileProvider::tileStatus(const TileIndex& index) {
if (currentTileProvider) {
return currentTileProvider->tileStatus(index);
}
else {
return Tile::Status::Unavailable;
}
}
TileDepthTransform ImageSequenceTileProvider::depthTransform() {
if (currentTileProvider) {
return currentTileProvider->depthTransform();
}
else {
return { 1.f, 0.f };
}
}
void ImageSequenceTileProvider::update() {
if (isImageDirty && !imagePaths.empty() &&
index >= 0 && index < imagePaths.size())
{
if (currentTileProvider) {
currentTileProvider->deinitialize();
}
std::string p = imagePaths[index].string();
currentImage = p;
initDict.setValue(KeyFilePath, p);
currentTileProvider = std::make_unique<DefaultTileProvider>(initDict);
currentTileProvider->initialize();
isImageDirty = false;
}
if (currentTileProvider) {
currentTileProvider->update();
}
}
void ImageSequenceTileProvider::reset() {
namespace fs = std::filesystem;
std::string path = folderPath;
imagePaths.clear();
for (const fs::directory_entry& p : fs::directory_iterator(path)) {
if (p.is_regular_file()) {
imagePaths.push_back(p.path());
}
}
index = 0;
index.setMaxValue(static_cast<int>(imagePaths.size() - 1));
if (currentTileProvider) {
currentTileProvider->reset();
}
}
int ImageSequenceTileProvider::maxLevel() {
return currentTileProvider ? currentTileProvider->maxLevel() : 0;
}
float ImageSequenceTileProvider::noDataValueAsFloat() {
if (currentTileProvider) {
return currentTileProvider->noDataValueAsFloat();
}
else {
return std::numeric_limits<float>::min();
}
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,58 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
namespace openspace::globebrowsing {
struct ImageSequenceTileProvider : public TileProvider {
ImageSequenceTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
std::unique_ptr<DefaultTileProvider> currentTileProvider = nullptr;
properties::IntProperty index;
properties::StringProperty currentImage;
properties::StringProperty folderPath;
ghoul::Dictionary initDict;
bool isImageDirty = true;
std::vector<std::filesystem::path> imagePaths;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__
@@ -0,0 +1,241 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/interpolatetileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/textureunit.h>
namespace openspace::globebrowsing {
InterpolateTileProvider::InterpolateTileProvider(const ghoul::Dictionary&) {
ZoneScoped
glGenFramebuffers(1, &fbo);
glGenVertexArrays(1, &vaoQuad);
glGenBuffers(1, &vboQuad);
glBindVertexArray(vaoQuad);
glBindBuffer(GL_ARRAY_BUFFER, vboQuad);
tileCache = global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
// Quad for fullscreen with vertex (xy) and texture coordinates (uv)
const GLfloat vertexData[] = {
// x y u v
-1.f, -1.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f,
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// vertex coordinates at location 0
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(0);
// texture coords at location 1
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
4 * sizeof(GLfloat),
reinterpret_cast<void*>(sizeof(GLfloat) * 2)
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
shaderProgram = global::renderEngine->buildRenderProgram(
"InterpolatingProgram",
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_fs.glsl")
);
}
InterpolateTileProvider::~InterpolateTileProvider() {
glDeleteFramebuffers(1, &fbo);
glDeleteBuffers(1, &vboQuad);
glDeleteVertexArrays(1, &vaoQuad);
}
Tile InterpolateTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
TracyGpuZone("tile");
// prev and next are the two tiles to interpolate between
Tile prev = t1->tile(tileIndex);
Tile next = t2->tile(tileIndex);
// the tile before and the tile after the interpolation interval are loaded so the
// interpolation goes smoother
Tile prevprev = before->tile(tileIndex);
Tile nextnext = future->tile(tileIndex);
cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
if (!prev.texture || !next.texture) {
return Tile{ nullptr, std::nullopt, Tile::Status::Unavailable };
}
// There is a previous and next texture to interpolate between so do the interpolation
// The texture that will give the color for the interpolated texture
ghoul::opengl::Texture* colormapTexture = singleImageProvider->ttile.texture;
long long hkey = cache::ProviderTileHasher()(key);
// The data for initializing the texture
TileTextureInitData initData(
prev.texture->dimensions().x,
prev.texture->dimensions().y,
prev.texture->dataType(),
prev.texture->format(),
TileTextureInitData::PadTiles::No,
TileTextureInitData::ShouldAllocateDataOnCPU::No
);
// Check if a tile exists for the given key in the tileCache
// Initializing the tile that will contian the interpolated texture
Tile ourTile;
// The texture that will contain the interpolated image
ghoul::opengl::Texture* writeTexture;
if (tileCache->exist(key)) {
// Get the tile from the tilecache
ourTile = tileCache->get(key);
// Use the texture from the tileCache
writeTexture = ourTile.texture;
}
else {
// Create a texture with the initialization data
writeTexture = tileCache->texture(initData);
// Create a tile with the texture
ourTile = Tile{ writeTexture, std::nullopt, Tile::Status::OK };
// Add it to the tilecache
tileCache->put(key, initData.hashKey, ourTile);
}
// Saves current state
GLint currentFBO;
GLint viewport[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFBO);
global::renderEngine->openglStateCache().viewport(viewport);
// Bind render texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
*writeTexture,
0
);
glDisable(GL_BLEND);
GLenum textureBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, textureBuffers);
// Check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LERRORC("TileProvider", "Incomplete framebuffer");
}
// Setup our own viewport settings
GLsizei w = static_cast<GLsizei>(writeTexture->width());
GLsizei h = static_cast<GLsizei>(writeTexture->height());
glViewport(0, 0, w, h);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
GLint id;
glGetIntegerv(GL_CURRENT_PROGRAM, &id);
// Activate shader and bind uniforms
shaderProgram->activate();
shaderProgram->setUniform("blendFactor", factor);
ghoul::opengl::TextureUnit colormapUnit;
colormapUnit.activate();
colormapTexture->bind();
shaderProgram->setUniform("colormapTexture", colormapUnit);
ghoul::opengl::TextureUnit prevUnit;
prevUnit.activate();
prev.texture->bind();
shaderProgram->setUniform("prevTexture", prevUnit);
ghoul::opengl::TextureUnit nextUnit;
nextUnit.activate();
next.texture->bind();
shaderProgram->setUniform("nextTexture", nextUnit);
// Render to the texture
glBindVertexArray(vaoQuad);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2 triangles
// Deactivate shader program (when rendering is completed)
shaderProgram->deactivate();
glUseProgram(id);
// Restores system state
glBindFramebuffer(GL_FRAMEBUFFER, currentFBO);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Restores OpenGL Rendering State
global::renderEngine->openglStateCache().resetColorState();
global::renderEngine->openglStateCache().resetBlendState();
global::renderEngine->openglStateCache().resetDepthState();
global::renderEngine->openglStateCache().resetPolygonAndClippingState();
global::renderEngine->openglStateCache().resetViewportState();
return ourTile;
}
Tile::Status InterpolateTileProvider::tileStatus(const TileIndex& index) {
Tile::Status t1Stat = t1->tileStatus(index);
Tile::Status t2Stat = t2->tileStatus(index);
if (t1Stat <= t2Stat) {
return t1Stat;
}
else {
return t2Stat;
}
}
TileDepthTransform InterpolateTileProvider::depthTransform() {
return t1->depthTransform();
}
void InterpolateTileProvider::update() {
t1->update();
t2->update();
before->update();
future->update();
}
void InterpolateTileProvider::reset() {
t1->reset();
t2->reset();
before->reset();
future->reset();
}
int InterpolateTileProvider::maxLevel() {
return glm::min(t1->maxLevel(), t2->maxLevel());
}
float InterpolateTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,62 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__INTERPOLATEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__INTERPOLATEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
namespace openspace::globebrowsing {
struct InterpolateTileProvider : public TileProvider {
InterpolateTileProvider(const ghoul::Dictionary&);
virtual ~InterpolateTileProvider();
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
TileProvider* before = nullptr;
TileProvider* t1 = nullptr;
TileProvider* t2 = nullptr;
TileProvider* future = nullptr;
float factor = 1.f;
GLuint vaoQuad = 0;
GLuint vboQuad = 0;
GLuint fbo = 0;
std::string colormap;
std::unique_ptr<ghoul::opengl::ProgramObject> shaderProgram;
std::unique_ptr<SingleImageProvider> singleImageProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__INTERPOLATEPROVIDER___H__
@@ -0,0 +1,93 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
#include <ghoul/io/texture/texturereader.h>
namespace {
constexpr const char* KeyFilePath = "FilePath";
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"The file path that is used for this image provider. The file must point to an "
"image that is then loaded and used for all tiles."
};
} // namespace
namespace openspace::globebrowsing {
SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary)
: filePath(FilePathInfo)
{
ZoneScoped
filePath = dictionary.value<std::string>(KeyFilePath);
addProperty(filePath);
reset();
}
Tile SingleImageProvider::tile(const TileIndex&) {
ZoneScoped
return ttile;
}
Tile::Status SingleImageProvider::tileStatus(const TileIndex&) {
return ttile.status;
}
TileDepthTransform SingleImageProvider::depthTransform() {
return { 0.f, 1.f };
}
void SingleImageProvider::update() {}
void SingleImageProvider::reset() {
if (filePath.value().empty()) {
return;
}
tileTexture = ghoul::io::TextureReader::ref().loadTexture(filePath, 2);
if (!tileTexture) {
throw ghoul::RuntimeError(
fmt::format("Unable to load texture '{}'", filePath.value())
);
}
Tile::Status tileStatus = Tile::Status::OK;
tileTexture->uploadTexture();
tileTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
ttile = Tile{ tileTexture.get(), std::nullopt, tileStatus };
}
int SingleImageProvider::maxLevel() {
return 1337; // unlimited
}
float SingleImageProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,52 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
struct SingleImageProvider : public TileProvider {
SingleImageProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
std::unique_ptr<ghoul::opengl::Texture> tileTexture;
Tile ttile;
properties::StringProperty filePath;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__
@@ -0,0 +1,112 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <openspace/engine/globals.h>
#include <ghoul/font/fontmanager.h>
namespace {
constexpr const char* KeyRadii = "Radii";
} // namespace
namespace openspace::globebrowsing {
SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary)
: TextTileProvider(tileTextureInitData(layergroupid::GroupID::ColorLayers, false))
{
ZoneScoped
font = global::fontManager->font("Mono", static_cast<float>(fontSize));
if (dictionary.hasValue<glm::dvec3>(KeyRadii)) {
ellipsoid = dictionary.value<glm::dvec3>(KeyRadii);
}
else if (dictionary.hasValue<double>(KeyRadii)) {
const double r = dictionary.value<double>(KeyRadii);
ellipsoid = glm::dvec3(r, r, r);
}
}
Tile SizeReferenceTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
const GeodeticPatch patch(tileIndex);
const bool aboveEquator = patch.isNorthern();
const double lat = aboveEquator ? patch.minLat() : patch.maxLat();
const double lon1 = patch.minLon();
const double lon2 = patch.maxLon();
int l = static_cast<int>(ellipsoid.longitudalDistance(lat, lon1, lon2));
const bool useKm = l > 9999;
if (useKm) {
l /= 1000;
}
l = static_cast<int>(std::round(l));
if (useKm) {
l *= 1000;
}
double tileLongitudalLength = l;
const char* unit;
if (tileLongitudalLength > 9999) {
tileLongitudalLength *= 0.001;
unit = "km";
}
else {
unit = "m";
}
text = fmt::format(" {:.0f} {:s}", tileLongitudalLength, unit);
textPosition = {
0.f,
aboveEquator ?
fontSize / 2.f :
initData.dimensions.y - 3.f * fontSize / 2.f
};
textColor = glm::vec4(1.f);
return TextTileProvider::tile(tileIndex);
}
Tile::Status SizeReferenceTileProvider::tileStatus(const TileIndex& index) {
return Tile::Status::OK;
}
TileDepthTransform SizeReferenceTileProvider::depthTransform() {
return { 0.f, 1.f };
}
void SizeReferenceTileProvider::update() {}
int SizeReferenceTileProvider::maxLevel() {
return 1337; // unlimited
}
float SizeReferenceTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,47 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/texttileprovider.h>
namespace openspace::globebrowsing {
struct SizeReferenceTileProvider : public TextTileProvider {
SizeReferenceTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
Ellipsoid ellipsoid;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__
@@ -0,0 +1,527 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <openspace/util/memorymanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include "cpl_minixml.h"
#include <fstream>
namespace {
constexpr const char* KeyBasePath = "BasePath";
constexpr const char* KeyFilePath = "FilePath";
constexpr const char* UrlTimePlaceholder = "${OpenSpaceTimeId}";
constexpr const char* TimeStart = "OpenSpaceTimeStart";
constexpr const char* TimeEnd = "OpenSpaceTimeEnd";
constexpr const char* TimeResolution = "OpenSpaceTimeResolution";
constexpr const char* TimeFormat = "OpenSpaceTimeIdFormat";
constexpr const char* TimeInterpolation = "OpenSpaceTimeInterpolation";
constexpr const char* TransferFunction = "OpenSpaceTransferFunction";
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"This is the path to the XML configuration file that describes the temporal tile "
"information."
};
constexpr openspace::properties::Property::PropertyInfo UseFixedTimeInfo = {
"UseFixedTime",
"Use Fixed Time",
"If this value is enabled, the time-varying timevarying dataset will always use "
"the time that is specified in the 'FixedTime' property, rather than using the "
"actual time from OpenSpace"
};
constexpr openspace::properties::Property::PropertyInfo FixedTimeInfo = {
"FixedTime",
"Fixed Time",
"If the 'UseFixedTime' is enabled, this time will be used instead of the actual "
"time taken from OpenSpace for the displayed tiles."
};
std::string xmlValue(openspace::globebrowsing::TemporalTileProvider& t,
CPLXMLNode* node, const std::string& key,
const std::string& defaultVal, bool isOptional = false)
{
CPLXMLNode* n = CPLSearchXMLNode(node, key.c_str());
if (!n && !isOptional) {
throw ghoul::RuntimeError(
fmt::format("Unable to parse file {}. {} missing", t.filePath.value(), key)
);
}
const bool hasValue = n && n->psChild && n->psChild->pszValue;
return hasValue ? n->psChild->pszValue : defaultVal;
}
} // namespace
namespace ghoul {
template <>
constexpr openspace::globebrowsing::TemporalTileProvider::TimeFormatType
from_string(std::string_view string)
{
using namespace openspace::globebrowsing;
if (string == "YYYY-MM-DD") {
return TemporalTileProvider::TimeFormatType::YYYY_MM_DD;
}
else if (string == "YYYY-MM-DDThh:mm:ssZ") {
return TemporalTileProvider::TimeFormatType::YYYY_MM_DDThhColonmmColonssZ;
}
else if (string == "YYYY-MM-DDThh_mm_ssZ") {
return TemporalTileProvider::TimeFormatType::YYYY_MM_DDThh_mm_ssZ;
}
else if (string == "YYYYMMDD_hhmmss") {
return TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmmss;
}
else if (string == "YYYYMMDD_hhmm") {
return TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmm;
}
else {
throw ghoul::RuntimeError("Unknown timeformat '" + std::string(string) + "'");
}
}
} // namespace ghoul
namespace openspace::globebrowsing {
TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
: initDict(dictionary)
, filePath(FilePathInfo)
, useFixedTime(UseFixedTimeInfo, false)
, fixedTime(FixedTimeInfo)
{
ZoneScoped
filePath = dictionary.value<std::string>(KeyFilePath);
addProperty(filePath);
if (dictionary.hasValue<bool>(UseFixedTimeInfo.identifier)) {
useFixedTime = dictionary.value<bool>(UseFixedTimeInfo.identifier);
}
addProperty(useFixedTime);
if (dictionary.hasValue<std::string>(FixedTimeInfo.identifier)) {
fixedTime = dictionary.value<std::string>(FixedTimeInfo.identifier);
}
addProperty(fixedTime);
readFilePath();
if (interpolation) {
interpolateTileProvider = std::make_unique<InterpolateTileProvider>(dictionary);
interpolateTileProvider->colormap = colormap;
interpolateTileProvider->initialize();
ghoul::Dictionary dict;
dict.setValue("FilePath", colormap);
interpolateTileProvider->singleImageProvider =
std::make_unique<SingleImageProvider>(dict);
}
}
void TemporalTileProvider::readFilePath() {
ZoneScoped
std::ifstream in(filePath.value());
std::string xml;
if (in.is_open()) {
// read file
xml = std::string(
std::istreambuf_iterator<char>(in),
(std::istreambuf_iterator<char>())
);
}
else {
// Assume that it is already an xml
xml = filePath;
}
// File path was not a path to a file but a GDAL config or empty
std::filesystem::path f(filePath.value());
if (std::filesystem::is_regular_file(f)) {
initDict.setValue(KeyBasePath, f.parent_path().string());
}
gdalXmlTemplate = consumeTemporalMetaData(xml);
}
std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml) {
ZoneScoped
CPLXMLNode* node = CPLParseXMLString(xml.c_str());
std::string timeStart = xmlValue(*this, node, TimeStart, "2000 Jan 1");
std::string timeResolution = xmlValue(*this, node, TimeResolution, "2d");
std::string timeEnd = xmlValue(*this, node, TimeEnd, "Today");
std::string timeIdFormat = xmlValue(
*this,
node,
TimeFormat,
"YYYY-MM-DDThh:mm:ssZ"
);
std::string timeInterpolation = xmlValue(
*this,
node,
TimeInterpolation,
"none",
true
);
colormap = xmlValue(*this, node, TransferFunction, "none", true);
Time start = Time(timeStart);
Time end = Time::now();
Time endOfInterval = Time(timeEnd);
startTimeJ2000 = start.j2000Seconds();
endTimeJ2000 = endOfInterval.j2000Seconds();
if (timeEnd == "Yesterday") {
end.advanceTime(-60.0 * 60.0 * 24.0); // Go back one day
}
else if (timeEnd != "Today") {
end.setTime(std::move(timeEnd));
}
try {
timeQuantizer.setStartEndRange(
std::string(start.ISO8601()),
std::string(end.ISO8601())
);
timeQuantizer.setResolution(timeResolution);
myResolution = timeResolution;
}
catch (const ghoul::RuntimeError& e) {
throw ghoul::RuntimeError(fmt::format(
"Could not create time quantizer for Temporal GDAL dataset '{}'. {}",
filePath.value(), e.message
));
}
timeFormat = ghoul::from_string<TemporalTileProvider::TimeFormatType>(timeIdFormat);
interpolation = (timeInterpolation == "linear");
CPLXMLNode* gdalNode = CPLSearchXMLNode(node, "GDAL_WMS");
if (gdalNode) {
std::string gdalDescription = CPLSerializeXMLTree(gdalNode);
return gdalDescription;
}
else {
gdalNode = CPLSearchXMLNode(node, "FilePath");
if (gdalNode) {
std::string gdalDescription = std::string(gdalNode->psChild->pszValue);
return gdalDescription;
}
else {
return "";
}
}
}
void TemporalTileProvider::ensureUpdated() {
ZoneScoped
if (!currentTileProvider) {
update();
}
}
Tile TemporalTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
ensureUpdated();
return currentTileProvider->tile(tileIndex);
}
Tile::Status TemporalTileProvider::tileStatus(const TileIndex& index) {
ensureUpdated();
return currentTileProvider->tileStatus(index);
}
TileDepthTransform TemporalTileProvider::depthTransform() {
ensureUpdated();
return currentTileProvider->depthTransform();
}
void TemporalTileProvider::update() {
TileProvider* newCurr = getTileProvider(global::timeManager->time());
if (newCurr) {
currentTileProvider = newCurr;
}
if (currentTileProvider) {
currentTileProvider->update();
}
}
void TemporalTileProvider::reset() {
using K = TemporalTileProvider::TimeKey;
using V = std::unique_ptr<TileProvider>;
for (std::pair<const K, V>& it : tileProviderMap) {
it.second->reset();
}
}
int TemporalTileProvider::maxLevel() {
ensureUpdated();
return currentTileProvider->maxLevel();
}
float TemporalTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
// Buffer needs at least 22 characters space
std::string_view TemporalTileProvider::timeStringify(TemporalTileProvider::TimeFormatType type, const Time& t) {
ZoneScoped
char* buffer = reinterpret_cast<char*>(
global::memoryManager->TemporaryMemory.allocate(22)
);
std::memset(buffer, 0, 22);
const double time = t.j2000Seconds();
switch (type) {
case TemporalTileProvider::TimeFormatType::YYYY_MM_DD:
{
constexpr const char Format[] = "YYYY-MM-DD";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmmss: {
constexpr const char Format[] = "YYYYMMDD_HRMNSC";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmm: {
constexpr const char Format[] = "YYYYMMDD_HRMN";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThhColonmmColonssZ:
{
constexpr const char Format[] = "YYYY-MM-DDTHR:MN:SCZ";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return std::string_view(buffer, Size - 1);
}
case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThh_mm_ssZ: {
constexpr const char Format[] = "YYYY-MM-DDTHR_MN_SCZ";
constexpr const int Size = sizeof(Format);
SpiceManager::ref().dateFromEphemerisTime(time, buffer, Size, Format);
return std::string_view(buffer, Size - 1);
}
default:
throw ghoul::MissingCaseException();
}
}
std::unique_ptr<TileProvider> TemporalTileProvider::initTileProvider(
std::string_view timekey)
{
ZoneScoped
static const std::vector<std::string> IgnoredTokens = {
// From: http://www.gdal.org/frmt_wms.html
"${x}",
"${y}",
"${z}",
"${version}",
"${format}",
"${layer}"
};
std::string xmlTemplate(gdalXmlTemplate);
const size_t pos = xmlTemplate.find(UrlTimePlaceholder);
const size_t numChars = strlen(UrlTimePlaceholder);
// @FRAGILE: This will only find the first instance. Dangerous if that instance is
// commented out ---abock
std::string xml = xmlTemplate.replace(pos, numChars, timekey);
xml = FileSys.expandPathTokens(std::move(xml), IgnoredTokens).string();
initDict.setValue(KeyFilePath, xml);
return std::make_unique<DefaultTileProvider>(initDict);
}
TileProvider* TemporalTileProvider::getTileProvider(std::string_view timekey) {
ZoneScoped
// @TODO (abock, 2020-08-20) This std::string creation can be removed once we switch
// to C++20 thanks to P0919R2
const auto it = tileProviderMap.find(std::string(timekey));
if (it != tileProviderMap.end()) {
return it->second.get();
}
else {
std::unique_ptr<TileProvider> tileProvider = initTileProvider(timekey);
tileProvider->initialize();
TileProvider* res = tileProvider.get();
tileProviderMap[std::string(timekey)] = std::move(tileProvider);
return res;
}
}
TileProvider* TemporalTileProvider::getTileProvider(const Time& time) {
ZoneScoped
if (!interpolation) {
if (useFixedTime && !fixedTime.value().empty()) {
try {
return getTileProvider(fixedTime.value());
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
else {
Time tCopy(time);
if (timeQuantizer.quantize(tCopy, true)) {
std::string_view timeStr = timeStringify(timeFormat, tCopy);
try {
return getTileProvider(timeStr);
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
}
}
Time tCopy(time);
if (!timeQuantizer.quantize(tCopy, true)) {
return nullptr;
}
Time simulationTime(time);
Time nextTile;
Time nextNextTile;
Time prevTile;
Time secondToLast;
Time secondToFirst;
std::string_view tCopyStr = timeStringify(timeFormat, tCopy);
try {
interpolateTileProvider->t1 = getTileProvider(tCopyStr);
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
// if the images are for each hour
if (myResolution == "1h") {
// the second tile to interpolate between
nextTile.setTime(tCopy.j2000Seconds() + 60 * 60);
// the tile after the second tile
nextNextTile.setTime(tCopy.j2000Seconds() + 120 * 60);
// the tile before the first tile
prevTile.setTime(tCopy.j2000Seconds() - 60 * 60 + 1);
// to make sure that an image outside the dataset is not searched for both ends of
// the dataset are calculated
secondToLast.setTime(endTimeJ2000 - 60 * 60);
secondToFirst.setTime(startTimeJ2000 + 60 * 60);
}
// if the images are for each month
if (myResolution == "1M") {
// the second tile to interpolate between
nextTile.setTime(tCopy.j2000Seconds() + 32 * 60 * 60 * 24);
// the tile after the second tile
nextNextTile.setTime(tCopy.j2000Seconds() + 64 * 60 * 60 * 24);
// the tile before the first tile
prevTile.setTime(tCopy.j2000Seconds() - 2 * 60 * 60 * 24);
// to make sure that an image outside the dataset is not searched for both ends of
// the dataset are calculated
secondToLast.setTime(endTimeJ2000 - 2 * 60 * 60 * 24);
secondToFirst.setTime(startTimeJ2000 + 32 * 60 * 60 * 24);
// since months vary in length the time strings are set to the first of each month
auto setToFirstOfMonth = [](Time& time) {
std::string timeString = std::string(time.ISO8601());
timeString[8] = '0';
timeString[9] = '1';
time.setTime(timeString);
};
setToFirstOfMonth(nextTile);
setToFirstOfMonth(nextNextTile);
setToFirstOfMonth(prevTile);
setToFirstOfMonth(secondToLast);
setToFirstOfMonth(secondToFirst);
}
std::string_view nextTileStr = timeStringify(timeFormat, nextTile);
std::string_view nextNextTileStr = timeStringify(timeFormat, nextNextTile);
std::string_view prevTileStr = timeStringify(timeFormat, prevTile);
try {
// the necessary tile providers are loaded if they exist within the
// dataset's timespan
if (secondToLast.j2000Seconds() > simulationTime.j2000Seconds() &&
secondToFirst.j2000Seconds() < simulationTime.j2000Seconds())
{
interpolateTileProvider->t2 = getTileProvider(nextTileStr);
interpolateTileProvider->future = getTileProvider(nextNextTileStr);
interpolateTileProvider->before = getTileProvider(prevTileStr);
}
else if (secondToLast.j2000Seconds() < simulationTime.j2000Seconds() &&
endTimeJ2000 > simulationTime.j2000Seconds())
{
interpolateTileProvider->t2 = getTileProvider(nextTileStr);
interpolateTileProvider->future = getTileProvider(tCopyStr);
interpolateTileProvider->before = getTileProvider(prevTileStr);
}
else if (secondToFirst.j2000Seconds() > simulationTime.j2000Seconds() &&
startTimeJ2000 < simulationTime.j2000Seconds())
{
interpolateTileProvider->t2 = getTileProvider(nextTileStr);
interpolateTileProvider->future = getTileProvider(nextNextTileStr);
interpolateTileProvider->before = getTileProvider(tCopyStr);
}
else {
interpolateTileProvider->t2 = getTileProvider(tCopyStr);
interpolateTileProvider->future = getTileProvider(tCopyStr);
interpolateTileProvider->before = getTileProvider(tCopyStr);
}
interpolateTileProvider->factor =
(simulationTime.j2000Seconds() - tCopy.j2000Seconds()) /
(nextTile.j2000Seconds() - tCopy.j2000Seconds());
if (interpolateTileProvider->factor > 1) {
interpolateTileProvider->factor = 1;
}
return interpolateTileProvider.get();
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
return nullptr;
}
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,99 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEMPORALTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEMPORALTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/interpolatetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
namespace openspace::globebrowsing {
/**
* Provide <code>Tile</code>s from web map services that have temporal resolution.
*
* TemporalTileProviders are instantiated using a ghoul::Dictionary, and must define a
* filepath to a Openspace Temporal dataset description file. This is an xml-file that
* defines the same meta data as the GDAL wms description
* (http://www.gdal.org/frmt_wms.html), but augmented with some extra tags describing the
* temporal properties of the dataset. See
* <code>TemporalTileProvider::TemporalXMLTags</code>
*/
struct TemporalTileProvider : public TileProvider {
enum class TimeFormatType {
YYYY_MM_DD = 0,
YYYYMMDD_hhmmss,
YYYYMMDD_hhmm,
YYYY_MM_DDThhColonmmColonssZ,
YYYY_MM_DDThh_mm_ssZ
};
using TimeKey = std::string;
TemporalTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
ghoul::Dictionary initDict;
properties::StringProperty filePath;
properties::BoolProperty useFixedTime;
properties::StringProperty fixedTime;
std::string gdalXmlTemplate;
std::unordered_map<TimeKey, std::unique_ptr<TileProvider>> tileProviderMap;
bool interpolation = false;
TileProvider* currentTileProvider = nullptr;
double startTimeJ2000;
double endTimeJ2000;
TimeFormatType timeFormat;
TimeQuantizer timeQuantizer;
std::string colormap;
std::string myResolution;
std::unique_ptr<InterpolateTileProvider> interpolateTileProvider;
private:
void readFilePath();
std::string consumeTemporalMetaData(const std::string& xml);
void ensureUpdated();
std::string_view timeStringify(TimeFormatType type, const Time& t);
std::unique_ptr<TileProvider> initTileProvider(std::string_view timekey);
TileProvider* getTileProvider(std::string_view timekey);
TileProvider* getTileProvider(const Time& time);
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEMPORALTILEPROVIDER___H__
@@ -0,0 +1,108 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/texttileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/opengl/openglstatecache.h>
namespace openspace::globebrowsing {
TextTileProvider::TextTileProvider(TileTextureInitData initData_, size_t fontSize_)
: initData(std::move(initData_))
, fontSize(fontSize_)
{
ZoneScoped
tileCache = global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
}
TextTileProvider::~TextTileProvider() {}
void TextTileProvider::internalInitialize() {
ZoneScoped
font = global::fontManager->font("Mono", static_cast<float>(fontSize));
fontRenderer = ghoul::fontrendering::FontRenderer::createDefault();
fontRenderer->setFramebufferSize(glm::vec2(initData.dimensions));
glGenFramebuffers(1, &fbo);
}
void TextTileProvider::internalDeinitialize() {
glDeleteFramebuffers(1, &fbo);
}
Tile TextTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
TracyGpuZone("tile")
cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
Tile tile = tileCache->get(key);
if (!tile.texture) {
ghoul::opengl::Texture* texture = tileCache->texture(initData);
// Keep track of defaultFBO and viewport to be able to reset state when done
GLint defaultFBO;
defaultFBO = global::renderEngine->openglStateCache().defaultFramebuffer();
// Render to texture
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
*texture,
0
);
GLsizei w = static_cast<GLsizei>(texture->width());
GLsizei h = static_cast<GLsizei>(texture->height());
glViewport(0, 0, w, h);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
fontRenderer->render(*font, textPosition, text, textColor);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
global::renderEngine->openglStateCache().resetViewportState();
tile = Tile{ texture, std::nullopt, Tile::Status::OK };
tileCache->put(key, initData.hashKey, tile);
}
return tile;
}
void TextTileProvider::reset() {
ZoneScoped
tileCache->clear();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,61 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEXTTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEXTTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
struct TextTileProvider : public TileProvider {
TextTileProvider(TileTextureInitData initData, size_t fontSize = 48);
virtual ~TextTileProvider();
Tile tile(const TileIndex& tileIndex) override;
void reset() override;
const TileTextureInitData initData;
std::unique_ptr<ghoul::fontrendering::FontRenderer> fontRenderer;
std::shared_ptr<ghoul::fontrendering::Font> font;
size_t fontSize = 0;
std::string text;
glm::vec2 textPosition = glm::vec2(0.f);
glm::vec4 textColor = glm::vec4(0.f);
GLuint fbo = 0;
cache::MemoryAwareTileCache* tileCache;
private:
void internalInitialize() override final;
void internalDeinitialize() override final;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEXTTILEPROVIDER___H__
@@ -0,0 +1,66 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
namespace openspace::globebrowsing {
TileIndexTileProvider::TileIndexTileProvider(const ghoul::Dictionary&)
: TextTileProvider(tileTextureInitData(layergroupid::GroupID::ColorLayers, false))
{}
Tile TileIndexTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
text = fmt::format(
"level: {}\nx: {}\ny: {}", tileIndex.level, tileIndex.x, tileIndex.y
);
textPosition = glm::vec2(
initData.dimensions.x / 4 -
(initData.dimensions.x / 32) * log10(1 << tileIndex.level),
initData.dimensions.y / 2 + fontSize
);
textColor = glm::vec4(1.f);
return TextTileProvider::tile(tileIndex);
}
Tile::Status TileIndexTileProvider::tileStatus(const TileIndex&) {
return Tile::Status::OK;
}
TileDepthTransform TileIndexTileProvider::depthTransform() {
return { 0.f, 1.f };
}
void TileIndexTileProvider::update() {}
int TileIndexTileProvider::maxLevel() {
return 1337; // unlimited
}
float TileIndexTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,45 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/texttileprovider.h>
namespace openspace::globebrowsing {
struct TileIndexTileProvider : public TextTileProvider {
TileIndexTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__
@@ -0,0 +1,213 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/asynctiledataprovider.h>
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/rawtiledatareader.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/interpolatetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/memorymanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/textureunit.h>
#include <filesystem>
#include <fstream>
#include "cpl_minixml.h"
namespace openspace::globebrowsing {
namespace {
std::unique_ptr<ghoul::opengl::Texture> DefaultTileTexture;
Tile DefaultTile = Tile { nullptr, std::nullopt, Tile::Status::Unavailable };
constexpr const char* KeyFilePath = "FilePath";
void reset(TextTileProvider& t) {
ZoneScoped
t.tileCache->clear();
}
} // namespace
unsigned int TileProvider::NumTileProviders = 0;
std::unique_ptr<TileProvider> TileProvider::createFromDictionary(
layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary)
{
ZoneScoped
const char* type = layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layerTypeID)];
auto factory = FactoryManager::ref().factory<TileProvider>();
TileProvider* result = factory->create(type, dictionary);
return std::unique_ptr<TileProvider>(result);
}
TileProvider::TileProvider() : properties::PropertyOwner({ "tileProvider" }) {}
void TileProvider::initialize() {
ZoneScoped
ghoul_assert(!isInitialized, "TileProvider can only be initialized once.");
if (TileProvider::NumTileProviders >
static_cast<unsigned int>(std::numeric_limits<uint16_t>::max()) - 1)
{
LERRORC(
"TileProvider",
"Number of tile providers exceeds 65535. Something will break soon"
);
TileProvider::NumTileProviders = 0;
}
uniqueIdentifier = static_cast<uint16_t>(TileProvider::NumTileProviders++);
if (TileProvider::NumTileProviders == std::numeric_limits<unsigned int>::max()) {
--TileProvider::NumTileProviders;
return;
}
internalInitialize();
isInitialized = true;
}
void TileProvider::deinitialize() {
ZoneScoped
internalDeinitialize();
}
void TileProvider::internalInitialize() {}
void TileProvider::internalDeinitialize() {}
ChunkTile TileProvider::chunkTile(TileIndex tileIndex, int parents, int maxParents) {
ZoneScoped
ghoul_assert(isInitialized, "TileProvider was not initialized.");
auto ascendToParent = [](TileIndex& ti, TileUvTransform& uv) {
uv.uvOffset *= 0.5;
uv.uvScale *= 0.5;
uv.uvOffset += ti.positionRelativeParent();
ti.x /= 2;
ti.y /= 2;
ti.level--;
};
TileUvTransform uvTransform = { glm::vec2(0.f, 0.f), glm::vec2(1.f, 1.f) };
// Step 1. Traverse 0 or more parents up the chunkTree as requested by the caller
for (int i = 0; i < parents && tileIndex.level > 1; i++) {
ascendToParent(tileIndex, uvTransform);
}
maxParents -= parents;
// Step 2. Traverse 0 or more parents up the chunkTree to make sure we're inside
// the range of defined data.
int maximumLevel = maxLevel();
while (tileIndex.level > maximumLevel) {
ascendToParent(tileIndex, uvTransform);
maxParents--;
}
if (maxParents < 0) {
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
// Step 3. Traverse 0 or more parents up the chunkTree until we find a chunk that
// has a loaded tile ready to use.
while (tileIndex.level > 1) {
Tile t = tile(tileIndex);
if (t.status != Tile::Status::OK) {
if (--maxParents < 0) {
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
ascendToParent(tileIndex, uvTransform);
}
else {
return ChunkTile { std::move(t), uvTransform, TileDepthTransform() };
}
}
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
ChunkTilePile TileProvider::chunkTilePile(TileIndex tileIndex, int pileSize) {
ZoneScoped
ghoul_assert(isInitialized, "TileProvider was not initialized.");
ghoul_assert(pileSize >= 0, "pileSize must be positive");
ChunkTilePile chunkTilePile;
std::fill(chunkTilePile.begin(), chunkTilePile.end(), std::nullopt);
for (int i = 0; i < pileSize; ++i) {
chunkTilePile[i] = chunkTile(tileIndex, i);
if (chunkTilePile[i]->tile.status == Tile::Status::Unavailable) {
if (i == 0) {
// First iteration
chunkTilePile[i]->tile = DefaultTile;
chunkTilePile[i]->uvTransform.uvOffset = { 0.f, 0.f };
chunkTilePile[i]->uvTransform.uvScale = { 1.f, 1.f };
}
else {
// We are iterating through the array one-by-one, so we are guaranteed
// that for tile 'i', tile 'i-1' already was initializated
chunkTilePile[i]->tile = chunkTilePile[i - 1]->tile;
chunkTilePile[i]->uvTransform.uvOffset =
chunkTilePile[i - 1]->uvTransform.uvOffset;
chunkTilePile[i]->uvTransform.uvScale =
chunkTilePile[i - 1]->uvTransform.uvScale;
}
}
}
return chunkTilePile;
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,142 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/ellipsoid.h>
#include <modules/globebrowsing/src/layergroupid.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <modules/globebrowsing/src/timequantizer.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <unordered_map>
#include <ghoul/opengl/programobject.h>
struct CPLXMLNode;
namespace ghoul::fontrendering {
class Font;
class FontRenderer;
} // namespace ghoul::fontrendering
namespace openspace { class PixelBuffer; }
namespace openspace::globebrowsing {
class AsyncTileDataProvider;
struct RawTile;
struct TileIndex;
namespace cache { class MemoryAwareTileCache; }
} // namespace openspace::globebrowsing
namespace openspace::globebrowsing {
enum class Type {
DefaultTileProvider = 0,
SingleImageTileProvider,
ImageSequenceTileProvider,
SizeReferenceTileProvider,
TemporalTileProvider,
TileIndexTileProvider,
ByIndexTileProvider,
ByLevelTileProvider,
InterpolateTileProvider
};
struct TileProvider : public properties::PropertyOwner {
static unsigned int NumTileProviders;
static std::unique_ptr<TileProvider> createFromDictionary(
layergroupid::TypeID layerTypeID, const ghoul::Dictionary& dictionary);
TileProvider();
virtual ~TileProvider() = default;
void initialize();
void deinitialize();
virtual Tile tile(const TileIndex& tileIndex) = 0;
/**
* Returns the status of a <code>Tile</code>. The <code>Tile::Status</code>
* corresponds the <code>Tile</code> that would be returned if the function
* <code>tile</code> would be invoked with the same <code>TileIndex</code> argument at
* this point in time.
*/
virtual Tile::Status tileStatus(const TileIndex& index) = 0;
/**
* Get the associated depth transform for this TileProvider. This is necessary for
* TileProviders serving height map data, in order to correcly map pixel values to
* meters.
*/
virtual TileDepthTransform depthTransform() = 0;
/**
* This method should be called once per frame. Here, TileProviders are given the
* opportunity to update their internal state.
*/
virtual void update() = 0;
/**
* Provides a uniform way of all TileProviders to reload or restore all of its
* internal state. This is mainly useful for debugging purposes.
*/
virtual void reset() = 0;
/**
* \return The maximum level as defined by <code>TileIndex</code> that this
* TileProvider is able provide.
*/
virtual int maxLevel() = 0;
/**
* \return the no data value for the dataset. Default is the minimum float value.
*/
virtual float noDataValueAsFloat() = 0;
ChunkTile chunkTile(TileIndex tileIndex, int parents = 0, int maxParents = 1337);
ChunkTilePile chunkTilePile(TileIndex tileIndex, int pileSize);
std::string name;
uint16_t uniqueIdentifier = 0;
bool isInitialized = false;
private:
virtual void internalInitialize();
virtual void internalDeinitialize();
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDER___H__
@@ -0,0 +1,145 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
namespace {
constexpr const char* KeyDefaultProvider = "DefaultProvider";
constexpr const char* KeyProviders = "IndexTileProviders";
constexpr const char* KeyTileIndex = "TileIndex";
constexpr const char* KeyTileProvider = "TileProvider";
} // namespace
namespace openspace::globebrowsing {
TileProviderByIndex::TileProviderByIndex(const ghoul::Dictionary& dictionary) {
ZoneScoped
const ghoul::Dictionary& defaultProviderDict = dictionary.value<ghoul::Dictionary>(
KeyDefaultProvider
);
layergroupid::TypeID typeID;
if (defaultProviderDict.hasValue<std::string>("Type")) {
const std::string& t = defaultProviderDict.value<std::string>("Type");
typeID = ghoul::from_string<layergroupid::TypeID>(t);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + t);
}
}
else {
typeID = layergroupid::TypeID::DefaultTileLayer;
}
defaultTileProvider = createFromDictionary(typeID, defaultProviderDict);
const ghoul::Dictionary& indexProvidersDict = dictionary.value<ghoul::Dictionary>(
KeyProviders
);
for (size_t i = 1; i <= indexProvidersDict.size(); i++) {
ghoul::Dictionary indexProviderDict = indexProvidersDict.value<ghoul::Dictionary>(
std::to_string(i)
);
ghoul::Dictionary tileIndexDict = indexProviderDict.value<ghoul::Dictionary>(
KeyTileIndex
);
ghoul::Dictionary providerDict = indexProviderDict.value<ghoul::Dictionary>(
KeyTileProvider
);
constexpr const char* KeyLevel = "Level";
constexpr const char* KeyX = "X";
constexpr const char* KeyY = "Y";
int level = static_cast<int>(tileIndexDict.value<double>(KeyLevel));
ghoul_assert(level < std::numeric_limits<uint8_t>::max(), "Level too large");
int x = static_cast<int>(tileIndexDict.value<double>(KeyX));
int y = static_cast<int>(tileIndexDict.value<double>(KeyY));
const TileIndex tileIndex(x, y, static_cast<uint8_t>(level));
layergroupid::TypeID providerTypeID = layergroupid::TypeID::DefaultTileLayer;
if (defaultProviderDict.hasValue<std::string>("Type")) {
const std::string& t = defaultProviderDict.value<std::string>("Type");
providerTypeID = ghoul::from_string<layergroupid::TypeID>(t);
if (providerTypeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + t);
}
}
std::unique_ptr<TileProvider> stp = createFromDictionary(
providerTypeID,
providerDict
);
TileIndex::TileHashKey key = tileIndex.hashKey();
tileProviderMap.insert(std::make_pair(key, std::move(stp)));
}
}
Tile TileProviderByIndex::tile(const TileIndex& tileIndex) {
ZoneScoped
const auto it = tileProviderMap.find(tileIndex.hashKey());
const bool hasProvider = it != tileProviderMap.end();
return hasProvider ? it->second->tile(tileIndex) : Tile();
}
Tile::Status TileProviderByIndex::tileStatus(const TileIndex& index) {
const auto it = tileProviderMap.find(index.hashKey());
const bool hasProvider = it != tileProviderMap.end();
return hasProvider ? it->second->tileStatus(index) : Tile::Status::Unavailable;
}
TileDepthTransform TileProviderByIndex::depthTransform() {
return defaultTileProvider->depthTransform();
}
void TileProviderByIndex::update() {
using K = TileIndex::TileHashKey;
using V = std::unique_ptr<TileProvider>;
for (std::pair<const K, V>& it : tileProviderMap) {
it.second->update();
}
defaultTileProvider->update();
}
void TileProviderByIndex::reset() {
using K = TileIndex::TileHashKey;
using V = std::unique_ptr<TileProvider>;
for (std::pair<const K, V>& it : tileProviderMap) {
it.second->reset();
}
defaultTileProvider->reset();
}
int TileProviderByIndex::maxLevel() {
return defaultTileProvider->maxLevel();
}
float TileProviderByIndex::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,52 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYINDEX___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYINDEX___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
struct TileProviderByIndex : public TileProvider {
TileProviderByIndex(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
std::unordered_map<
TileIndex::TileHashKey, std::unique_ptr<TileProvider>
> tileProviderMap;
std::unique_ptr<TileProvider> defaultTileProvider;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYINDEX___H__
@@ -0,0 +1,169 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
namespace {
constexpr const char* KeyProviders = "LevelTileProviders";
constexpr const char* KeyMaxLevel = "MaxLevel";
constexpr const char* KeyTileProvider = "TileProvider";
constexpr const char* KeyLayerGroupID = "LayerGroupID";
} // namespace
namespace openspace::globebrowsing {
TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
ZoneScoped
layergroupid::GroupID layerGroupID = static_cast<layergroupid::GroupID>(
dictionary.value<int>(KeyLayerGroupID)
);
if (dictionary.hasValue<ghoul::Dictionary>(KeyProviders)) {
ghoul::Dictionary providers = dictionary.value<ghoul::Dictionary>(KeyProviders);
for (size_t i = 1; i <= providers.size(); i++) {
ghoul::Dictionary levelProviderDict = providers.value<ghoul::Dictionary>(
std::to_string(i)
);
double floatMaxLevel = levelProviderDict.value<double>(KeyMaxLevel);
int maxLevel = static_cast<int>(std::round(floatMaxLevel));
ghoul::Dictionary providerDict = levelProviderDict.value<ghoul::Dictionary>(
KeyTileProvider
);
providerDict.setValue(KeyLayerGroupID, static_cast<int>(layerGroupID));
layergroupid::TypeID typeID;
if (providerDict.hasValue<std::string>("Type")) {
const std::string& typeString = providerDict.value<std::string>("Type");
typeID = ghoul::from_string<layergroupid::TypeID>(typeString);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + typeString);
}
}
else {
typeID = layergroupid::TypeID::DefaultTileLayer;
}
std::unique_ptr<TileProvider> tp = createFromDictionary(typeID, providerDict);
std::string provId = providerDict.value<std::string>("Identifier");
tp->setIdentifier(provId);
std::string providerName = providerDict.value<std::string>("Name");
tp->setGuiName(providerName);
addPropertySubOwner(tp.get());
levelTileProviders.push_back(std::move(tp));
// Ensure we can represent the max level
if (static_cast<int>(providerIndices.size()) < maxLevel) {
providerIndices.resize(maxLevel + 1, -1);
}
// map this level to the tile provider index
providerIndices[maxLevel] = static_cast<int>(levelTileProviders.size()) - 1;
}
}
// Fill in the gaps (value -1 ) in provider indices, from back to end
for (int i = static_cast<int>(providerIndices.size()) - 2; i >= 0; --i) {
if (providerIndices[i] == -1) {
providerIndices[i] = providerIndices[i + 1];
}
}
}
void TileProviderByLevel::internalInitialize() {
for (const std::unique_ptr<TileProvider>& prov : levelTileProviders) {
prov->initialize();
}
}
void TileProviderByLevel::internalDeinitialize() {
for (const std::unique_ptr<TileProvider>& prov : levelTileProviders) {
prov->deinitialize();
}
}
Tile TileProviderByLevel::tile(const TileIndex& tileIndex) {
ZoneScoped
TileProvider* provider = levelProvider(tileIndex.level);
if (provider) {
return provider->tile(tileIndex);
}
else {
return Tile();
}
}
Tile::Status TileProviderByLevel::tileStatus(const TileIndex& index) {
TileProvider* provider = levelProvider(index.level);
return provider ? provider->tileStatus(index) : Tile::Status::Unavailable;
}
TileProvider* TileProviderByLevel::levelProvider(int level) const {
ZoneScoped
if (!levelTileProviders.empty()) {
int clampedLevel = glm::clamp(
level,
0,
static_cast<int>(providerIndices.size() - 1)
);
int idx = providerIndices[clampedLevel];
return levelTileProviders[idx].get();
}
else {
return nullptr;
}
}
TileDepthTransform TileProviderByLevel::depthTransform() {
return { 0.f, 1.f };
}
void TileProviderByLevel::update() {
for (const std::unique_ptr<TileProvider>& provider : levelTileProviders) {
provider->update();
}
}
void TileProviderByLevel::reset() {
for (const std::unique_ptr<TileProvider>& provider : levelTileProviders) {
provider->reset();
}
}
int TileProviderByLevel::maxLevel() {
return static_cast<int>(providerIndices.size() - 1);
}
float TileProviderByLevel::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,54 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
struct TileProviderByLevel : public TileProvider {
TileProviderByLevel(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
std::vector<int> providerIndices;
std::vector<std::unique_ptr<TileProvider>> levelTileProviders;
private:
void internalInitialize() override final;
void internalDeinitialize() override final;
TileProvider* levelProvider(int level) const;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__