/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2017 * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { const char* KeyPerformPreProcessing = "PerformPreProcessing"; const char* KeyTilePixelSize = "TilePixelSize"; const char* KeyFilePath = "FilePath"; const char* KeyBasePath = "BasePath"; const char* KeyPreCacheLevel = "PreCacheLevel"; } namespace openspace { namespace globebrowsing { namespace tileprovider { DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary) : TileProvider(dictionary) , _filePath("filePath", "File Path", "") , _tilePixelSize("tilePixelSize", "Tile Pixel Size", 32, 32, 1024) , _preCacheLevel(0) { _tileCache = OsEng.moduleEngine().module()->tileCache(); _name = "Name unspecified"; dictionary.getValue("Name", _name); std::string _loggerCat = "DefaultTileProvider : " + _name; // 1. Get required Keys std::string filePath; dictionary.getValue(KeyFilePath, filePath); //filePath = absPath(filePath); _filePath.setValue(filePath); if (!dictionary.getValue("LayerGroupID", _layerGroupID)) { ghoul_assert(false, "Unknown layer group id"); } // 2. Initialize default values for any optional Keys // getValue does not work for integers double pixelSize = 0.0; int tilePixelSize = 0; if (dictionary.getValue(KeyTilePixelSize, pixelSize)) { LDEBUG("Default pixel size overridden: " << pixelSize); tilePixelSize = pixelSize; } TileTextureInitData initData(LayerManager::getTileTextureInitData( _layerGroupID, tilePixelSize)); _tilePixelSize.setValue(initData.dimensionsWithoutPadding().x); _performPreProcessing = LayerManager::shouldPerformPreProcessingOnLayergroup(_layerGroupID); if (dictionary.getValue(KeyPerformPreProcessing, _performPreProcessing)) { LDEBUG("Default PerformPreProcessing overridden: " << _performPreProcessing); } if (dictionary.hasKeyAndValue(KeyPreCacheLevel)) { _preCacheLevel = static_cast(dictionary.value(KeyPreCacheLevel)); } dictionary.getValue(KeyBasePath, _basePath); initAsyncTileDataReader(initData); // Properties addProperty(_filePath); addProperty(_tilePixelSize); } DefaultTileProvider::DefaultTileProvider( std::shared_ptr tileReader) : _asyncTextureDataProvider(tileReader) , _filePath("filePath", "File Path", "") , _tilePixelSize("tilePixelSize", "Tile Pixel Size", 32, 32, 1024) { } DefaultTileProvider::~DefaultTileProvider() { } void DefaultTileProvider::update() { if (_asyncTextureDataProvider) { _asyncTextureDataProvider->update(); initTexturesFromLoadedData(); if (_asyncTextureDataProvider->shouldBeDeleted()) { _asyncTextureDataProvider = nullptr; TileTextureInitData initData(LayerManager::getTileTextureInitData( _layerGroupID, _tilePixelSize)); initAsyncTileDataReader(initData); } } } void DefaultTileProvider::reset() { _tileCache->clear(); if (_asyncTextureDataProvider) { _asyncTextureDataProvider->prepairToBeDeleted(); } else { TileTextureInitData initData(LayerManager::getTileTextureInitData( _layerGroupID, _tilePixelSize)); initAsyncTileDataReader(initData); } } int DefaultTileProvider::maxLevel() { if (_asyncTextureDataProvider) { return _asyncTextureDataProvider->getRawTileDataReader()->maxChunkLevel(); } else { // Current theoretical maximum based on the number of hashes that are possible // to uniquely identify a tile. See ProviderTileHasher in memoryawaretilecache.h return 22; } } Tile DefaultTileProvider::getTile(const TileIndex& tileIndex) { if (_asyncTextureDataProvider) { if (tileIndex.level > maxLevel()) { return Tile(nullptr, nullptr, Tile::Status::OutOfRange); } cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; Tile tile = _tileCache->get(key); if (tile.texture() == nullptr) { _asyncTextureDataProvider->enqueueTileIO(tileIndex); } return tile; } else { return Tile(nullptr, nullptr, Tile::Status::Unavailable); } } float DefaultTileProvider::noDataValueAsFloat() { if (_asyncTextureDataProvider) { return _asyncTextureDataProvider->noDataValueAsFloat(); } else { return std::numeric_limits::min(); } } void DefaultTileProvider::initTexturesFromLoadedData() { if (_asyncTextureDataProvider) { std::shared_ptr rawTile = _asyncTextureDataProvider->popFinishedRawTile(); if (rawTile) { cache::ProviderTileKey key = { rawTile->tileIndex, uniqueIdentifier() }; ghoul_assert(!_tileCache->exist(key), "Tile must not be existing in cache"); _tileCache->createTileAndPut(key, rawTile); } } } void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData) { std::string _loggerCat = "DefaultTileProvider : " + _name; RawTileDataReader* tileDataReader = nullptr; RawTileDataReader::PerformPreprocessing preprocess = _performPreProcessing ? RawTileDataReader::PerformPreprocessing::Yes : RawTileDataReader::PerformPreprocessing::No; // Initialize instance variables #ifdef GLOBEBROWSING_USE_GDAL auto tileDataset = std::make_shared(_filePath, initData, _basePath, preprocess); #else // GLOBEBROWSING_USE_GDAL auto tileDataset = std::make_shared(_filePath, initData, preprocess); #endif // GLOBEBROWSING_USE_GDAL _asyncTextureDataProvider = std::make_shared(_name, tileDataset); if (_preCacheLevel > -1) { LDEBUG("Precaching '" << _filePath << "' with level '" << _preCacheLevel << "'"); for (int level = 0; level <= _preCacheLevel; ++level) { for (int x = 0; x <= level * 2; ++x) { for (int y = 0; y <= level; ++y) { _asyncTextureDataProvider->enqueueTileIO({ x, y, level }); } } } } } Tile::Status DefaultTileProvider::getTileStatus(const TileIndex& tileIndex) { if (_asyncTextureDataProvider) { auto rawTileDataReader = _asyncTextureDataProvider->getRawTileDataReader(); if (tileIndex.level > rawTileDataReader->maxChunkLevel()) { return Tile::Status::OutOfRange; } cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; return _tileCache->get(key).status(); } else { return Tile::Status::Unavailable; } } TileDepthTransform DefaultTileProvider::depthTransform() { if (_asyncTextureDataProvider) { return _asyncTextureDataProvider->getRawTileDataReader()->getDepthTransform(); } else { return { 1.0f, 0.0f }; } } } // namespace tileprovider } // namespace globebrowsing } // namespace openspace