Merge branch 'feature/globebrowsing' of https://github.com/OpenSpace/OpenSpace into feature/globebrowsing

This commit is contained in:
Alexander Bock
2016-11-30 14:00:46 +01:00
28 changed files with 759 additions and 98 deletions
+31 -8
View File
@@ -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 = {
{
@@ -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);
@@ -31,6 +31,10 @@
#include <openspace/util/mouse.h>
#include <openspace/util/keys.h>
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#include <modules/globebrowsing/tile/tileindex.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#endif
#include <list>
@@ -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
+4
View File
@@ -50,6 +50,8 @@ set(HEADER_FILES
${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
@@ -102,6 +104,8 @@ set(SOURCE_FILES
${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
@@ -149,6 +149,11 @@ namespace globebrowsing {
}
}
Geodetic2 GeodeticPatch::getSize() const {
return _halfSize * 2;
}
Scalar GeodeticPatch::minLat() const {
return _center.lat - _halfSize.lat;
}
@@ -108,6 +108,7 @@ public:
Scalar isNorthern() const;
Geodetic2 getCorner(Quad q) const;
Geodetic2 getSize() const;
Scalar minLat() const;
Scalar maxLat() const;
@@ -38,6 +38,8 @@
#include <modules/globebrowsing/tile/tileprovider/singleimageprovider.h>
#include <modules/globebrowsing/tile/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/texttileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
namespace openspace {
@@ -65,6 +67,10 @@ void GlobeBrowsingModule::internalInitialize() {
fTileProvider->registerClass<globebrowsing::TemporalTileProvider>("Temporal");
fTileProvider->registerClass<globebrowsing::TileIndexTileProvider>("TileIndex");
fTileProvider->registerClass<globebrowsing::SizeReferenceTileProvider>("SizeReference");
// Combining Tile Providers
fTileProvider->registerClass<globebrowsing::TileProviderByLevel>("ByLevel");
fTileProvider->registerClass<globebrowsing::TileProviderByIndex>("ByIndex");
}
} // namespace openspace
@@ -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();
@@ -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());
@@ -73,6 +73,7 @@ public:
properties::BoolProperty resetTileProviders;
properties::BoolProperty toggleEnabledEveryFrame;
properties::BoolProperty collectStats;
properties::BoolProperty onlyModelSpaceRendering;
};
struct GeneralProperties {
@@ -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 {
@@ -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));
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -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;
+21
View File
@@ -25,10 +25,16 @@
#include <modules/globebrowsing/tile/tileindex.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <ghoul/misc/dictionary.h>
#include <sstream>
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<int>(dict.value<double>(KeyLevel));
x = static_cast<int>(dict.value<double>(KeyX));
y = static_cast<int>(dict.value<double>(KeyY));
}
TileIndex TileIndex::child(Quad q) const {
return TileIndex(2 * x + q % 2, 2 * y + q / 2, level + 1);
}
@@ -79,6 +94,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[
+11 -4
View File
@@ -31,6 +31,10 @@
#include <vector>
#include <stdint.h>
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 {
@@ -72,24 +77,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;
@@ -32,6 +32,7 @@
#include <openspace/engine/downloadmanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h> // abspath
#include <openspace/util/time.h>
@@ -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<TileProvider> TemporalTileProvider::initTileProvider(TimeKey timekey) {
std::string gdalDatasetXml = getGdalDatasetXML(timekey);
_initDict.setValue<std::string>(KeyFilePath, gdalDatasetXml);
return std::make_shared<CachingTileProvider>(_initDict);
auto tileProvider = std::make_shared<CachingTileProvider>(_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<std::string, std::unique_ptr<TimeFormat> >( "YYYY-MM-DD", std::make_unique<YYYY_MM_DD>() ));
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat> > ( "YYYY-MM-DDThh:mm:ssZ", std::make_unique<YYYY_MM_DDThh_mm_ssZ>() ));
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat> > ( "YYYY-MM-DDThh:mm:ssZ", std::make_unique<YYYY_MM_DDThhColonmmColonssZ>() ));
initialized = true;
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat> > ( "YYYY-MM-DDThh_mm_ssZ", std::make_unique<YYYY_MM_DDThh_mm_ssZ>() ));
initialized = true;
}
@@ -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__
#endif // __TEMPORAL_TILE_PROVIDER_H__
@@ -27,6 +27,8 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <openspace/util/factorymanager.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/tile/tileselector.h>
#include <ghoul/logging/logmanager.h>
@@ -61,5 +63,65 @@ float TileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
ChunkTile TileProvider::getChunkTile(TileIndex tileIndex, int parents, int maxParents){
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);
}
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
// has a loaded tile ready to use.
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 };
}
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
@@ -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, int maxParents = 1337);
virtual ChunkTilePile getChunkTilePile(TileIndex tileIndex, int pileSize);
/**
* TileProviders must be able to provide a defualt
* <code>Tile</code> which may be used by clients in cases when
@@ -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 <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/tile/tileindex.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <openspace/engine/openspaceengine.h>
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<ghoul::Dictionary>(KeyDefaultProvider);
TileProvider * defaultProvider = TileProvider::createFromDictionary(defaultProviderDict);
_defaultTileProvider = std::shared_ptr<TileProvider>(defaultProvider);
ghoul::Dictionary indexProvidersDict = dictionary.value<ghoul::Dictionary>(KeyProviders);
for (size_t i = 0; i < indexProvidersDict.size(); i++) {
std::string dictKey = std::to_string(i + 1);
ghoul::Dictionary indexProviderDict = indexProvidersDict.value<ghoul::Dictionary>(dictKey);
ghoul::Dictionary tileIndexDict = indexProviderDict.value<ghoul::Dictionary>(KeyTileIndex);
ghoul::Dictionary providerDict = indexProviderDict.value<ghoul::Dictionary>(KeyTileProvider);
TileIndex tileIndex(tileIndexDict);
TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict);
std::shared_ptr<TileProvider> stp = std::shared_ptr<TileProvider>(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
@@ -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 <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/asynctilereader.h>
#include <gdal_priv.h>
#include <openspace/engine/downloadmanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h> // absPath
#include <ghoul/opengl/texture.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/font/fontrenderer.h>
#include <unordered_map>
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<TileHashKey, std::shared_ptr<TileProvider>> _tileProviderMap;
std::shared_ptr<TileProvider> _defaultTileProvider;
};
} // namespace globebrowsing
} // namespace openspace
#endif // __TILE_PROVIDER_BY_INDEX__
@@ -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 <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
#include <modules/globebrowsing/tile/tileindex.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <openspace/engine/openspaceengine.h>
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<ghoul::Dictionary>(KeyProviders);
for (size_t i = 0; i < levelProvidersDict.size(); i++) {
std::string dictKey = std::to_string(i + 1);
ghoul::Dictionary levelProviderDict = levelProvidersDict.value<ghoul::Dictionary>(dictKey);
double floatMaxLevel;
int maxLevel = 0;
if (!levelProviderDict.getValue<double>(KeyMaxLevel, floatMaxLevel)) {
throw std::runtime_error("Must define key '" + KeyMaxLevel + "'");
}
maxLevel = std::round(floatMaxLevel);
ghoul::Dictionary providerDict;
if (!levelProviderDict.getValue<ghoul::Dictionary>(KeyTileProvider, providerDict)) {
throw std::runtime_error("Must define key '" + KeyTileProvider + "'");
}
TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict);
_levelTileProviders.push_back(std::shared_ptr<TileProvider>(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
@@ -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 <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/asynctilereader.h>
#include <gdal_priv.h>
#include <openspace/engine/downloadmanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h> // absPath
#include <ghoul/opengl/texture.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/font/fontrenderer.h>
#include <set>
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<int> _providerIndices;
std::vector<std::shared_ptr<TileProvider>> _levelTileProviders;
};
} // namespace globebrowsing
} // namespace openspace
#endif // __TILE_PROVIDER_BY_LEVEL__
+3 -62
View File
@@ -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<ChunkTile> TileSelector::getTilesSortedByHighestResolution(const LayerGroup& layerGroup, const TileIndex& tileIndex) {
std::vector<ChunkTile> 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);
@@ -132,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;
}
+1 -7
View File
@@ -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<ChunkTile> 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);
};
+34
View File
@@ -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<GlobeBrowsingInteractionMode> gbim =
std::dynamic_pointer_cast<GlobeBrowsingInteractionMode> (_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<GlobeBrowsingInteractionMode> gbim =
std::dynamic_pointer_cast<GlobeBrowsingInteractionMode> (_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"
},
}
};
}
@@ -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";
+88
View File
@@ -38,6 +38,7 @@
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#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