From 14f9126df27d2a8bb9fd88b40bd3281c8d45f6e0 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Mon, 28 Nov 2016 17:39:43 +0100 Subject: [PATCH 1/8] Add TileProviderByLevel and use for Earth --- data/scene/lodglobes/lodearth/lodearth.mod | 39 ++++-- modules/globebrowsing/CMakeLists.txt | 2 + modules/globebrowsing/globebrowsingmodule.cpp | 2 + .../tile/tileprovider/tileproviderbylevel.cpp | 129 ++++++++++++++++++ .../tile/tileprovider/tileproviderbylevel.h | 74 ++++++++++ 5 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 modules/globebrowsing/tile/tileprovider/tileproviderbylevel.cpp create mode 100644 modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h diff --git a/data/scene/lodglobes/lodearth/lodearth.mod b/data/scene/lodglobes/lodearth/lodearth.mod index 3fa149799c..9f91c218da 100644 --- a/data/scene/lodglobes/lodearth/lodearth.mod +++ b/data/scene/lodglobes/lodearth/lodearth.mod @@ -57,8 +57,18 @@ return { Layers = { ColorLayers = { { - Name = "ESRI Imagery World 2D", - FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms", + Name = "ESRI VIIRS Combo", + Type = "ByLevel", + LevelTileProviders = { + { + MaxLevel = 7, + TileProvider = { FilePath = "map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", }, + }, + { + MaxLevel = 22, + TileProvider = { FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms" }, + }, + }, Enabled = true, }, { @@ -71,15 +81,10 @@ return { Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature", FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml", }, - { - Name = "VIIRS_SNPP_CorrectedReflectance_TrueColor", - FilePath = "map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", - Enabled = true, - }, { Type = "SingleImage", Name = "Debug Tiles", - FilePath = "textures/test_tile.png", + FilePath = "../../debugglobe/textures/test_tile.png", }, }, GrayScaleLayers = { }, @@ -111,12 +116,30 @@ return { Name = "Reference_Labels", FilePath = "map_service_configs/GIBS/Reference_Labels.xml", }, + { + Type = "TileIndex", + Name = "Tile Indices", + }, { Type = "SizeReference", Name = "Size Reference", Radii = earthEllipsoid, BackgroundImagePath = "../../debugglobe/textures/arrows.png", }, + --[[{ + Name = "Test", + Type = "LevelSpecific", + LevelTileProviders = { + { + MaxLevel = 5, + TileProvider = { Type = "TileIndex" }, + }, + { + MaxLevel = 7, + TileProvider = { Type = "SingleImage", FilePath = "../../debugglobe/textures/test_tile.png",}, + }, + }, + },]] }, HeightLayers = { { diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 76a96a1a14..924b57c3da 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -47,6 +47,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h @@ -99,6 +100,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index e7ba3e3aab..929782947a 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,7 @@ void GlobeBrowsingModule::internalInitialize() { fTileProvider->registerClass("Temporal"); fTileProvider->registerClass("TileIndex"); fTileProvider->registerClass("SizeReference"); + fTileProvider->registerClass("ByLevel"); } } // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.cpp b/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.cpp new file mode 100644 index 0000000000..b9704182b1 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.cpp @@ -0,0 +1,129 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 + +namespace { + const std::string _loggerCat = "TileProviderByLevel"; + + const std::string KeyProviders = "LevelTileProviders"; + const std::string KeyMaxLevel = "MaxLevel"; + const std::string KeyTileProvider = "TileProvider"; +} + +namespace openspace { +namespace globebrowsing { + + TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) { + + ghoul::Dictionary levelProvidersDict = dictionary.value(KeyProviders); + for (size_t i = 0; i < levelProvidersDict.size(); i++) { + std::string dictKey = std::to_string(i + 1); + ghoul::Dictionary levelProviderDict = levelProvidersDict.value(dictKey); + double floatMaxLevel; + int maxLevel = 0; + if (!levelProviderDict.getValue(KeyMaxLevel, floatMaxLevel)) { + throw std::runtime_error("Must define key '" + KeyMaxLevel + "'"); + } + maxLevel = std::round(floatMaxLevel); + + ghoul::Dictionary providerDict; + if (!levelProviderDict.getValue(KeyTileProvider, providerDict)) { + throw std::runtime_error("Must define key '" + KeyTileProvider + "'"); + } + + TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict); + _levelTileProviders.push_back(std::shared_ptr(tileProvider)); + + // Ensure we can represent the max level + if(_providerIndices.size() < maxLevel){ + _providerIndices.resize(maxLevel+1, -1); + } + + // map this level to the tile provider index + _providerIndices[maxLevel] = _levelTileProviders.size() - 1; + } + + // Fill in the gaps (value -1) in provider indices, from back to end + for(int i = _providerIndices.size() - 2; i>=0; --i){ + if(_providerIndices[i] == -1){ + _providerIndices[i] = _providerIndices[i+1]; + } + } + } + + Tile TileProviderByLevel::getTile(const TileIndex& tileIndex) { + return levelProvider(tileIndex.level)->getTile(tileIndex); + } + + Tile TileProviderByLevel::getDefaultTile() { + return levelProvider(0)->getDefaultTile(); + } + + Tile::Status TileProviderByLevel::getTileStatus(const TileIndex& index) { + return levelProvider(index.level)->getTileStatus(index); + } + + TileDepthTransform TileProviderByLevel::depthTransform() { + TileDepthTransform transform; + transform.depthOffset = 0.0f; + transform.depthScale = 1.0f; + return transform; + } + + void TileProviderByLevel::update() { + for(auto provider : _levelTileProviders){ + provider->update(); + } + } + + void TileProviderByLevel::reset() { + for(auto provider : _levelTileProviders){ + provider->reset(); + } + } + + int TileProviderByLevel::maxLevel() { + return _providerIndices.size()-1; + } + + int TileProviderByLevel::providerIndex(int level) const { + int clampedLevel = std::max(0, std::min(level, (int)_providerIndices.size()-1)); + return _providerIndices[clampedLevel]; + } + + TileProvider* TileProviderByLevel::levelProvider(int level) const{ + return _levelTileProviders[providerIndex(level)].get(); + } + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h b/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h new file mode 100644 index 0000000000..651cc9616e --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h @@ -0,0 +1,74 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 __TILE_PROVIDER_BY_LEVEL__ +#define __TILE_PROVIDER_BY_LEVEL__ + +#include +#include +#include + +#include + +#include + +#include +#include // absPath +#include +#include +#include + +#include + +namespace openspace { +namespace globebrowsing { + + using namespace ghoul::opengl; + + class TileProviderByLevel : public TileProvider { + public: + + TileProviderByLevel(const ghoul::Dictionary& dictionary); + TileProviderByLevel(const std::string& imagePath); + virtual ~TileProviderByLevel() { } + + virtual Tile getTile(const TileIndex& tileIndex); + virtual Tile getDefaultTile(); + virtual Tile::Status getTileStatus(const TileIndex& index); + virtual TileDepthTransform depthTransform(); + virtual void update(); + virtual void reset(); + virtual int maxLevel(); + private: + inline int providerIndex(int level) const; + inline TileProvider* levelProvider(int level) const; + + std::vector _providerIndices; + std::vector> _levelTileProviders; + }; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __TILE_PROVIDER_BY_LEVEL__ From e6d758a418df6c77b3e99779541bea24512a5eab Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Mon, 28 Nov 2016 18:09:26 +0100 Subject: [PATCH 2/8] Move ChunkTile selection to TileProvider interface --- .../globebrowsing/globes/chunkedlodglobe.cpp | 2 +- .../globebrowsing/rendering/layermanager.cpp | 7 +-- .../tile/tileprovider/tileprovider.cpp | 54 ++++++++++++++++++ .../tile/tileprovider/tileprovider.h | 10 ++++ modules/globebrowsing/tile/tileselector.cpp | 56 +------------------ modules/globebrowsing/tile/tileselector.h | 8 +-- 6 files changed, 70 insertions(+), 67 deletions(-) diff --git a/modules/globebrowsing/globes/chunkedlodglobe.cpp b/modules/globebrowsing/globes/chunkedlodglobe.cpp index d4776092bd..25fd9e4c56 100644 --- a/modules/globebrowsing/globes/chunkedlodglobe.cpp +++ b/modules/globebrowsing/globes/chunkedlodglobe.cpp @@ -200,7 +200,7 @@ namespace globebrowsing { for (const auto& layer : heightMapLayers) { TileProvider* tileProvider = layer->tileProvider(); // Transform the uv coordinates to the current tile texture - ChunkTile chunkTile = TileSelector::getHighestResolutionTile(tileProvider, tileIndex); + ChunkTile chunkTile = tileProvider->getChunkTile(tileIndex); const auto& tile = chunkTile.tile; const auto& uvTransform = chunkTile.uvTransform; const auto& depthTransform = tileProvider->depthTransform(); diff --git a/modules/globebrowsing/rendering/layermanager.cpp b/modules/globebrowsing/rendering/layermanager.cpp index 80fff54721..bdb5e5e4fc 100644 --- a/modules/globebrowsing/rendering/layermanager.cpp +++ b/modules/globebrowsing/rendering/layermanager.cpp @@ -83,11 +83,8 @@ namespace globebrowsing { } - ChunkTilePile Layer::getChunkTilePile( - const TileIndex& tileIndex, - int pileSize) const { - return std::move(TileSelector::getHighestResolutionTilePile( - _tileProvider.get(), tileIndex, pileSize)); + ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const { + return std::move(_tileProvider->getChunkTilePile(tileIndex, pileSize)); } ////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp index d499c79f4f..241495794a 100644 --- a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp @@ -27,6 +27,8 @@ #include #include +#include +#include #include @@ -61,5 +63,57 @@ float TileProvider::noDataValueAsFloat() { return std::numeric_limits::min(); } +ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents){ + TileUvTransform uvTransform; + uvTransform.uvOffset = glm::vec2(0, 0); + uvTransform.uvScale = glm::vec2(1, 1); + + // 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++) { + TileSelector::ascendToParent(tileIndex, uvTransform); + } + + // 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){ + TileSelector::ascendToParent(tileIndex, uvTransform); + } + + // 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 tile = getTile(tileIndex); + if (tile.status != Tile::Status::OK) { + TileSelector::ascendToParent(tileIndex, uvTransform); + } + else return { tile, uvTransform }; + } + + return{ Tile::TileUnavailable, uvTransform }; +} + +ChunkTilePile TileProvider::getChunkTilePile(TileIndex tileIndex, int pileSize){ + ghoul_assert(pileSize >= 0, "pileSize must be positive"); + ChunkTilePile chunkTilePile; + chunkTilePile.chunkTiles.resize(pileSize); + for (size_t i = 0; i < pileSize; ++i){ + chunkTilePile.chunkTiles[i] = getChunkTile(tileIndex, i); + if (chunkTilePile.chunkTiles[i].tile.status == Tile::Status::Unavailable) { + if(i>0){ + chunkTilePile.chunkTiles[i].tile = chunkTilePile.chunkTiles[i-1].tile; + chunkTilePile.chunkTiles[i].uvTransform.uvOffset = chunkTilePile.chunkTiles[i-1].uvTransform.uvOffset; + chunkTilePile.chunkTiles[i].uvTransform.uvScale = chunkTilePile.chunkTiles[i-1].uvTransform.uvScale; + } + else{ + chunkTilePile.chunkTiles[i].tile = getDefaultTile(); + chunkTilePile.chunkTiles[i].uvTransform.uvOffset = { 0, 0 }; + chunkTilePile.chunkTiles[i].uvTransform.uvScale = { 1, 1 }; + } + } + } + return std::move(chunkTilePile); +} + } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileprovider.h b/modules/globebrowsing/tile/tileprovider/tileprovider.h index 653d879b8f..e85ff5f149 100644 --- a/modules/globebrowsing/tile/tileprovider/tileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/tileprovider.h @@ -40,6 +40,9 @@ namespace openspace { namespace globebrowsing { + + class ChunkTile; + class ChunkTilePile; using namespace ghoul::opengl; @@ -96,6 +99,13 @@ namespace globebrowsing { */ virtual Tile getTile(const TileIndex& tileIndex) = 0; + + virtual ChunkTile getChunkTile(TileIndex tileIndex, int parents = 0); + + + virtual ChunkTilePile getChunkTilePile(TileIndex tileIndex, int pileSize); + + /** * TileProviders must be able to provide a defualt * Tile which may be used by clients in cases when diff --git a/modules/globebrowsing/tile/tileselector.cpp b/modules/globebrowsing/tile/tileselector.cpp index 05d206aab7..d8cbe873cd 100644 --- a/modules/globebrowsing/tile/tileselector.cpp +++ b/modules/globebrowsing/tile/tileselector.cpp @@ -42,65 +42,13 @@ namespace globebrowsing { const TileSelector::CompareResolution TileSelector::HIGHEST_RES = TileSelector::CompareResolution(); - ChunkTilePile TileSelector::getHighestResolutionTilePile(TileProvider* tileProvider, TileIndex tileIndex, int pileSize){ - ghoul_assert(pileSize >= 0, "pileSize must be positive"); - ChunkTilePile chunkTilePile; - chunkTilePile.chunkTiles.resize(pileSize); - for (size_t i = 0; i < pileSize; ++i){ - chunkTilePile.chunkTiles[i] = TileSelector::getHighestResolutionTile(tileProvider, tileIndex, i); - if (chunkTilePile.chunkTiles[i].tile.status == Tile::Status::Unavailable) { - if(i>0){ - chunkTilePile.chunkTiles[i].tile = chunkTilePile.chunkTiles[i-1].tile; - chunkTilePile.chunkTiles[i].uvTransform.uvOffset = chunkTilePile.chunkTiles[i-1].uvTransform.uvOffset; - chunkTilePile.chunkTiles[i].uvTransform.uvScale = chunkTilePile.chunkTiles[i-1].uvTransform.uvScale; - } - else{ - chunkTilePile.chunkTiles[i].tile = tileProvider->getDefaultTile(); - chunkTilePile.chunkTiles[i].uvTransform.uvOffset = { 0, 0 }; - chunkTilePile.chunkTiles[i].uvTransform.uvScale = { 1, 1 }; - } - } - } - return std::move(chunkTilePile); - } - - ChunkTile TileSelector::getHighestResolutionTile(TileProvider* tileProvider, TileIndex tileIndex, int parents) { - TileUvTransform uvTransform; - uvTransform.uvOffset = glm::vec2(0, 0); - uvTransform.uvScale = glm::vec2(1, 1); - - // 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); - } - - // Step 2. Traverse 0 or more parents up the chunkTree to make sure we're inside - // the range of defined data. - int maximumLevel = tileProvider->maxLevel(); - while(tileIndex.level > maximumLevel){ - ascendToParent(tileIndex, uvTransform); - } - - // 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 tile = tileProvider->getTile(tileIndex); - if (tile.status != Tile::Status::OK) { - ascendToParent(tileIndex, uvTransform); - } - else return { tile, uvTransform }; - } - - return{ Tile::TileUnavailable, uvTransform }; - } - ChunkTile TileSelector::getHighestResolutionTile(const LayerGroup& layerGroup, TileIndex tileIndex) { ChunkTile mostHighResolution; mostHighResolution.tile = Tile::TileUnavailable; mostHighResolution.uvTransform.uvScale.x = 0; for (const auto& layer : layerGroup.activeLayers()) { - ChunkTile chunkTile = getHighestResolutionTile(layer->tileProvider(), tileIndex); + ChunkTile chunkTile = layer->tileProvider()->getChunkTile(tileIndex); bool tileIsOk = chunkTile.tile.status == Tile::Status::OK; bool tileHasMetaData = chunkTile.tile.metaData != nullptr; bool tileIsHigherResolution = chunkTile.uvTransform.uvScale.x > mostHighResolution.uvTransform.uvScale.x; @@ -120,7 +68,7 @@ namespace globebrowsing { std::vector TileSelector::getTilesSortedByHighestResolution(const LayerGroup& layerGroup, const TileIndex& tileIndex) { std::vector tiles; for (const auto& layer : layerGroup.activeLayers()) { - tiles.push_back(getHighestResolutionTile(layer->tileProvider(), tileIndex)); + tiles.push_back(layer->tileProvider()->getChunkTile(tileIndex)); } std::sort(tiles.begin(), tiles.end(), TileSelector::HIGHEST_RES); diff --git a/modules/globebrowsing/tile/tileselector.h b/modules/globebrowsing/tile/tileselector.h index d36fde2b89..9e955a5f7b 100644 --- a/modules/globebrowsing/tile/tileselector.h +++ b/modules/globebrowsing/tile/tileselector.h @@ -41,12 +41,7 @@ namespace globebrowsing { class TileSelector { public: - static ChunkTile getHighestResolutionTile(TileProvider* tileProvider, TileIndex tileIndex, int parents = 0); - static ChunkTile getHighestResolutionTile( - const LayerGroup& layerGroup, - TileIndex tileIndex - ); - static ChunkTilePile getHighestResolutionTilePile(TileProvider* tileProvider, TileIndex tileIndex, int pileSize); + static ChunkTile getHighestResolutionTile(const LayerGroup& layerGroup, TileIndex tileIndex); static std::vector getTilesSortedByHighestResolution(const LayerGroup& layerGroup, const TileIndex& tileIndex); struct CompareResolution { @@ -55,7 +50,6 @@ namespace globebrowsing { static const CompareResolution HIGHEST_RES; - private: static void ascendToParent(TileIndex& tileIndex, TileUvTransform& uv); }; From f7957255f85203701c63190c4bdd9730593aa6fe Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Mon, 28 Nov 2016 18:19:04 +0100 Subject: [PATCH 3/8] Add and use TileIndex positionRelativeParent --- modules/globebrowsing/tile/tileindex.cpp | 6 ++++++ modules/globebrowsing/tile/tileindex.h | 10 ++++++---- modules/globebrowsing/tile/tileselector.cpp | 9 +-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/modules/globebrowsing/tile/tileindex.cpp b/modules/globebrowsing/tile/tileindex.cpp index 59e2836b2d..bbb890bf2b 100644 --- a/modules/globebrowsing/tile/tileindex.cpp +++ b/modules/globebrowsing/tile/tileindex.cpp @@ -79,6 +79,12 @@ namespace globebrowsing { return *this; } + + glm::vec2 TileIndex::positionRelativeParent() const{ + // In OpenGL, positive y direction is up + return glm::vec2(isEastChild() ? 0.5 : 0, isNorthChild() ? 0.5 : 0); + } + /** Gets the tile at a specified offset from this tile. Accepts delta indices ranging from [-2^level, Infinity[ diff --git a/modules/globebrowsing/tile/tileindex.h b/modules/globebrowsing/tile/tileindex.h index 61ce061578..31680dd602 100644 --- a/modules/globebrowsing/tile/tileindex.h +++ b/modules/globebrowsing/tile/tileindex.h @@ -72,24 +72,26 @@ struct TileIndex { TileIndex& operator-=(unsigned int levels); - bool isWestChild() const { + inline bool isWestChild() const { return x % 2 == 0; } - bool isEastChild() const { + inline bool isEastChild() const { return x % 2 == 1; } - bool isNorthChild() const { + inline bool isNorthChild() const { return y % 2 == 0; } - bool isSouthChild() const { + inline bool isSouthChild() const { return y % 2 == 1; } TileIndex child(Quad q) const; + glm::vec2 positionRelativeParent() const; + std::string toString() const; diff --git a/modules/globebrowsing/tile/tileselector.cpp b/modules/globebrowsing/tile/tileselector.cpp index d8cbe873cd..773c998fe5 100644 --- a/modules/globebrowsing/tile/tileselector.cpp +++ b/modules/globebrowsing/tile/tileselector.cpp @@ -80,14 +80,7 @@ namespace globebrowsing { uv.uvOffset *= 0.5; uv.uvScale *= 0.5; - if (tileIndex.isEastChild()) { - uv.uvOffset.x += 0.5; - } - - // In OpenGL, positive y direction is up - if (tileIndex.isNorthChild()) { - uv.uvOffset.y += 0.5; - } + uv.uvOffset += tileIndex.positionRelativeParent(); --tileIndex; } From 3eedf20eba4edf498c4e13a740de671802650115 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Tue, 29 Nov 2016 01:05:13 +0100 Subject: [PATCH 4/8] Add ghoul dictionary constructor to TileIndex --- modules/globebrowsing/tile/tileindex.cpp | 15 +++++++++++++++ modules/globebrowsing/tile/tileindex.h | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/modules/globebrowsing/tile/tileindex.cpp b/modules/globebrowsing/tile/tileindex.cpp index bbb890bf2b..11676bd7f8 100644 --- a/modules/globebrowsing/tile/tileindex.cpp +++ b/modules/globebrowsing/tile/tileindex.cpp @@ -25,10 +25,16 @@ #include #include +#include + #include namespace { const std::string _loggerCat = "TileIndex"; + + const std::string KeyLevel = "Level"; + const std::string KeyX = "X"; + const std::string KeyY = "Y"; } namespace openspace { @@ -50,6 +56,15 @@ namespace globebrowsing { y = floor(yIndexSpace); } + /** + * Initializes a TileIndex from a Dictionary + */ + TileIndex::TileIndex(const ghoul::Dictionary& dict){ + level = static_cast(dict.value(KeyLevel)); + x = static_cast(dict.value(KeyX)); + y = static_cast(dict.value(KeyY)); + } + TileIndex TileIndex::child(Quad q) const { return TileIndex(2 * x + q % 2, 2 * y + q / 2, level + 1); } diff --git a/modules/globebrowsing/tile/tileindex.h b/modules/globebrowsing/tile/tileindex.h index 31680dd602..44b9b15d6b 100644 --- a/modules/globebrowsing/tile/tileindex.h +++ b/modules/globebrowsing/tile/tileindex.h @@ -31,6 +31,10 @@ #include #include +namespace ghoul{ + class Dictionary; +} + namespace openspace { namespace globebrowsing { @@ -59,6 +63,7 @@ struct TileIndex { TileIndex(int x, int y, int level) : x(x), y(y), level(level) { } TileIndex(const TileIndex& other) : x(other.x), y(other.y), level(other.level) { } TileIndex(const Geodetic2& point, int level); + TileIndex(const ghoul::Dictionary& dict); bool hasParent() const { From 0f4ab1887696b95ed22691b1b3e42747e5e4c076 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Tue, 29 Nov 2016 01:06:45 +0100 Subject: [PATCH 5/8] Add TileProviderByIndex and use test for Earth --- modules/globebrowsing/CMakeLists.txt | 6 +- modules/globebrowsing/globebrowsingmodule.cpp | 6 +- .../tile/tileprovider/tileproviderbyindex.cpp | 111 ++++++++++++++++++ .../tile/tileprovider/tileproviderbyindex.h | 75 ++++++++++++ 4 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 modules/globebrowsing/tile/tileprovider/tileproviderbyindex.cpp create mode 100644 modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 924b57c3da..839169ab82 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -47,10 +47,11 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilepile.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.h @@ -100,10 +101,11 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/texttileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilepile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/chunktile.cpp diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 929782947a..fcb050707c 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -36,9 +36,10 @@ #include #include #include -#include #include #include +#include +#include namespace openspace { @@ -66,7 +67,10 @@ void GlobeBrowsingModule::internalInitialize() { fTileProvider->registerClass("Temporal"); fTileProvider->registerClass("TileIndex"); fTileProvider->registerClass("SizeReference"); + + // Combining Tile Providers fTileProvider->registerClass("ByLevel"); + fTileProvider->registerClass("ByIndex"); } } // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.cpp b/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.cpp new file mode 100644 index 0000000000..ed03e8228e --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.cpp @@ -0,0 +1,111 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 + +namespace { + const std::string _loggerCat = "TileProviderByIndex"; + + const std::string KeyDefaultProvider = "DefaultProvider"; + const std::string KeyProviders = "IndexTileProviders"; + const std::string KeyTileIndex = "TileIndex"; + const std::string KeyTileProvider = "TileProvider"; +} + +namespace openspace { +namespace globebrowsing { + + TileProviderByIndex::TileProviderByIndex(const ghoul::Dictionary& dictionary) { + ghoul::Dictionary defaultProviderDict = dictionary.value(KeyDefaultProvider); + TileProvider * defaultProvider = TileProvider::createFromDictionary(defaultProviderDict); + _defaultTileProvider = std::shared_ptr(defaultProvider); + + ghoul::Dictionary indexProvidersDict = dictionary.value(KeyProviders); + for (size_t i = 0; i < indexProvidersDict.size(); i++) { + std::string dictKey = std::to_string(i + 1); + ghoul::Dictionary indexProviderDict = indexProvidersDict.value(dictKey); + ghoul::Dictionary tileIndexDict = indexProviderDict.value(KeyTileIndex); + ghoul::Dictionary providerDict = indexProviderDict.value(KeyTileProvider); + + TileIndex tileIndex(tileIndexDict); + TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict); + std::shared_ptr stp = std::shared_ptr(tileProvider); + TileHashKey key = tileIndex.hashKey(); + _tileProviderMap.insert(std::make_pair(key, stp)); + } + } + + Tile TileProviderByIndex::getTile(const TileIndex& tileIndex) { + auto it = _tileProviderMap.find(tileIndex.hashKey()); + bool hasProvider = it != _tileProviderMap.end(); + return hasProvider ? it->second->getTile(tileIndex) : Tile::TileUnavailable; + } + + Tile TileProviderByIndex::getDefaultTile() { + return _defaultTileProvider->getDefaultTile(); + } + + Tile::Status TileProviderByIndex::getTileStatus(const TileIndex& tileIndex) { + auto it = _tileProviderMap.find(tileIndex.hashKey()); + bool hasProvider = it != _tileProviderMap.end(); + return hasProvider ? it->second->getTileStatus(tileIndex) : Tile::Status::Unavailable; + } + + TileDepthTransform TileProviderByIndex::depthTransform() { + _defaultTileProvider->depthTransform(); + } + + void TileProviderByIndex::update() { + for(auto it : _tileProviderMap){ + it.second->update(); + } + _defaultTileProvider->update(); + } + + void TileProviderByIndex::reset() { + for(auto it : _tileProviderMap){ + it.second->reset(); + } + _defaultTileProvider->reset(); + } + + int TileProviderByIndex::maxLevel() { + return _defaultTileProvider->maxLevel(); + } + + TileProvider* TileProviderByIndex::indexProvider(const TileIndex& tileIndex) const{ + auto it = _tileProviderMap.find(tileIndex.hashKey()); + return (it != _tileProviderMap.end()) ? it->second.get() : nullptr; + } + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h b/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h new file mode 100644 index 0000000000..bb0d257a66 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h @@ -0,0 +1,75 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 __TILE_PROVIDER_BY_INDEX__ +#define __TILE_PROVIDER_BY_INDEX__ + +#include +#include +#include + +#include + +#include + +#include +#include // absPath +#include +#include +#include + +#include + +namespace openspace { +namespace globebrowsing { + + using namespace ghoul::opengl; + + class TileProviderByIndex : public TileProvider { + public: + + TileProviderByIndex(const ghoul::Dictionary& dictionary); + TileProviderByIndex(const std::string& imagePath); + virtual ~TileProviderByIndex() { } + + virtual Tile getTile(const TileIndex& tileIndex); + virtual Tile getDefaultTile(); + virtual Tile::Status getTileStatus(const TileIndex& index); + virtual TileDepthTransform depthTransform(); + virtual void update(); + virtual void reset(); + virtual int maxLevel(); + + private: + + inline TileProvider* indexProvider(const TileIndex& tileIndex) const; + + std::unordered_map> _tileProviderMap; + std::shared_ptr _defaultTileProvider; + }; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __TILE_PROVIDER_BY_INDEX__ From 0df09d23ad01d4aaa5a34482b6734c2957f68b43 Mon Sep 17 00:00:00 2001 From: kalbl Date: Tue, 29 Nov 2016 13:29:02 +0100 Subject: [PATCH 6/8] Add possibility to switch geographic position --- .../interaction/interactionhandler.h | 5 +- .../openspace/interaction/interactionmode.h | 14 ++- modules/globebrowsing/geometry/geodetic2.cpp | 5 ++ modules/globebrowsing/geometry/geodetic2.h | 1 + .../globebrowsing/globes/renderableglobe.cpp | 4 +- .../globebrowsing/globes/renderableglobe.h | 1 + .../globebrowsing/rendering/chunkrenderer.cpp | 2 +- .../shaders/globalchunkedlodpatch_fs.glsl | 2 +- src/interaction/interactionhandler.cpp | 34 +++++++ src/interaction/interactionhandler_lua.inl | 31 +++++++ src/interaction/interactionmode.cpp | 88 +++++++++++++++++++ 11 files changed, 182 insertions(+), 5 deletions(-) diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 1018f37068..d81e85bde5 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -65,7 +65,10 @@ public: // Interaction mode setters void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict); void setInteractionMode(const std::string& interactionModeKey); - + + void goToChunk(int x, int y, int level); + void goToGeo(double latitude, double longitude); + void resetKeyBindings(); void addKeyframe(const datamessagestructures::CameraKeyframe &kf); diff --git a/include/openspace/interaction/interactionmode.h b/include/openspace/interaction/interactionmode.h index 4a5f418db9..25688a2e77 100644 --- a/include/openspace/interaction/interactionmode.h +++ b/include/openspace/interaction/interactionmode.h @@ -31,6 +31,10 @@ #include #include +#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED +#include +#include +#endif #include @@ -258,7 +262,15 @@ public: virtual void setFocusNode(SceneGraphNode* focusNode); //virtual void update(Camera& camera, const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); - +#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED + void goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv, + bool resetCameraDirection); + void goToGeodetic2(Camera& camera, globebrowsing::Geodetic2 geo2, + bool resetCameraDirection); + + void goToGeodetic3(Camera& camera, globebrowsing::Geodetic3 geo3); + void resetCameraDirection(Camera& camera, globebrowsing::Geodetic2 geo2); +#endif private: //void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED diff --git a/modules/globebrowsing/geometry/geodetic2.cpp b/modules/globebrowsing/geometry/geodetic2.cpp index 1e22cca34a..5e7fd44b56 100644 --- a/modules/globebrowsing/geometry/geodetic2.cpp +++ b/modules/globebrowsing/geometry/geodetic2.cpp @@ -149,6 +149,11 @@ namespace globebrowsing { } } + Geodetic2 GeodeticPatch::getSize() const { + return _halfSize * 2; + } + + Scalar GeodeticPatch::minLat() const { return _center.lat - _halfSize.lat; } diff --git a/modules/globebrowsing/geometry/geodetic2.h b/modules/globebrowsing/geometry/geodetic2.h index 5a344c05a7..40481ddf23 100644 --- a/modules/globebrowsing/geometry/geodetic2.h +++ b/modules/globebrowsing/geometry/geodetic2.h @@ -108,6 +108,7 @@ public: Scalar isNorthern() const; Geodetic2 getCorner(Quad q) const; + Geodetic2 getSize() const; Scalar minLat() const; Scalar maxLat() const; diff --git a/modules/globebrowsing/globes/renderableglobe.cpp b/modules/globebrowsing/globes/renderableglobe.cpp index 6336818f2e..422ef41431 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -80,7 +80,8 @@ namespace globebrowsing { properties::BoolProperty("levelByProjectedAreaElseDistance", "level by projected area (else distance)",false), properties::BoolProperty("resetTileProviders", "reset tile providers", false), properties::BoolProperty("toggleEnabledEveryFrame", "toggle enabled every frame", false), - properties::BoolProperty("collectStats", "collect stats", false) + properties::BoolProperty("collectStats", "collect stats", false), + properties::BoolProperty("onlyModelSpaceRendering", "Only Model Space Rendering", false) }) { @@ -144,6 +145,7 @@ namespace globebrowsing { _debugPropertyOwner.addProperty(_debugProperties.resetTileProviders); _debugPropertyOwner.addProperty(_debugProperties.toggleEnabledEveryFrame); _debugPropertyOwner.addProperty(_debugProperties.collectStats); + _debugPropertyOwner.addProperty(_debugProperties.onlyModelSpaceRendering); addPropertySubOwner(_debugPropertyOwner); addPropertySubOwner(_layerManager.get()); diff --git a/modules/globebrowsing/globes/renderableglobe.h b/modules/globebrowsing/globes/renderableglobe.h index ed66466d1b..afa3042f2c 100644 --- a/modules/globebrowsing/globes/renderableglobe.h +++ b/modules/globebrowsing/globes/renderableglobe.h @@ -73,6 +73,7 @@ public: properties::BoolProperty resetTileProviders; properties::BoolProperty toggleEnabledEveryFrame; properties::BoolProperty collectStats; + properties::BoolProperty onlyModelSpaceRendering; }; struct GeneralProperties { diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 98b084bd1d..53b0aedede 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -80,7 +80,7 @@ namespace globebrowsing { void ChunkRenderer::renderChunk(const Chunk& chunk, const RenderData& data) { // A little arbitrary with 10 but it works - if (chunk.tileIndex().level < 10) { + if (chunk.owner().debugProperties().onlyModelSpaceRendering || chunk.tileIndex().level < 10) { renderChunkGlobally(chunk, data); } else { diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl index 9a90381e25..9b1764e690 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl @@ -30,7 +30,7 @@ Fragment getFragment() { frag.color = getTileFragColor(); #if SHOW_CHUNK_EDGES - frag.color += patchBorderOverlay(fs_uv, vec3(0,1,0), 0.005); + frag.color += patchBorderOverlay(fs_uv, vec3(0,1,0), 0.02); #endif // SHOW_CHUNK_EDGES frag.depth = fs_position.w; diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index e9af75dead..63cf497c4e 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -203,6 +203,28 @@ void InteractionHandler::setInteractionMode(const std::string& interactionModeKe "' is not a valid interaction mode. Candidates are " << listInteractionModes); } } + +void InteractionHandler::goToChunk(int x, int y, int level) { + std::shared_ptr gbim = + std::dynamic_pointer_cast (_currentInteractionMode); + + if (gbim) { + gbim->goToChunk(*_camera, globebrowsing::TileIndex(x,y,level), glm::vec2(0.5,0.5), true); + } else { + LWARNING("Interaction mode must be set to 'GlobeBrowsing'"); + } +} + +void InteractionHandler::goToGeo(double latitude, double longitude) { + std::shared_ptr gbim = + std::dynamic_pointer_cast (_currentInteractionMode); + + if (gbim) { + gbim->goToGeodetic2(*_camera, globebrowsing::Geodetic2(latitude, longitude) / 180 * M_PI, true); + } else { + LWARNING("Interaction mode must be set to 'GlobeBrowsing'"); + } +} void InteractionHandler::lockControls() { @@ -568,6 +590,18 @@ scripting::LuaLibrary InteractionHandler::luaLibrary() { "void", "Reset the camera direction to point at the focus node" }, + { + "goToChunk", + &luascriptfunctions::goToChunk, + "void", + "Go to chunk with given index x, y, level" + }, + { + "goToGeo", + &luascriptfunctions::goToGeo, + "void", + "Go to geographic coordinates latitude and longitude" + }, } }; } diff --git a/src/interaction/interactionhandler_lua.inl b/src/interaction/interactionhandler_lua.inl index 21ad7fc862..b810761ecb 100644 --- a/src/interaction/interactionhandler_lua.inl +++ b/src/interaction/interactionhandler_lua.inl @@ -191,6 +191,37 @@ int setInteractionMode(lua_State* L) { return 0; } +int goToChunk(lua_State* L) { + using ghoul::lua::luaTypeToString; + + int nArguments = lua_gettop(L); + if (nArguments != 3) + return luaL_error(L, "Expected %i arguments, got %i", 3, nArguments); + + int x = lua_tonumber(L, 1); + int y = lua_tonumber(L, 2); + int level = lua_tonumber(L, 3); + + OsEng.interactionHandler().goToChunk(x, y, level); + + return 0; +} + +int goToGeo(lua_State* L) { + using ghoul::lua::luaTypeToString; + + int nArguments = lua_gettop(L); + if (nArguments != 2) + return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); + + double latitude = lua_tonumber(L, 1); + double longitude = lua_tonumber(L, 2); + + OsEng.interactionHandler().goToGeo(latitude, longitude); + + return 0; +} + int restoreCameraStateFromFile(lua_State* L) { using ghoul::lua::luaTypeToString; const std::string _loggerCat = "lua.restoreCameraStateFromFile"; diff --git a/src/interaction/interactionmode.cpp b/src/interaction/interactionmode.cpp index 466382579f..70274c1876 100644 --- a/src/interaction/interactionmode.cpp +++ b/src/interaction/interactionmode.cpp @@ -38,6 +38,7 @@ #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED #include #include +#include #endif @@ -685,5 +686,92 @@ void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& came #endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED } +#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED +void GlobeBrowsingInteractionMode::goToChunk(Camera& camera, + globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection) { + using namespace globebrowsing; + + // Camera position in model space + glm::dvec3 camPos = camera.positionVec3(); + glm::dmat4 inverseModelTransform = _globe->inverseModelTransform(); + glm::dvec3 cameraPositionModelSpace = + glm::dvec3(inverseModelTransform * glm::dvec4(camPos, 1)); + + GeodeticPatch patch(ti); + Geodetic2 corner = patch.getCorner(SOUTH_WEST); + Geodetic2 positionOnPatch = patch.getSize(); + positionOnPatch.lat *= uv.y; + positionOnPatch.lon *= uv.x; + Geodetic2 pointPosition = corner + positionOnPatch; + + glm::dvec3 positionOnEllipsoid = + _globe->ellipsoid().geodeticSurfaceProjection(cameraPositionModelSpace); + double altitude = glm::length(cameraPositionModelSpace - positionOnEllipsoid); + + goToGeodetic3(camera, {pointPosition, altitude}); + + if (resetCameraDirection) { + this->resetCameraDirection(camera, pointPosition); + } +} + +void GlobeBrowsingInteractionMode::goToGeodetic2(Camera& camera, + globebrowsing::Geodetic2 geo2, bool resetCameraDirection) { + using namespace globebrowsing; + + // Camera position in model space + glm::dvec3 camPos = camera.positionVec3(); + glm::dmat4 inverseModelTransform = _globe->inverseModelTransform(); + glm::dvec3 cameraPositionModelSpace = + glm::dvec3(inverseModelTransform * glm::dvec4(camPos, 1)); + + glm::dvec3 positionOnEllipsoid = + _globe->ellipsoid().geodeticSurfaceProjection(cameraPositionModelSpace); + double altitude = glm::length(cameraPositionModelSpace - positionOnEllipsoid); + + goToGeodetic3(camera, {geo2, altitude}); + + if (resetCameraDirection) { + this->resetCameraDirection(camera, geo2); + } +} + +void GlobeBrowsingInteractionMode::goToGeodetic3(Camera& camera, globebrowsing::Geodetic3 geo3) { + glm::dvec3 positionModelSpace = _globe->ellipsoid().cartesianPosition(geo3); + glm::dmat4 modelTransform = _globe->modelTransform(); + glm::dvec3 positionWorldSpace = modelTransform * glm::dvec4(positionModelSpace, 1.0); + camera.setPositionVec3(positionWorldSpace); +} + + void GlobeBrowsingInteractionMode::resetCameraDirection(Camera& camera, globebrowsing::Geodetic2 geo2) { + using namespace globebrowsing; + + // Camera is described in world space + glm::dmat4 modelTransform = _globe->modelTransform(); + + // Lookup vector + glm::dvec3 positionModelSpace = _globe->ellipsoid().cartesianSurfacePosition(geo2); + glm::dvec3 slightlyNorth = _globe->ellipsoid().cartesianSurfacePosition( + Geodetic2(geo2.lat + 0.001, geo2.lon)); + glm::dvec3 lookUpModelSpace = glm::normalize(slightlyNorth - positionModelSpace); + glm::dvec3 lookUpWorldSpace = glm::dmat3(modelTransform) * lookUpModelSpace; + + // Lookat vector + glm::dvec3 lookAtWorldSpace = modelTransform * glm::dvec4(positionModelSpace, 1.0); + + // Eye position + glm::dvec3 eye = camera.positionVec3(); + + // Matrix + glm::dmat4 lookAtMatrix = glm::lookAt( + eye, lookAtWorldSpace, lookUpWorldSpace); + + // Set rotation + glm::dquat rotation = glm::quat_cast(inverse(lookAtMatrix)); + camera.setRotation(rotation); + } + +#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED + } // namespace interaction } // namespace openspace From 322c87e499dc1c58c8e87a28d25b6771fce78828 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Tue, 29 Nov 2016 13:32:55 +0100 Subject: [PATCH 7/8] Add ability to limit num parents in chunktile seletion --- .../globebrowsing/tile/tileprovider/tileprovider.cpp | 10 +++++++++- modules/globebrowsing/tile/tileprovider/tileprovider.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp index 241495794a..c2b63b398b 100644 --- a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp @@ -63,7 +63,7 @@ float TileProvider::noDataValueAsFloat() { return std::numeric_limits::min(); } -ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents){ +ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents, int maxParents){ TileUvTransform uvTransform; uvTransform.uvOffset = glm::vec2(0, 0); uvTransform.uvScale = glm::vec2(1, 1); @@ -72,12 +72,17 @@ ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents){ for (int i = 0; i < parents && tileIndex.level > 1; i++) { TileSelector::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){ TileSelector::ascendToParent(tileIndex, uvTransform); + maxParents--; + } + if(maxParents < 0){ + return{ Tile::TileUnavailable, uvTransform }; } // Step 3. Traverse 0 or more parents up the chunkTree until we find a chunk that @@ -85,6 +90,9 @@ ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents){ while (tileIndex.level > 1) { Tile tile = getTile(tileIndex); if (tile.status != Tile::Status::OK) { + if(--maxParents < 0){ + return{ Tile::TileUnavailable, uvTransform }; + } TileSelector::ascendToParent(tileIndex, uvTransform); } else return { tile, uvTransform }; diff --git a/modules/globebrowsing/tile/tileprovider/tileprovider.h b/modules/globebrowsing/tile/tileprovider/tileprovider.h index e85ff5f149..e315f09102 100644 --- a/modules/globebrowsing/tile/tileprovider/tileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/tileprovider.h @@ -100,7 +100,7 @@ namespace globebrowsing { virtual Tile getTile(const TileIndex& tileIndex) = 0; - virtual ChunkTile getChunkTile(TileIndex tileIndex, int parents = 0); + virtual ChunkTile getChunkTile(TileIndex tileIndex, int parents = 0, int maxParents = 1337); virtual ChunkTilePile getChunkTilePile(TileIndex tileIndex, int pileSize); From ddd101e1b6f37485c095fbe65762a44e633a4211 Mon Sep 17 00:00:00 2001 From: kalbl Date: Wed, 30 Nov 2016 01:01:59 +0100 Subject: [PATCH 8/8] Add ability to read local temporal datasets. --- .../tileprovider/temporaltileprovider.cpp | 32 ++++++++++++++++--- .../tile/tileprovider/temporaltileprovider.h | 10 +++++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index 80c1668ad9..a8e4d2a7d3 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -32,6 +32,7 @@ #include #include +#include // abspath #include @@ -108,8 +109,17 @@ namespace globebrowsing { throw ghoul::RuntimeError("Invalid Time Format " + timeIdFormat + " in " + _datasetFile); } + std::string gdalDescription; CPLXMLNode* gdalNode = CPLSearchXMLNode(node, "GDAL_WMS"); - return CPLSerializeXMLTree(gdalNode); + if (gdalNode) { + gdalDescription = CPLSerializeXMLTree(gdalNode); + } + if (!gdalNode) { + CPLXMLNode* gdalNode = CPLSearchXMLNode(node, "FilePath"); + gdalDescription = std::string(gdalNode->psChild->pszValue); + } + + return gdalDescription; } std::string TemporalTileProvider::getXMLValue(CPLXMLNode* root, const std::string& key, const std::string& defaultVal) { @@ -155,7 +165,10 @@ namespace globebrowsing { } void TemporalTileProvider::update() { - _currentTileProvider = getTileProvider(); + auto newCurrent = getTileProvider(); + if (newCurrent) { + _currentTileProvider = newCurrent; + } _currentTileProvider->update(); } @@ -198,7 +211,8 @@ namespace globebrowsing { std::shared_ptr TemporalTileProvider::initTileProvider(TimeKey timekey) { std::string gdalDatasetXml = getGdalDatasetXML(timekey); _initDict.setValue(KeyFilePath, gdalDatasetXml); - return std::make_shared(_initDict); + auto tileProvider = std::make_shared(_initDict); + return tileProvider; } std::string TemporalTileProvider::getGdalDatasetXML(Time t) { @@ -222,9 +236,15 @@ namespace globebrowsing { return t.ISO8601().substr(0, 10); } - std::string YYYY_MM_DDThh_mm_ssZ::stringify(const Time& t) const { + std::string YYYY_MM_DDThhColonmmColonssZ::stringify(const Time& t) const { return t.ISO8601().substr(0, 19) + "Z"; } + + std::string YYYY_MM_DDThh_mm_ssZ::stringify(const Time& t) const { + std::string timeString = t.ISO8601().substr(0, 19) + "Z"; + replace( timeString.begin(), timeString.end(), ':', '_' ); + return timeString; + } ////////////////////////////////////////////////////////////////////////////////////// // Time Id Providers Facotry // @@ -237,7 +257,9 @@ namespace globebrowsing { void TimeIdProviderFactory::init() { _timeIdProviderMap.insert( std::pair >( "YYYY-MM-DD", std::make_unique() )); - _timeIdProviderMap.insert(std::pair > ( "YYYY-MM-DDThh:mm:ssZ", std::make_unique() )); + _timeIdProviderMap.insert(std::pair > ( "YYYY-MM-DDThh:mm:ssZ", std::make_unique() )); + initialized = true; + _timeIdProviderMap.insert(std::pair > ( "YYYY-MM-DDThh_mm_ssZ", std::make_unique() )); initialized = true; } diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h index 34e810e728..a1a7a61ac1 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h @@ -76,6 +76,14 @@ namespace globebrowsing { * Stringifies OpenSpace to the format "YYYY-MM-DDThh:mm:ssZ" * Example: 2016-09-08T23:05:05Z */ + struct YYYY_MM_DDThhColonmmColonssZ : public TimeFormat { + virtual std::string stringify(const Time& t) const; + }; + + /** + * Stringifies OpenSpace to the format "YYYY-MM-DDThh:mm:ssZ" + * Example: 2016-09-08T23:05:05Z + */ struct YYYY_MM_DDThh_mm_ssZ : public TimeFormat { virtual std::string stringify(const Time& t) const; }; @@ -312,4 +320,4 @@ namespace globebrowsing { } // namespace globebrowsing } // namespace openspace -#endif // __TEMPORAL_TILE_PROVIDER_H__ \ No newline at end of file +#endif // __TEMPORAL_TILE_PROVIDER_H__