From 23a97e982b1ad25204e3a8f2858cbaca875d7fe3 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 10 Jul 2017 13:48:00 -0400 Subject: [PATCH 1/5] Remove the SIMD project and thus remove the dependency on NASM --- support/cmake/support_macros.cmake | 38 ++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/support/cmake/support_macros.cmake b/support/cmake/support_macros.cmake index cc58e7e47d..84ea5c5877 100644 --- a/support/cmake/support_macros.cmake +++ b/support/cmake/support_macros.cmake @@ -165,27 +165,45 @@ function (add_external_dependencies) set(SGCT_BUILD_CSHARP_PROJECTS OFF CACHE BOOL "" FORCE) set(SGCT_LIGHT_ONLY ON CACHE BOOL "" FORCE) set(SGCT_CUSTOMOUTPUTDIRS OFF CACHE BOOL "" FORCE) + set(JPEG_TURBO_WITH_SIMD OFF CACHE BOOL "" FORCE) add_subdirectory(${OPENSPACE_EXT_DIR}/sgct) target_include_directories(libOpenSpace SYSTEM PUBLIC ${OPENSPACE_EXT_DIR}/sgct/include) target_link_libraries( libOpenSpace - # sgct sgct_light glew glfw png16_static quat tinyxml2static turbojpeg-static vrpn ${GLFW_LIBRARIES} ) set_property(TARGET sgct_light PROPERTY FOLDER "External") - set_property(TARGET glew PROPERTY FOLDER "External/SGCT") - set_property(TARGET glfw PROPERTY FOLDER "External/SGCT") - set_property(TARGET png16_static PROPERTY FOLDER "External/SGCT") - set_property(TARGET quat PROPERTY FOLDER "External/SGCT") - set_property(TARGET simd PROPERTY FOLDER "External/SGCT") - set_property(TARGET tinyxml2static PROPERTY FOLDER "External/SGCT") - set_property(TARGET turbojpeg-static PROPERTY FOLDER "External/SGCT") - set_property(TARGET vrpn PROPERTY FOLDER "External/SGCT") - set_property(TARGET zlibstatic PROPERTY FOLDER "External/SGCT") + if (TARGET glew) + set_property(TARGET glew PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET glfw) + set_property(TARGET glfw PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET png16_static) + set_property(TARGET png16_static PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET quat) + set_property(TARGET quat PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET simd) + set_property(TARGET simd PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET tinyxml2static) + set_property(TARGET tinyxml2static PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET turbojpeg-static) + set_property(TARGET turbojpeg-static PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET vrpn) + set_property(TARGET vrpn PROPERTY FOLDER "External/SGCT") + endif () + if (TARGET zlibstatic) + set_property(TARGET zlibstatic PROPERTY FOLDER "External/SGCT") + endif () if (UNIX AND (NOT APPLE)) target_link_libraries(libOpenSpace Xcursor Xinerama X11) From 2d1661679c7863abd68af40b6b20d65129d42176 Mon Sep 17 00:00:00 2001 From: Matthew Territo Date: Mon, 10 Jul 2017 11:53:15 -0600 Subject: [PATCH 2/5] Replace ${SGCT} token with ${CONFIG} in Launcher and OpenSpaceEngine. --- apps/Launcher/mainwindow.cpp | 2 +- src/engine/openspaceengine.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/Launcher/mainwindow.cpp b/apps/Launcher/mainwindow.cpp index 51fe2e9207..8f16781d49 100644 --- a/apps/Launcher/mainwindow.cpp +++ b/apps/Launcher/mainwindow.cpp @@ -285,7 +285,7 @@ void MainWindow::initialize() { _syncWidget->setSceneFiles(_sceneFiles); // Load all available configuration files - QString configurationDirectory = QString::fromStdString(absPath("${SGCT}")); + QString configurationDirectory = QString::fromStdString(absPath("${CONFIG}")); d = QDir(configurationDirectory); d.setFilter(QDir::Files); list = d.entryInfoList(); diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 8d807b705f..a0e932332c 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -88,7 +88,7 @@ using namespace ghoul::cmdparser; namespace { const char* _loggerCat = "OpenSpaceEngine"; - const char* SgctDefaultConfigFile = "${SGCT}/single.xml"; + const char* SgctDefaultConfigFile = "${CONFIG}/single.xml"; const char* SgctConfigArgumentCommand = "-config"; From 4f903ac03010172531941002c6d2076264edbfd1 Mon Sep 17 00:00:00 2001 From: Kalle Bladin Date: Mon, 10 Jul 2017 20:34:39 +0200 Subject: [PATCH 3/5] Feature/globebrowsing (#334) Layer support for globe browsing: Add layers using the function openspace.globebrowsing.addLayer Delete layers using openspace.globebrowsing.deleteLayer Layer type does not necessarily have to be of tile type. For example solidcolor does not use tiles Blend modes for layers are Normal, Add, Subtract, Multiply, Color Layer adjustments to affect layers. The current only active one is chroma key to cut out a color from the layer. Transfer functions or clipping masks are examples of layer adjustments for the future. Support for adding layer specifications for quickly accessing GIBS layers: openspace.globebrowsing.createGibsGdalXml openspace.globebrowsing.createTemporalGibsGdalXml The arguments for these functions are currently strings. Would it be better to use a lua dictionary? No data values for height layers are correctly regarded (can be seen on Earth. No longer bumps on the poles) Other minor things: Worked a bit on point globe to render globes at large distances. Currently not in use and doesn't have anything to do with the other things. Concurrent job manager takes a thread pool as argument and not a pointer to one. This is because the concurrent job manager needs to have ownership of the thread pool for correct deinitialization. Will cause breaking change for users of concurrent job manager if merged in to master. * Add ability to add layers programatically. * Clean up * Fix order of deletion in concurrent job manager and clean up * Can create by level tile provider with empty dictionary. * Add script to add GIBS datasets. * Start working with layer adjustment * Update mod files * More work on point globe * Add script to create temporal GIBS datasets. * Update temporal tile provider to be able to take gdal descriptions without file path. * Add adjustment property to layers. * Rename adjustment layer * Add adjustment code to all layer groups * Remove caching of gdal datasets due to cluttering of folders * Document layer support * Update Mars mod * Make Mercury great again. * Cleanup and add blend mode Color * Enable setting of layeradjustment and blend mode from mod files. * No more use for grayscale color overlays. Use grayscale layer with color blend mode instead. * Clean up mod files * Clean up * Clean up * No need for grayscale layers. Reading grayscale in to rgb instead for color layers. * Remove unused layer groups * Correctly read to grayscale layers * Update globe mod files * Rename ColorOverlays to Overlays. * Clean up * Clean up * Solve compilation error --- data/scene/lodglobes/earth/earth.mod | 46 +- .../ESRI/ESRI_Imagery_World_2D.wms | 5 - .../map_service_configs/ESRI/TERRAIN.wms | 12 - .../map_service_configs/GIBS/Coastlines.xml | 6 - .../GIBS/GIBS_Aqua_MODIS_true.xml | 5 - ...MODIS_Terra_Brightness_Temp_Band31_Day.xml | 5 - ...S_Terra_CorrectedReflectance_TrueColor.xml | 5 - .../GIBS/MODIS_Water_Mask.xml | 8 +- .../GIBS/Reference_Features.xml | 6 - .../GIBS/Reference_Labels.xml | 6 - .../GIBS/VIIRS_CityLights_2012.xml | 6 - ...RS_SNPP_CorrectedReflectance_TrueColor.xml | 6 - .../other/frmt_wms_virtualearth.xml | 1 - .../lodglobes/jupiter/callisto/callisto.mod | 7 - .../scene/lodglobes/jupiter/europa/europa.mod | 7 - .../lodglobes/jupiter/ganymede/ganymede.mod | 7 - data/scene/lodglobes/jupiter/io/io.mod | 6 - .../lodglobes/jupiter/jupiter/jupiter.mod | 6 - .../mars/map_service_configs/CTX_Mosaic.xml | 8 +- .../map_service_configs/Mola_Elevation.xml | 5 - .../map_service_configs/Utah/CTX_Mosaic.xml | 2 + .../Utah/MolaCTX_Elevation.xml | 5 - data/scene/lodglobes/mars/mars.mod | 114 +-- .../map_service_configs/OnMercuryColor.xml | 1 + data/scene/lodglobes/mercury/mercury.mod | 74 ++ .../moon/map_service_configs/OnMoonColor.xml | 7 +- .../moon/map_service_configs/OnMoonHeight.xml | 5 - data/scene/lodglobes/moon/moon.mod | 27 +- data/scene/lodglobes/neptune/neptune.mod | 7 - data/scene/lodglobes/saturn/saturn.mod | 7 - data/scene/lodglobes/uranus/uranus.mod | 7 - data/scene/lodglobes/venus/venus.mod | 7 - modules/globebrowsing/CMakeLists.txt | 15 +- modules/globebrowsing/cache/lrucache.h | 1 + modules/globebrowsing/cache/lrucache.inl | 5 + .../cache/memoryawaretilecache.cpp | 2 +- .../availabletiledataevaluator.cpp | 2 +- modules/globebrowsing/globebrowsingmodule.cpp | 107 ++- modules/globebrowsing/globebrowsingmodule.h | 11 +- .../globebrowsing/globebrowsingmodule_lua.inl | 141 ++++ .../globebrowsing/globes/chunkedlodglobe.cpp | 28 +- modules/globebrowsing/globes/pointglobe.cpp | 80 +- modules/globebrowsing/globes/pointglobe.h | 4 + .../globebrowsing/globes/renderableglobe.cpp | 17 +- .../globebrowsing/globes/renderableglobe.h | 3 + .../other/concurrentjobmanager.h | 4 +- .../other/concurrentjobmanager.inl | 6 +- .../globebrowsing/other/distanceswitch.cpp | 41 +- modules/globebrowsing/other/distanceswitch.h | 13 +- modules/globebrowsing/other/lruthreadpool.h | 2 + modules/globebrowsing/other/lruthreadpool.inl | 11 +- .../other/prioritizingconcurrentjobmanager.h | 7 +- .../prioritizingconcurrentjobmanager.inl | 12 +- modules/globebrowsing/other/threadpool.cpp | 9 +- modules/globebrowsing/other/threadpool.h | 2 + .../rendering/gpu/gpuheightlayer.cpp | 2 +- .../globebrowsing/rendering/gpu/gpulayer.cpp | 40 +- .../globebrowsing/rendering/gpu/gpulayer.h | 5 + .../rendering/gpu/gpulayeradjustment.cpp | 64 ++ .../rendering/gpu/gpulayeradjustment.h | 56 ++ .../globebrowsing/rendering/layer/layer.cpp | 278 ++++++- modules/globebrowsing/rendering/layer/layer.h | 55 +- .../rendering/layer/layeradjustment.cpp | 134 ++++ .../layer/layeradjustment.h} | 55 +- .../rendering/layer/layergroup.cpp | 63 +- .../rendering/layer/layergroup.h | 8 +- .../rendering/layer/layergroupid.h | 121 ++- .../rendering/layer/layermanager.cpp | 83 +- .../rendering/layer/layermanager.h | 10 +- .../rendering/layer/layerrendersettings.cpp | 32 +- .../rendering/layer/layerrendersettings.h | 6 + .../rendering/layershadermanager.cpp | 49 +- .../rendering/layershadermanager.h | 4 + .../globebrowsing/scripts/layer_support.lua | 130 ++- modules/globebrowsing/shaders/blending.hglsl | 2 +- .../globebrowsing/shaders/pointglobe_fs.glsl | 25 +- .../globebrowsing/shaders/pointglobe_vs.glsl | 29 +- .../shaders/texturetilemapping.hglsl | 295 +++---- modules/globebrowsing/shaders/tile.hglsl | 9 + .../globebrowsing/shaders/tilefragcolor.hglsl | 30 +- .../tile/asynctiledataprovider.cpp | 27 +- .../tile/asynctiledataprovider.h | 5 + .../gdalrawtiledatareader.cpp | 742 ++++++++++-------- .../rawtiledatareader/rawtiledatareader.cpp | 13 +- .../tile/tileprovider/cachingtileprovider.cpp | 191 ----- .../tile/tileprovider/defaulttileprovider.cpp | 255 ++++++ ...ngtileprovider.h => defaulttileprovider.h} | 20 +- .../presentationslideprovider.cpp | 4 + .../tileprovider/projectiontileprovider.cpp | 385 --------- .../tile/tileprovider/singleimageprovider.cpp | 20 +- .../tile/tileprovider/singleimageprovider.h | 5 +- .../sizereferencetileprovider.cpp | 6 +- .../tileprovider/temporaltileprovider.cpp | 174 ++-- .../tile/tileprovider/temporaltileprovider.h | 13 +- .../tileprovider/tileindextileprovider.cpp | 2 +- .../tile/tileprovider/tileprovider.cpp | 7 +- .../tile/tileprovider/tileprovider.h | 4 +- .../tile/tileprovider/tileproviderbyindex.cpp | 33 +- .../tile/tileprovider/tileproviderbylevel.cpp | 63 +- .../tile/tileprovider/tileproviderbylevel.h | 2 + modules/globebrowsing/tile/tileselector.cpp | 8 +- modules/onscreengui/src/renderproperties.cpp | 4 +- tests/test_concurrentjobmanager.inl | 7 +- 103 files changed, 2743 insertions(+), 1781 deletions(-) create mode 100644 data/scene/lodglobes/mercury/mercury.mod create mode 100644 modules/globebrowsing/globebrowsingmodule_lua.inl create mode 100644 modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp create mode 100644 modules/globebrowsing/rendering/gpu/gpulayeradjustment.h create mode 100644 modules/globebrowsing/rendering/layer/layeradjustment.cpp rename modules/globebrowsing/{tile/tileprovider/presentationslideprovider.h => rendering/layer/layeradjustment.h} (64%) delete mode 100644 modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp create mode 100644 modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp rename modules/globebrowsing/tile/tileprovider/{cachingtileprovider.h => defaulttileprovider.h} (86%) delete mode 100644 modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index 37a222bf58..b20133580d 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -70,12 +70,12 @@ return { ColorLayers = { { Name = "ESRI VIIRS Combo", - Type = "ByLevel", + Type = "ByLevelTileLayer", LevelTileProviders = { { MaxLevel = 3, TileProvider = { - Type = "Temporal", + Type = "TemporalTileLayer", Name = "Temporal VIIRS SNPP", FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", }, }, @@ -90,22 +90,37 @@ return { Enabled = true, }, { - Type = "Temporal", - Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature", - FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml", + Name = "BMNG", + FilePath = "map_service_configs/Utah/Bmng.wms" }, { - Type = "Temporal", + Type = "TemporalTileLayer", Name = "Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration", FilePath = "map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml", }, { - Name = "BMNG", - FilePath = "map_service_configs/Utah/Bmng.wms" - } + Type = "TemporalTileLayer", + Name = "MODIS_Terra_Chlorophyll_A", + FilePath = openspace.globebrowsing.createTemporalGibsGdalXml( + "MODIS_Terra_Chlorophyll_A", + "2013-07-02", + "Yesterday", + "1d", + "1km", + "png") + }, + { + Type = "TemporalTileLayer", + Name = "GHRSST_L4_G1SST_Sea_Surface_Temperature", + FilePath = openspace.globebrowsing.createTemporalGibsGdalXml( + "GHRSST_L4_G1SST_Sea_Surface_Temperature", + "2010-06-21", + "Yesterday", + "1d", + "1km", + "png") + }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, NightLayers = { { Name = "Earth at Night 2012", @@ -118,7 +133,7 @@ return { }, }, { - Type = "Temporal", + Type = "TemporalTileLayer", Name = "Temporal Earth at Night", FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml" } @@ -134,7 +149,7 @@ return { FilePath = "map_service_configs/Utah/Gebco.wms", } }, - ColorOverlays = { + Overlays = { { Name = "Coastlines", FilePath = "map_service_configs/GIBS/Coastlines.xml", @@ -148,14 +163,13 @@ return { FilePath = "map_service_configs/GIBS/Reference_Labels.xml", }, { - Type = "TileIndex", + Type = "TileIndexTileLayer", Name = "Tile Indices", }, { - Type = "SizeReference", + Type = "SizeReferenceTileLayer", Name = "Size Reference", Radii = earthEllipsoid, - BackgroundImagePath = "../arrows.png", }, }, HeightLayers = { diff --git a/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms b/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms index d7d7263f5c..7c54ed40f0 100644 --- a/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms +++ b/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms @@ -13,10 +13,5 @@ 512 3 5 - - ./GDAL_Cache/ESRI_Imagery_World_2d - 4 - .jpg - false \ No newline at end of file diff --git a/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms b/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms index 3937681945..a4a50c0a83 100644 --- a/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms +++ b/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms @@ -3,19 +3,7 @@ http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d? GCS_Elevation - - -180.0 - 90.0 - 180.0 - -90.0 - bottom - 2 5 - - ./GDAL_Cache/TERRAIN - 4 - .jpg - false diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml index 830e32da8a..120c022a25 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml @@ -20,10 +20,4 @@ 400 true 5 - - ./GDAL_Cache/Coastlines - 4 - .png - - false diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml index 19bbcdb9c5..1e5ed01815 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml @@ -17,11 +17,6 @@ 512 3 5 - - ./GDAL_Cache/GIBS_Aqua_MODIS_true - 4 - .jpg - false true 400 diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml index 46a1189c43..7311954847 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml @@ -17,11 +17,6 @@ 512 4 5 - - ./GDAL_Cache/MODIS_Terra_Brightness_Temp_Band31_Day - 4 - .png - false true 400 diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml index a0d82a02b0..3d9b24822d 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml @@ -17,11 +17,6 @@ 512 3 5 - - ./GDAL_Cache/MODIS_Terra_CorrectedReflectance_TrueColor - 4 - .jpg - false true 400 diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml index b3b90a2f48..4abfdde13d 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml @@ -17,13 +17,7 @@ 512 4 5 - - ./GDAL_Cache/MODIS_Water_Mask - 4 - .png - - false true - 400 + 400,204,404 true diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml index 7cb0e23db1..b4874f7db2 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml @@ -17,12 +17,6 @@ 512 4 5 - - ./GDAL_Cache/Reference_Features - 4 - .png - - false true 400 true diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml index 2731893a09..5f45a0d424 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml @@ -17,12 +17,6 @@ 512 4 5 - - ./GDAL_Cache/Reference_Labels - 4 - .png - - false true 400 true diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml index 8530c80b81..5589007002 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml @@ -17,12 +17,6 @@ 512 4 5 - - ./GDAL_Cache/VIIRS_CityLights_2012 - 4 - .jpg - - false true 400 true diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml index b6ffc234fa..d0ff0f3985 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml @@ -17,12 +17,6 @@ 512 3 5 - - ./GDAL_Cache/VIIRS_SNPP_CorrectedReflectance_TrueColor - 4 - .jpg - - false true 400 true diff --git a/data/scene/lodglobes/earth/map_service_configs/other/frmt_wms_virtualearth.xml b/data/scene/lodglobes/earth/map_service_configs/other/frmt_wms_virtualearth.xml index 3b628e9a89..42946f0a2f 100644 --- a/data/scene/lodglobes/earth/map_service_configs/other/frmt_wms_virtualearth.xml +++ b/data/scene/lodglobes/earth/map_service_configs/other/frmt_wms_virtualearth.xml @@ -3,5 +3,4 @@ http://a${server_num}.ortho.tiles.virtualearth.net/tiles/a${quadkey}.jpeg?g=90 4 - diff --git a/data/scene/lodglobes/jupiter/callisto/callisto.mod b/data/scene/lodglobes/jupiter/callisto/callisto.mod index c86a629158..53b8cee865 100644 --- a/data/scene/lodglobes/jupiter/callisto/callisto.mod +++ b/data/scene/lodglobes/jupiter/callisto/callisto.mod @@ -32,15 +32,8 @@ return { Name = "Callisto Texture", FilePath = "textures/callisto.jpg", Enabled = true, - TilePixelSize = 112, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, } }, diff --git a/data/scene/lodglobes/jupiter/europa/europa.mod b/data/scene/lodglobes/jupiter/europa/europa.mod index b3f4c1a8df..720e68d7db 100644 --- a/data/scene/lodglobes/jupiter/europa/europa.mod +++ b/data/scene/lodglobes/jupiter/europa/europa.mod @@ -32,15 +32,8 @@ return { Name = "Europa Texture", FilePath = "textures/europa.jpg", Enabled = true, - TilePixelSize = 256, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, } }, diff --git a/data/scene/lodglobes/jupiter/ganymede/ganymede.mod b/data/scene/lodglobes/jupiter/ganymede/ganymede.mod index 0099a57786..098014cc0c 100644 --- a/data/scene/lodglobes/jupiter/ganymede/ganymede.mod +++ b/data/scene/lodglobes/jupiter/ganymede/ganymede.mod @@ -32,15 +32,8 @@ return { Name = "Ganymede Texture", FilePath = "textures/ganymede.jpg", Enabled = true, - TilePixelSize = 112, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, } }, diff --git a/data/scene/lodglobes/jupiter/io/io.mod b/data/scene/lodglobes/jupiter/io/io.mod index 0deb7fae71..dc6b7c2b8e 100644 --- a/data/scene/lodglobes/jupiter/io/io.mod +++ b/data/scene/lodglobes/jupiter/io/io.mod @@ -34,12 +34,6 @@ return { Enabled = true, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, } }, diff --git a/data/scene/lodglobes/jupiter/jupiter/jupiter.mod b/data/scene/lodglobes/jupiter/jupiter/jupiter.mod index d8a50af4a5..2c6610b3ae 100644 --- a/data/scene/lodglobes/jupiter/jupiter/jupiter.mod +++ b/data/scene/lodglobes/jupiter/jupiter/jupiter.mod @@ -45,12 +45,6 @@ return { Enabled = true, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, } }, diff --git a/data/scene/lodglobes/mars/map_service_configs/CTX_Mosaic.xml b/data/scene/lodglobes/mars/map_service_configs/CTX_Mosaic.xml index 51fd81ce11..0491a66bd5 100644 --- a/data/scene/lodglobes/mars/map_service_configs/CTX_Mosaic.xml +++ b/data/scene/lodglobes/mars/map_service_configs/CTX_Mosaic.xml @@ -12,10 +12,6 @@ 256 256 - - ./GDAL_CTX_cache - 3 - .png - - false + 400,204,404 + true \ No newline at end of file diff --git a/data/scene/lodglobes/mars/map_service_configs/Mola_Elevation.xml b/data/scene/lodglobes/mars/map_service_configs/Mola_Elevation.xml index 9c440826b0..c003ebf07d 100644 --- a/data/scene/lodglobes/mars/map_service_configs/Mola_Elevation.xml +++ b/data/scene/lodglobes/mars/map_service_configs/Mola_Elevation.xml @@ -10,10 +10,5 @@ -90.0 bottom - - ./GDAL_MOLA_cache - 3 - .png - false \ No newline at end of file diff --git a/data/scene/lodglobes/mars/map_service_configs/Utah/CTX_Mosaic.xml b/data/scene/lodglobes/mars/map_service_configs/Utah/CTX_Mosaic.xml index 6135ce51b0..164ab0eb2f 100644 --- a/data/scene/lodglobes/mars/map_service_configs/Utah/CTX_Mosaic.xml +++ b/data/scene/lodglobes/mars/map_service_configs/Utah/CTX_Mosaic.xml @@ -17,4 +17,6 @@ 256 2 10 + 400,204,404 + true \ No newline at end of file diff --git a/data/scene/lodglobes/mars/map_service_configs/Utah/MolaCTX_Elevation.xml b/data/scene/lodglobes/mars/map_service_configs/Utah/MolaCTX_Elevation.xml index 96c96f84d7..baa437174c 100644 --- a/data/scene/lodglobes/mars/map_service_configs/Utah/MolaCTX_Elevation.xml +++ b/data/scene/lodglobes/mars/map_service_configs/Utah/MolaCTX_Elevation.xml @@ -10,10 +10,5 @@ -90.0 bottom - - ./GDAL_MOLA_cache - 3 - .png - false \ No newline at end of file diff --git a/data/scene/lodglobes/mars/mars.mod b/data/scene/lodglobes/mars/mars.mod index e25290d1c0..7443aa8f2f 100644 --- a/data/scene/lodglobes/mars/mars.mod +++ b/data/scene/lodglobes/mars/mars.mod @@ -1,4 +1,5 @@ local marsEllipsoid = {3396190.0, 3396190.0, 3376200.0} + return { -- Barycenter module { @@ -34,7 +35,8 @@ return { CameraMinHeight = 10, SegmentsPerPatch = 90, -- Allows camera to go down 10000 meters below the reference ellipsoid - InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values + -- Useful when having negative height map values + InteractionDepthBelowEllipsoid = 10000, Layers = { ColorLayers = { { @@ -42,87 +44,30 @@ return { FilePath = "map_service_configs/MARS_Viking_MDIM21.xml", Enabled = true, }, - -- { - -- Type = "SingleImage", - -- Name = "Debug Tiles", - -- FilePath = "../../debugglobe/textures/test_tile.png", - -- }, - --{ - -- Name = "MARS_Viking", - -- FilePath = "map_service_configs/MARS_Viking_MDIM21.xml", - -- Enabled = true, - --}, { Name = "MOLA Pseudo Color", FilePath = "map_service_configs/Utah/MolaPseudoColor.xml", - -- Enabled = true, - }, - --[[ - { - Name = "Mars Viking Clr", - FilePath = "map_datasets/Viking/Mars_Viking_ClrMosaic_global_925m_longlat_full.vrt", - Enabled = true, - }, - ]] - }, - GrayScaleLayers = { - - }, - GrayScaleColorOverlays = { - { - Name = "CTX Mosaic [AWS]", - FilePath = "map_service_configs/CTX.wms", - Enabled = true, }, { Name = "CTX Mosaic [Europe]", FilePath = "map_service_configs/CTX_Mosaic.xml", - --Enabled = true, + BlendMode = "Color" }, { Name = "CTX Mosaic [Utah]", FilePath = "map_service_configs/Utah/CTX_Mosaic.xml", + BlendMode = "Color" }, - { - Name = "West Candor Chasma", - FilePath = "map_datasets/CTX/West_Candor_Chasma_longlat_global.vrt", - --Enabled = true, - }, - { - Name = "Layered Rock Outcrops in Southwest Candor Chasma", - FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Texture.vrt", - }, - --[[{ - Name = "Themis IR Day", - FilePath = "map_service_configs/Utah/ThemisIRDay.xml", - }, - { - Name = "Themis IR Night", - FilePath = "map_service_configs/Utah/ThemisIRNight.xml", - }, - - { - Name = "MER_Meridianni_Endeavor_Basemap_25cm", - FilePath = "map_datasets/Basemap/MER_Meridianni_Endeavor_Basemap_25cm.vrt", - }, - { - Name = "Part of Area Traversed by the Mars Exploration Rover", - FilePath = "map_datasets/HiRISE/Part_of_Area_Traversed_by_the_Mars_Exploration_Rover_Texture.vrt", - }, - ]] }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { + Overlays = { { - Type = "TileIndex", + Type = "TileIndexTileLayer", Name = "Indices", }, { - Type = "SizeReference", + Type = "SizeReferenceTileLayer", Name = "Size Reference", Radii = marsEllipsoid, - BackgroundImagePath = "../arrows.png", }, }, HeightLayers = { @@ -131,50 +76,7 @@ return { FilePath = "map_service_configs/Mola_Elevation.xml", Enabled = true, TilePixelSize = 90, - DoPreProcessing = true, }, - --[[ - { - Name = "Mola Elevation [Utah]", - FilePath = "map_service_configs/Utah/Mola_Elevation.xml", - Enabled = false, - TilePixelSize = 90, - DoPreProcessing = true, - }, - { - Name = "Mola Elevation CTX", - FilePath = "map_service_configs/Utah/MolaCTX_Elevation.xml", - -- Enabled = true, - TilePixelSize = 90, - DoPreProcessing = true, - },]] - { - Name = "West Candor Chasma", - FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt", - --Enabled = true, - TilePixelSize = 90, - DoPreProcessing = true, - }, - { - Name = "Layered Rock Outcrops in Southwest Candor Chasma", - FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Heightmap.vrt", - TilePixelSize = 90, - DoPreProcessing = true, - }, - --[[ - { - Name = "West Candor Chasma", - FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt", - --Enabled = true, - TilePixelSize = 90, - DoPreProcessing = true, - },]] - --[[ - { - Name = "Part of Area Traversed by the Mars Exploration Rover", - FilePath = "map_datasets/HiRISE/Part_of_Area_Traversed_by_the_Mars_Exploration_Rover_Heightmap.vrt", - }, - ]] }, }, } diff --git a/data/scene/lodglobes/mercury/map_service_configs/OnMercuryColor.xml b/data/scene/lodglobes/mercury/map_service_configs/OnMercuryColor.xml index d53cb3ad5e..4083bfbba8 100644 --- a/data/scene/lodglobes/mercury/map_service_configs/OnMercuryColor.xml +++ b/data/scene/lodglobes/mercury/map_service_configs/OnMercuryColor.xml @@ -25,6 +25,7 @@ 1 top + 5 512 512 \ No newline at end of file diff --git a/data/scene/lodglobes/mercury/mercury.mod b/data/scene/lodglobes/mercury/mercury.mod new file mode 100644 index 0000000000..531b855ba7 --- /dev/null +++ b/data/scene/lodglobes/mercury/mercury.mod @@ -0,0 +1,74 @@ +return { + -- Barycenter module + { + Name = "MercuryBarycenter", + Parent = "SolarSystemBarycenter", + Transform = { + Translation = { + Type = "SpiceTranslation", + Body = "MERCURY", + Observer = "SUN", + Kernels = "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" + }, + }, + }, + -- RenderableGlobe module + { + Name = "Mercury", + Parent = "MercuryBarycenter", + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "IAU_MERCURY", + DestinationFrame = "GALACTIC", + }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, + }, + Renderable = { + Type = "RenderableGlobe", + Radii = {2439700, 2439700.0, 2439700.0}, + Frame = "IAU_MERCURY", + Body = "MERCURY", + + CameraMinHeight = 300, + InteractionDepthBelowEllipsoid = 0, -- Useful when having negative height map values + SegmentsPerPatch = 64, + Layers = { + ColorLayers = { + { + Name = "Simple Texture", + FilePath = "textures/mercury.jpg", + Enabled = true, + }, + { + Name = "Messenger_Mosaic", + FilePath = "map_service_configs/Utah/MessengerMosaic.wms" + }, + { + Name = "Messenger_MDIS", + FilePath = "map_service_configs/Utah/MessengerMDIS.wms" + } + }, + }, + }, + }, + -- Trail module + { + Name = "MercuryTrail", + Parent = "SolarSystemBarycenter", + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "SpiceTranslation", + Body = "MERCURY", + Observer = "SUN", + }, + Color = {0.6, 0.5, 0.5 }, + Period = 87.968, + Resolution = 100 + } + } +} diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml index d2d9d1ec11..458fdab892 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml @@ -61,13 +61,8 @@ top 512 - 512 + 512 true 400 true - - ./GDAL_Cache/OnMoonColor - 4 - .png - \ No newline at end of file diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml index e008c2aa90..3f0934091c 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml @@ -19,9 +19,4 @@ true 400 true - - ./GDAL_Cache/OnMoonHeight - 4 - .png - \ No newline at end of file diff --git a/data/scene/lodglobes/moon/moon.mod b/data/scene/lodglobes/moon/moon.mod index 1247ae7187..40499d6004 100644 --- a/data/scene/lodglobes/moon/moon.mod +++ b/data/scene/lodglobes/moon/moon.mod @@ -25,12 +25,6 @@ return { InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values Layers = { ColorLayers = { - - }, - GrayScaleColorOverlays = { - - }, - GrayScaleLayers = { { Name = "OnMoonColorGrayscale", FilePath = "map_service_configs/OnMoonColor.xml", @@ -48,29 +42,14 @@ return { Name = "WAC", FilePath = "map_service_configs/Utah/Wac.wms" } - }, - NightLayers = { - - }, - WaterMasks = { - - }, - ColorOverlays = { - }, HeightLayers = { - { - Name = "OnMoonHeight", - FilePath = "map_service_configs/OnMoonHeight.xml", - Enabled = true, - DoPreProcessing = true, - TileSize = 64, - }, { Name = "LolaDem", FilePath = "map_service_configs/Utah/LolaDem.wms", - DoPreProcessing = true, - TileSize = 64, + Enabled = true, + TilePixelSize = 64, + Settings = { Multiplier = 0.5 }, } }, }, diff --git a/data/scene/lodglobes/neptune/neptune.mod b/data/scene/lodglobes/neptune/neptune.mod index cfb74029b9..31bac3a1fe 100644 --- a/data/scene/lodglobes/neptune/neptune.mod +++ b/data/scene/lodglobes/neptune/neptune.mod @@ -40,15 +40,8 @@ return { Name = "Texture", FilePath = "textures/neptune.jpg", Enabled = true, - TilePixelSize = 256, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, }, }, diff --git a/data/scene/lodglobes/saturn/saturn.mod b/data/scene/lodglobes/saturn/saturn.mod index da471b0979..cb04b02d13 100644 --- a/data/scene/lodglobes/saturn/saturn.mod +++ b/data/scene/lodglobes/saturn/saturn.mod @@ -40,15 +40,8 @@ return { Name = "Saturn Texture", FilePath = "textures/saturn.jpg", Enabled = true, - TilePixelSize = 256, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, }, }, diff --git a/data/scene/lodglobes/uranus/uranus.mod b/data/scene/lodglobes/uranus/uranus.mod index 06b2160647..81dd7f8eb3 100644 --- a/data/scene/lodglobes/uranus/uranus.mod +++ b/data/scene/lodglobes/uranus/uranus.mod @@ -40,15 +40,8 @@ return { Name = "Texture", FilePath = "textures/uranus.jpg", Enabled = true, - TilePixelSize = 256, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, }, }, diff --git a/data/scene/lodglobes/venus/venus.mod b/data/scene/lodglobes/venus/venus.mod index 2ac91197ed..6288883665 100644 --- a/data/scene/lodglobes/venus/venus.mod +++ b/data/scene/lodglobes/venus/venus.mod @@ -45,15 +45,8 @@ return { Name = "Venus Texture", FilePath = "textures/venus.jpg", Enabled = true, - TilePixelSize = 256, }, }, - GrayScaleLayers = { }, - GrayScaleColorOverlays = { }, - NightLayers = { }, - WaterMasks = { }, - ColorOverlays = { }, - HeightLayers = { }, }, }, }, diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 786d6ec329..57b8c92a56 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -25,6 +25,8 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.h ${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.inl ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.h @@ -79,12 +81,14 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroupid.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.h @@ -102,8 +106,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileuvtransform.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h @@ -123,6 +126,9 @@ set(HEADER_FILES ) set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule_lua.inl + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cache/texturecontainer.cpp @@ -159,12 +165,14 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.cpp @@ -178,8 +186,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilemetadata.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp diff --git a/modules/globebrowsing/cache/lrucache.h b/modules/globebrowsing/cache/lrucache.h index b23cdae9db..8ebf224a9c 100644 --- a/modules/globebrowsing/cache/lrucache.h +++ b/modules/globebrowsing/cache/lrucache.h @@ -70,6 +70,7 @@ public: */ Item popLRU(); size_t size() const; + size_t maximumCacheSize() const; private: void putWithoutCleaning(const KeyType& key, const ValueType& value); diff --git a/modules/globebrowsing/cache/lrucache.inl b/modules/globebrowsing/cache/lrucache.inl index 6141338001..47c0eb4126 100644 --- a/modules/globebrowsing/cache/lrucache.inl +++ b/modules/globebrowsing/cache/lrucache.inl @@ -120,6 +120,11 @@ size_t LRUCache::size() const { return _itemMap.size(); } +template +size_t LRUCache::maximumCacheSize() const { + return _maximumCacheSize; +} + template void LRUCache::putWithoutCleaning(const KeyType& key, const ValueType& value) diff --git a/modules/globebrowsing/cache/memoryawaretilecache.cpp b/modules/globebrowsing/cache/memoryawaretilecache.cpp index e59423515a..98f439f700 100644 --- a/modules/globebrowsing/cache/memoryawaretilecache.cpp +++ b/modules/globebrowsing/cache/memoryawaretilecache.cpp @@ -117,7 +117,7 @@ void MemoryAwareTileCache::clear() { void MemoryAwareTileCache::createDefaultTextureContainers() { for (int id = 0; id < layergroupid::NUM_LAYER_GROUPS; id++) { TileTextureInitData initData = - LayerManager::getTileTextureInitData(layergroupid::ID(id)); + LayerManager::getTileTextureInitData(layergroupid::GroupID(id)); assureTextureContainerExists(initData); } } diff --git a/modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.cpp b/modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.cpp index caaeaac038..8191439767 100644 --- a/modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.cpp +++ b/modules/globebrowsing/chunk/chunklevelevaluator/availabletiledataevaluator.cpp @@ -42,7 +42,7 @@ int AvailableTileData::getDesiredLevel(const Chunk& chunk, const RenderData& dat for (size_t i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) { for (const auto& layer : layerManager->layerGroup(i).activeLayers()) { - Tile::Status status = layer->tileProvider()->getTileStatus(chunk.tileIndex()); + Tile::Status status = layer->getTileStatus(chunk.tileIndex()); if (status == Tile::Status::OK) { return UnknownDesiredLevel; } diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 79621716c0..a4d9b9947c 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,10 +37,11 @@ #include #include #include -#include + +#include +#include #include -#include #include #include @@ -48,6 +49,8 @@ #include +#include "globebrowsingmodule_lua.inl" + namespace openspace { const std::string GlobeBrowsingModule::name = "GlobeBrowsing"; @@ -59,11 +62,10 @@ GlobeBrowsingModule::GlobeBrowsingModule() void GlobeBrowsingModule::internalInitialize() { using namespace globebrowsing; + // Initialize OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Initialize, [&] { - - _tileCache = std::make_unique(); - addPropertySubOwner(*_tileCache); - + _tileCache = std::make_unique(); + addPropertySubOwner(*_tileCache); #ifdef GLOBEBROWSING_USE_GDAL // Convert from MB to Bytes GdalWrapper::create( @@ -73,37 +75,47 @@ void GlobeBrowsingModule::internalInitialize() { #endif // GLOBEBROWSING_USE_GDAL }); + // Render OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Render, [&]{ _tileCache->update(); }); - + // Deinitialize OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Deinitialize, [&]{ #ifdef GLOBEBROWSING_USE_GDAL GdalWrapper::ref().destroy(); #endif // GLOBEBROWSING_USE_GDAL }); + // Get factories auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fRenderable, "Renderable factory was not created"); + // Create factory for TileProviders + auto fTileProvider = + std::make_unique>(); + ghoul_assert(fTileProvider, "TileProvider factory was not created"); + + // Register renderable class fRenderable->registerClass("RenderableGlobe"); - // add Tile Provider factory - auto fTileProvider = std::make_unique>(); - - fTileProvider->registerClass("LRUCaching"); - fTileProvider->registerClass("SingleImage"); + // Register TileProvider classes + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::DefaultTileLayer)]); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::SingleImageTileLayer)]); #ifdef GLOBEBROWSING_USE_GDAL - fTileProvider->registerClass("Temporal"); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::TemporalTileLayer)]); #endif // GLOBEBROWSING_USE_GDAL - - fTileProvider->registerClass("TileIndex"); - fTileProvider->registerClass("SizeReference"); - - // Combining Tile Providers - fTileProvider->registerClass("ByLevel"); - fTileProvider->registerClass("ByIndex"); - fTileProvider->registerClass("PresentationSlides"); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::TileIndexTileLayer)]); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::SizeReferenceTileLayer)]); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::ByLevelTileLayer)]); + fTileProvider->registerClass( + layergroupid::LAYER_TYPE_NAMES[static_cast(layergroupid::TypeID::ByIndexTileLayer)]); + FactoryManager::ref().addFactory(std::move(fTileProvider)); } @@ -112,13 +124,62 @@ globebrowsing::cache::MemoryAwareTileCache* GlobeBrowsingModule::tileCache() { } scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const { + std::string listLayerGroups = layerGroupNamesList(); return { "globebrowsing", - {}, + { + { + "addLayer", + &globebrowsing::luascriptfunctions::addLayer, + "string, string, table", + "Adds a layer to the specified globe. The first argument specifies the " + "name of the scene graph node of which to add the layer. The renderable " + "of the specified scene graph node needs to be a renderable globe. " + "The second argument is the layer group which can be any of " + + listLayerGroups + ". The third argument is the dictionary defining the " + "layer." + }, + { + "deleteLayer", + &globebrowsing::luascriptfunctions::deleteLayer, + "string, string", + "Removes a layer from the specified globe. The first argument specifies " + "the name of the scene graph node of which to remove the layer. " + "The renderable of the specified scene graph node needs to be a " + "renderable globe. The second argument is the layer group which can be " + "any of " + listLayerGroups + ". The third argument is the dictionary" + "defining the layer." + }, + }, { "${MODULE_GLOBEBROWSING}/scripts/layer_support.lua" + }, + { + // Documentation } }; } +std::string GlobeBrowsingModule::layerGroupNamesList() { + std::string listLayerGroups(""); + for (int i = 0; i < globebrowsing::layergroupid::NUM_LAYER_GROUPS - 1; ++i) { + listLayerGroups += + globebrowsing::layergroupid::LAYER_GROUP_NAMES[i] + std::string(", "); + } + listLayerGroups += + std::string(" and ") + globebrowsing::layergroupid::LAYER_GROUP_NAMES[ + globebrowsing::layergroupid::NUM_LAYER_GROUPS - 1]; + return listLayerGroups; +} + +std::string GlobeBrowsingModule::layerTypeNamesList() { + std::string listLayerTypes(""); + for (int i = 0; i < globebrowsing::layergroupid::NUM_LAYER_TYPES - 1; ++i) { + listLayerTypes += globebrowsing::layergroupid::LAYER_TYPE_NAMES[i] + ", "; + } + listLayerTypes += + " and " + globebrowsing::layergroupid::LAYER_TYPE_NAMES[globebrowsing::layergroupid::NUM_LAYER_TYPES - 1]; + return listLayerTypes; +} + } // namespace openspace diff --git a/modules/globebrowsing/globebrowsingmodule.h b/modules/globebrowsing/globebrowsingmodule.h index b07b845cb6..a72a4b0fee 100644 --- a/modules/globebrowsing/globebrowsingmodule.h +++ b/modules/globebrowsing/globebrowsingmodule.h @@ -46,11 +46,20 @@ public: scripting::LuaLibrary luaLibrary() const override; - protected: void internalInitialize() override; private: + /** + \return a comma separated list of layer group names. + */ + static std::string layerGroupNamesList(); + + /** + \return a comma separated list of layer type names. + */ + static std::string layerTypeNamesList(); + std::unique_ptr _tileCache; }; diff --git a/modules/globebrowsing/globebrowsingmodule_lua.inl b/modules/globebrowsing/globebrowsingmodule_lua.inl new file mode 100644 index 0000000000..cd6dbfb9f7 --- /dev/null +++ b/modules/globebrowsing/globebrowsingmodule_lua.inl @@ -0,0 +1,141 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + + +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace openspace { +namespace globebrowsing { +namespace luascriptfunctions { + +/** + Adds a layer to the specified globe. + */ +int addLayer(lua_State* L) { + using ghoul::lua::errorLocation; + + // Argument locations + const int GlobeLocation = -3; + const int LayerGroupLocation = -2; + const int DictionaryLocation = -1; + + int nArguments = lua_gettop(L); + if (nArguments != 3) { + return luaL_error(L, "Expected %i arguments, got %i", 3, nArguments); + } + + // String arguments + const std::string GlobeName = luaL_checkstring(L, GlobeLocation); + const std::string LayerGroupName = luaL_checkstring(L, LayerGroupLocation); + + // Get the node and make sure it exists + SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(GlobeName); + if (!node) { + return luaL_error(L, ("Unknown globe name: " + GlobeName).c_str()); + } + + // Get the renderable globe + RenderableGlobe* globe = dynamic_cast(node->renderable()); + if (!globe) { + return luaL_error(L, ("Renderable is not a globe: " + GlobeName).c_str()); + } + + // Get the layer group + layergroupid::GroupID groupID = layergroupid::getGroupIDFromName(LayerGroupName); + if (groupID == layergroupid::GroupID::Unknown) { + return luaL_error(L, ("Unknown layer group: " + LayerGroupName).c_str()); + } + + // Get the dictionary defining the layer + ghoul::Dictionary d; + try { + ghoul::lua::luaDictionaryFromState(L, d); + } + catch (const ghoul::lua::LuaFormatException& e) { + LERRORC("addLayerFromDictionary", e.what()); + return 0; + } + + globe->layerManager()->addLayer(groupID, d); + + return 0; +} + +/** + Deletes a layer from the specified globe. + */ +int deleteLayer(lua_State* L) { + using ghoul::lua::errorLocation; + + // Argument locations + const int GlobeLocation = -3; + const int LayerGroupLocation = -2; + const int NameLocation = -1; + + int nArguments = lua_gettop(L); + if (nArguments != 3) { + return luaL_error(L, "Expected %i arguments, got %i", 3, nArguments); + } + + // String arguments + const std::string GlobeName = luaL_checkstring(L, GlobeLocation); + const std::string LayerGroupName = luaL_checkstring(L, LayerGroupLocation); + const std::string LayerName = luaL_checkstring(L, NameLocation); + + // Get the node and make sure it exists + SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(GlobeName); + if (!node) { + return luaL_error(L, ("Unknown globe name: " + GlobeName).c_str()); + } + + // Get the renderable globe + RenderableGlobe* globe = dynamic_cast(node->renderable()); + if (!globe) { + return luaL_error(L, ("Renderable is not a globe: " + GlobeName).c_str()); + } + + // Get the layer group + layergroupid::GroupID groupID = layergroupid::getGroupIDFromName(LayerGroupName); + if (groupID == layergroupid::GroupID::Unknown) { + return luaL_error(L, ("Unknown layer group: " + LayerGroupName).c_str()); + } + + globe->layerManager()->deleteLayer(groupID, LayerName); + + return 0; +} + + +} // namespace luascriptfunctions +} // nameapace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/globes/chunkedlodglobe.cpp b/modules/globebrowsing/globes/chunkedlodglobe.cpp index 48fffb6faa..2014f0c20c 100644 --- a/modules/globebrowsing/globes/chunkedlodglobe.cpp +++ b/modules/globebrowsing/globes/chunkedlodglobe.cpp @@ -178,6 +178,9 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { for (const std::shared_ptr& layer : heightMapLayers) { tileprovider::TileProvider* tileProvider = layer->tileProvider(); + if (!tileProvider) { + continue; + } // Transform the uv coordinates to the current tile texture ChunkTile chunkTile = tileProvider->getChunkTile(tileIndex); const Tile& tile = chunkTile.tile; @@ -188,8 +191,9 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { } ghoul::opengl::Texture* tileTexture = tile.texture(); - if (!tileTexture) - return 0; + if (!tileTexture) { + return 0; + } glm::vec2 transformedUv = Tile::TileUvToTextureSamplePosition( uvTransform, @@ -253,12 +257,19 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { float sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y; - // Perform depth transform to get the value in meters - height = depthTransform.depthOffset + depthTransform.depthScale * sample; - // Make sure that the height value follows the layer settings. - // For example if the multiplier is set to a value bigger than one, - // the sampled height should be modified as well. - height = layer->renderSettings().performLayerSettings(height); + // Same as is used in the shader. This is not a perfect solution but + // if the sample is actually a no-data-value (min_float) the interpolated + // value might not be. Therefore we have a cut-off. Assuming no data value + // is smaller than -100000 + if (sample > -100000) + { + // Perform depth transform to get the value in meters + height = depthTransform.depthOffset + depthTransform.depthScale * sample; + // Make sure that the height value follows the layer settings. + // For example if the multiplier is set to a value bigger than one, + // the sampled height should be modified as well. + height = layer->renderSettings().performLayerSettings(height); + } } // Return the result return height; @@ -346,6 +357,7 @@ void ChunkedLodGlobe::debugRenderChunk(const Chunk& chunk, const glm::dmat4& mvp } void ChunkedLodGlobe::update(const UpdateData& data) { + setBoundingSphere(_owner.ellipsoid().maximumRadius() * data.modelTransform.scale); _renderer->update(); } diff --git a/modules/globebrowsing/globes/pointglobe.cpp b/modules/globebrowsing/globes/pointglobe.cpp index 1de34b1fa7..f1cc79a4c3 100644 --- a/modules/globebrowsing/globes/pointglobe.cpp +++ b/modules/globebrowsing/globes/pointglobe.cpp @@ -38,7 +38,20 @@ namespace globebrowsing { PointGlobe::PointGlobe(const RenderableGlobe& owner) : _owner(owner) -{} + , _intensityClamp( + "intensityClamp", + "Intensity clamp", + 1, 0, 1 + ) + , _lightIntensity( + "lightIntensity", + "Light intensity", + 1, 0, 50 + ) +{ + addProperty(_intensityClamp); + addProperty(_lightIntensity); +} PointGlobe::~PointGlobe() { glDeleteBuffers(1, &_vertexBufferID); @@ -56,21 +69,27 @@ bool PointGlobe::initialize() { glBindVertexArray(_vaoID); - // Vertex data is only one point in the origin - glm::vec3 data = glm::vec3(0,0,0); - + std::array quadVertexData = { + glm::vec2(-1.0f, -1.0f), + glm::vec2(1.0f, -1.0f), + glm::vec2(-1.0f, 1.0f), + glm::vec2(-1.0f, 1.0f), + glm::vec2(1.0f, -1.0f), + glm::vec2(1.0f, 1.0f) + }; + // Vertex buffer glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID); glBufferData( GL_ARRAY_BUFFER, - sizeof(glm::vec3), - &data, + sizeof(glm::vec2) * quadVertexData.size(), + quadVertexData.data(), GL_STATIC_DRAW ); // Position at location 0 glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), 0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), 0); glBindVertexArray(0); @@ -91,32 +110,55 @@ void PointGlobe::render(const RenderData& data) { // Calculate variables to be used as uniform variables in shader glm::dvec3 bodyPosition = data.modelTransform.translation; + glm::dmat4 rotationTransform = glm::lookAt( + glm::dvec3(0.0f), + data.camera.positionVec3() - bodyPosition, + glm::normalize(glm::dvec3(1000000.0f) - bodyPosition)); + + glm::dvec3 camToBody = bodyPosition - data.camera.positionVec3(); + float distanceToBody = glm::length(camToBody); + + float avgRadius = _owner.ellipsoid().averageRadius(); + float lightIntensity = _lightIntensity.value() * data.modelTransform.scale * avgRadius / distanceToBody; + float lightIntensityClamped = glm::min(lightIntensity, _intensityClamp.value()); + float lightOverflow = glm::max(lightIntensity - lightIntensityClamped, 0.0f); + + float billboardRadius = lightIntensityClamped * distanceToBody; + glm::dmat4 scaleTransform = glm::scale(glm::dmat4(1.0), glm::dvec3(billboardRadius)); + + setBoundingSphere(billboardRadius); + // Model transform and view transform needs to be in double precision glm::dmat4 modelTransform = glm::translate(glm::dmat4(1.0), bodyPosition) * // Translation - glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); // Scale + glm::inverse(rotationTransform) * + scaleTransform; // Scale glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; glm::vec3 directionToSun = glm::normalize(glm::vec3(0) - glm::vec3(bodyPosition)); glm::vec3 directionToSunViewSpace = glm::mat3(data.camera.combinedViewMatrix()) * directionToSun; - int windowWidth = OsEng.windowWrapper().currentWindowSize().x; - float avgRadius = _owner.ellipsoid().averageRadius(); - - _programObject->setUniform("windowWidth", windowWidth); - _programObject->setUniform("globeRadius", avgRadius); - _programObject->setUniform("directionToSunViewSpace", directionToSunViewSpace); + + _programObject->setUniform("lightIntensityClamped", lightIntensityClamped); + //_programObject->setUniform("lightOverflow", lightOverflow); + //_programObject->setUniform("directionToSunViewSpace", directionToSunViewSpace); _programObject->setUniform("modelViewTransform", glm::mat4(modelViewTransform)); _programObject->setUniform("projectionTransform", data.camera.sgctInternal.projectionMatrix()); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); - + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glBindVertexArray(_vaoID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vertexBufferID); - glDrawArrays(GL_POINTS, 0, 1); + glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); - glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + _programObject->deactivate(); } diff --git a/modules/globebrowsing/globes/pointglobe.h b/modules/globebrowsing/globes/pointglobe.h index 9750444785..34c28ab6fb 100644 --- a/modules/globebrowsing/globes/pointglobe.h +++ b/modules/globebrowsing/globes/pointglobe.h @@ -26,6 +26,7 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___POINTGLOBE___H__ #include +#include #include @@ -55,6 +56,9 @@ private: GLuint _vertexBufferID; GLuint _vaoID; + + properties::FloatProperty _intensityClamp; + properties::FloatProperty _lightIntensity; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/globes/renderableglobe.cpp b/modules/globebrowsing/globes/renderableglobe.cpp index 72a80d9d3b..f8976b8f58 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -26,6 +26,7 @@ #include #include +#include #include namespace { @@ -78,7 +79,7 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) glm::dvec3 radii; dictionary.getValue(keyRadii, radii); _ellipsoid = Ellipsoid(radii); - setBoundingSphere(_ellipsoid.averageRadius()); + setBoundingSphere(_ellipsoid.maximumRadius()); // Ghoul can't read ints from lua dictionaries... double patchSegmentsd; @@ -105,13 +106,10 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) _chunkedLodGlobe = std::make_shared( *this, patchSegments, _layerManager); + //_pointGlobe = std::make_shared(*this); - // This distance will be enough to render the globe as one pixel if the field of - // view is 'fov' radians and the screen resolution is 'res' pixels. - double fov = 2 * glm::pi() / 6; // 60 degrees - int res = 2880; - double distance = res * _ellipsoid.maximumRadius() / tan(fov / 2); - _distanceSwitch.addSwitchValue(_chunkedLodGlobe, distance); + _distanceSwitch.addSwitchValue(_chunkedLodGlobe); + //_distanceSwitch.addSwitchValue(_pointGlobe); addProperty(_generalProperties.isEnabled); addProperty(_generalProperties.atmosphereEnabled); @@ -149,6 +147,7 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) addPropertySubOwner(_debugPropertyOwner); addPropertySubOwner(_layerManager.get()); + //addPropertySubOwner(_pointGlobe.get()); } bool RenderableGlobe::initialize() { @@ -229,6 +228,10 @@ std::shared_ptr RenderableGlobe::chunkedLodGlobe() const{ return _chunkedLodGlobe; } +LayerManager* RenderableGlobe::layerManager() const { + return _layerManager.get(); +} + const Ellipsoid& RenderableGlobe::ellipsoid() const{ return _ellipsoid; } diff --git a/modules/globebrowsing/globes/renderableglobe.h b/modules/globebrowsing/globes/renderableglobe.h index b90e01eec2..ee92df2197 100644 --- a/modules/globebrowsing/globes/renderableglobe.h +++ b/modules/globebrowsing/globes/renderableglobe.h @@ -37,6 +37,7 @@ namespace openspace { namespace globebrowsing { class ChunkedLodGlobe; +class PointGlobe; class LayerManager; /** @@ -93,6 +94,7 @@ public: // Getters std::shared_ptr chunkedLodGlobe() const; + LayerManager* layerManager() const; const Ellipsoid& ellipsoid() const; const glm::dmat4& modelTransform() const; const glm::dmat4& inverseModelTransform() const; @@ -107,6 +109,7 @@ private: // Globes. These are renderables inserted in a distance switch so that the heavier // ChunkedLodGlobe does not have to be rendered at far distances. std::shared_ptr _chunkedLodGlobe; + //std::shared_ptr _pointGlobe; Ellipsoid _ellipsoid; std::shared_ptr _layerManager; diff --git a/modules/globebrowsing/other/concurrentjobmanager.h b/modules/globebrowsing/other/concurrentjobmanager.h index 910a02ef1f..fad0a62704 100644 --- a/modules/globebrowsing/other/concurrentjobmanager.h +++ b/modules/globebrowsing/other/concurrentjobmanager.h @@ -51,7 +51,7 @@ struct Job { template class ConcurrentJobManager { public: - ConcurrentJobManager(std::shared_ptr pool); + ConcurrentJobManager(ThreadPool pool); void enqueueJob(std::shared_ptr> job); @@ -63,8 +63,8 @@ public: private: ConcurrentQueue>> _finishedJobs; - std::shared_ptr threadPool; std::mutex _finishedJobsMutex; + ThreadPool threadPool; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/concurrentjobmanager.inl b/modules/globebrowsing/other/concurrentjobmanager.inl index a522216f5b..763f46b848 100644 --- a/modules/globebrowsing/other/concurrentjobmanager.inl +++ b/modules/globebrowsing/other/concurrentjobmanager.inl @@ -34,13 +34,13 @@ template Job

::~Job() {} template -ConcurrentJobManager

::ConcurrentJobManager(std::shared_ptr pool) +ConcurrentJobManager

::ConcurrentJobManager(ThreadPool pool) : threadPool(pool) { } template void ConcurrentJobManager

::enqueueJob(std::shared_ptr> job) { - threadPool->enqueue([this, job]() { + threadPool.enqueue([this, job]() { job->execute(); std::lock_guard lock(_finishedJobsMutex); _finishedJobs.push(job); @@ -49,7 +49,7 @@ void ConcurrentJobManager

::enqueueJob(std::shared_ptr> job) { template void ConcurrentJobManager

::clearEnqueuedJobs() { - threadPool->clearTasks(); + threadPool.clearTasks(); } template diff --git a/modules/globebrowsing/other/distanceswitch.cpp b/modules/globebrowsing/other/distanceswitch.cpp index 1b6ff8349f..aeb95de079 100644 --- a/modules/globebrowsing/other/distanceswitch.cpp +++ b/modules/globebrowsing/other/distanceswitch.cpp @@ -32,7 +32,6 @@ namespace globebrowsing { DistanceSwitch::~DistanceSwitch() {} bool DistanceSwitch::initialize() { - _objectScale = 1.0; for (unsigned int i = 0; i < _renderables.size(); ++i) { _renderables[i]->initialize(); } @@ -46,44 +45,32 @@ bool DistanceSwitch::deinitialize() { return true; } - void DistanceSwitch::render(const RenderData& data) { - if (_maxDistances.size() == 0) { - return; - } - - double distanceToCamera = distance(data.camera.positionVec3(), data.modelTransform.translation); - - if (distanceToCamera > _maxDistances.back() * _objectScale) { - return; - } + const double distanceToCamera = + distance(data.camera.positionVec3(), data.modelTransform.translation); + // This distance will be enough to render the globe as one pixel if the field of + // view is 'fov' radians and the screen resolution is 'res' pixels. + const double fov = 2 * glm::pi() / 6; // 60 degrees + int res = 2880; + // linear search through nodes to find which Renderable to render - for (unsigned int i = 0; i < _renderables.size(); ++i) { - if (distanceToCamera < _maxDistances[i] * _objectScale) { - _renderables[i]->render(data); - return; + for (std::shared_ptr renderable : _renderables) { + const double distance = res * renderable->boundingSphere() / tan(fov / 2); + if (distanceToCamera < distance) { + renderable->render(data); } } } void DistanceSwitch::update(const UpdateData& data) { - _objectScale = data.modelTransform.scale; - for (unsigned int i = 0; i < _renderables.size(); ++i) { - _renderables[i]->update(data); + for (std::shared_ptr renderable : _renderables) { + renderable->update(data); } } -void DistanceSwitch::addSwitchValue(std::shared_ptr renderable, - double maxDistance) -{ - ghoul_assert(maxDistance > 0, "Renderable must have a positive maxDistance"); - if (_maxDistances.size() > 0) { - ghoul_assert(maxDistance > _maxDistances.back(), - "Renderables must be inserted in ascending order wrt distance"); - } +void DistanceSwitch::addSwitchValue(std::shared_ptr renderable) { _renderables.push_back(renderable); - _maxDistances.push_back(maxDistance); } } // namespace globebrowsing diff --git a/modules/globebrowsing/other/distanceswitch.h b/modules/globebrowsing/other/distanceswitch.h index 9f26e35f43..2ba77a9d90 100644 --- a/modules/globebrowsing/other/distanceswitch.h +++ b/modules/globebrowsing/other/distanceswitch.h @@ -39,7 +39,7 @@ namespace globebrowsing { /** * Selects a specific Renderable to be used for rendering, based on distance to the * camera -*/ + */ class DistanceSwitch { public: ~DistanceSwitch(); @@ -50,20 +50,17 @@ public: /** * Picks the first Renderable with the associated maxDistance greater than the * current distance to the camera - */ + */ void render(const RenderData& data); void update(const UpdateData& data); /** - * Adds a new renderable (first argument) which may be rendered only if the distance - * to the camera is less than maxDistance (second argument) - */ - void addSwitchValue(std::shared_ptr renderable, double maxDistance); + * Adds a new renderable + */ + void addSwitchValue(std::shared_ptr renderable); private: std::vector> _renderables; - std::vector _maxDistances; - double _objectScale; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/lruthreadpool.h b/modules/globebrowsing/other/lruthreadpool.h index 35a370a179..1b89e04ce1 100644 --- a/modules/globebrowsing/other/lruthreadpool.h +++ b/modules/globebrowsing/other/lruthreadpool.h @@ -33,6 +33,7 @@ #include #include #include +#include // Implementatin based on http://progsch.net/wordpress/?p=81 @@ -65,6 +66,7 @@ template class LRUThreadPool { public: LRUThreadPool(size_t numThreads, size_t queueSize); + LRUThreadPool(const LRUThreadPool& toCopy); ~LRUThreadPool(); void enqueue(std::function f, KeyType key); diff --git a/modules/globebrowsing/other/lruthreadpool.inl b/modules/globebrowsing/other/lruthreadpool.inl index 329767e3bc..bcc57029b5 100644 --- a/modules/globebrowsing/other/lruthreadpool.inl +++ b/modules/globebrowsing/other/lruthreadpool.inl @@ -68,11 +68,18 @@ LRUThreadPool::LRUThreadPool(size_t numThreads, size_t queueSize) } } +template +LRUThreadPool::LRUThreadPool(const LRUThreadPool& toCopy) + : LRUThreadPool(toCopy._workers.size(), toCopy._queuedTasks.maximumCacheSize()) +{ } + // the destructor joins all threads template LRUThreadPool::~LRUThreadPool() { - // Stop all threads - _stop = true; + { + std::unique_lock lock(_queueMutex); + _stop = true; + } _condition.notify_all(); // join them diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h index f2314b07f5..6b166dd1a2 100644 --- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h +++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h @@ -43,7 +43,7 @@ namespace globebrowsing { template class PrioritizingConcurrentJobManager { public: - PrioritizingConcurrentJobManager(std::shared_ptr> pool); + PrioritizingConcurrentJobManager(LRUThreadPool pool); /** * Enqueues a job which is identified using a given key @@ -85,9 +85,10 @@ public: private: ConcurrentQueue>> _finishedJobs; - /// An LRU thread pool is used since the jobs can be bumped and hence prioritized. - std::shared_ptr> _threadPool; std::mutex _finishedJobsMutex; + /// An LRU thread pool is used since the jobs can be bumped and hence prioritized. + LRUThreadPool _threadPool; + }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl index ebe0147947..dbfbcbefdf 100644 --- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl +++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl @@ -29,7 +29,7 @@ namespace globebrowsing { template PrioritizingConcurrentJobManager::PrioritizingConcurrentJobManager( - std::shared_ptr> pool) + LRUThreadPool pool) : _threadPool(pool) { } @@ -37,7 +37,7 @@ template void PrioritizingConcurrentJobManager::enqueueJob(std::shared_ptr> job, KeyType key) { - _threadPool->enqueue([this, job]() { + _threadPool.enqueue([this, job]() { job->execute(); std::lock_guard lock(_finishedJobsMutex); _finishedJobs.push(job); @@ -47,23 +47,23 @@ void PrioritizingConcurrentJobManager::enqueueJob(std::shared_ptr std::vector PrioritizingConcurrentJobManager::getKeysToUnfinishedJobs() { - return _threadPool->getUnqueuedTasksKeys(); + return _threadPool.getUnqueuedTasksKeys(); } template std::vector PrioritizingConcurrentJobManager::getKeysToEnqueuedJobs() { - return _threadPool->getQueuedTasksKeys(); + return _threadPool.getQueuedTasksKeys(); } template bool PrioritizingConcurrentJobManager::touch(KeyType key) { - return _threadPool->touch(key); + return _threadPool.touch(key); } template void PrioritizingConcurrentJobManager::clearEnqueuedJobs() { - _threadPool->clearEnqueuedTasks(); + _threadPool.clearEnqueuedTasks(); } template diff --git a/modules/globebrowsing/other/threadpool.cpp b/modules/globebrowsing/other/threadpool.cpp index 10de678202..a5a6fb718a 100644 --- a/modules/globebrowsing/other/threadpool.cpp +++ b/modules/globebrowsing/other/threadpool.cpp @@ -67,10 +67,17 @@ ThreadPool::ThreadPool(size_t numThreads) } } +ThreadPool::ThreadPool(const ThreadPool& toCopy) + : ThreadPool(toCopy.workers.size()) +{ } + // the destructor joins all threads ThreadPool::~ThreadPool() { // stop all threads - stop = true; + { + std::unique_lock lock(queue_mutex); + stop = true; + } condition.notify_all(); // join them diff --git a/modules/globebrowsing/other/threadpool.h b/modules/globebrowsing/other/threadpool.h index 97bf25190b..475714086f 100644 --- a/modules/globebrowsing/other/threadpool.h +++ b/modules/globebrowsing/other/threadpool.h @@ -31,6 +31,7 @@ #include #include #include +#include // Implementatin based on http://progsch.net/wordpress/?p=81 @@ -50,6 +51,7 @@ private: class ThreadPool { public: ThreadPool(size_t numThreads); + ThreadPool(const ThreadPool& toCopy); ~ThreadPool(); void enqueue(std::function f); diff --git a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp index 5b77c34f9b..ce2fa871ef 100644 --- a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp +++ b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp @@ -38,7 +38,7 @@ void GPUHeightLayer::setValue(ghoul::opengl::ProgramObject* programObject, int pileSize) { GPULayer::setValue(programObject, layer, tileIndex, pileSize); - _gpuDepthTransform.setValue(programObject, layer.tileProvider()->depthTransform()); + _gpuDepthTransform.setValue(programObject, layer.depthTransform()); } void GPUHeightLayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.cpp b/modules/globebrowsing/rendering/gpu/gpulayer.cpp index e02dd15a45..edfeb457ef 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayer.cpp +++ b/modules/globebrowsing/rendering/gpu/gpulayer.cpp @@ -33,15 +33,51 @@ void GPULayer::setValue(ghoul::opengl::ProgramObject* programObject, const Layer const TileIndex& tileIndex, int pileSize) { ChunkTilePile chunkTilePile = layer.getChunkTilePile(tileIndex, pileSize); - gpuChunkTilePile.setValue(programObject, chunkTilePile); gpuRenderSettings.setValue(programObject, layer.renderSettings()); + gpuLayerAdjustment.setValue(programObject, layer.layerAdjustment()); + + switch (layer.type()) { + // Intentional fall through. Same for all tile layers + case layergroupid::TypeID::DefaultTileLayer: + case layergroupid::TypeID::SingleImageTileLayer: + case layergroupid::TypeID::SizeReferenceTileLayer: + case layergroupid::TypeID::TemporalTileLayer: + case layergroupid::TypeID::TileIndexTileLayer: + case layergroupid::TypeID::ByIndexTileLayer: + case layergroupid::TypeID::ByLevelTileLayer: + gpuChunkTilePile.setValue(programObject, chunkTilePile); + break; + case layergroupid::TypeID::SolidColor: + gpuColor.setValue(programObject, layer.otherTypesProperties().color.value()); + break; + default: + break; + } } void GPULayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, const std::string& nameBase, int pileSize) { - gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize); gpuRenderSettings.bind(layer.renderSettings(), programObject, nameBase + "settings."); + gpuLayerAdjustment.bind(layer.layerAdjustment(), programObject, nameBase + "adjustment."); + + switch (layer.type()) { + // Intentional fall through. Same for all tile layers + case layergroupid::TypeID::DefaultTileLayer: + case layergroupid::TypeID::SingleImageTileLayer: + case layergroupid::TypeID::SizeReferenceTileLayer: + case layergroupid::TypeID::TemporalTileLayer: + case layergroupid::TypeID::TileIndexTileLayer: + case layergroupid::TypeID::ByIndexTileLayer: + case layergroupid::TypeID::ByLevelTileLayer: + gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize); + break; + case layergroupid::TypeID::SolidColor: + gpuColor.bind(programObject, nameBase + "color"); + break; + default: + break; + } } void GPULayer::deactivate() { diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.h b/modules/globebrowsing/rendering/gpu/gpulayer.h index 3cc2e881c9..746c581b25 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayer.h +++ b/modules/globebrowsing/rendering/gpu/gpulayer.h @@ -26,6 +26,7 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__ #include +#include #include #include #include @@ -73,6 +74,10 @@ public: private: GPUChunkTilePile gpuChunkTilePile; GPULayerRenderSettings gpuRenderSettings; + GPULayerAdjustment gpuLayerAdjustment; + + // Adjustment layer stuff + GPUData gpuColor; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp new file mode 100644 index 0000000000..69ff1707bb --- /dev/null +++ b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp @@ -0,0 +1,64 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +namespace openspace { +namespace globebrowsing { + +void GPULayerAdjustment::setValue(ghoul::opengl::ProgramObject* programObject, + const LayerAdjustment& layerAdjustment) +{ + switch (layerAdjustment.type()) { + case layergroupid::AdjustmentTypeID::None: + break; + case layergroupid::AdjustmentTypeID::ChromaKey: { + gpuChromaKeyColor.setValue(programObject, layerAdjustment.chromaKeyColor.value()); + gpuChromaKeyTolerance.setValue(programObject, layerAdjustment.chromaKeyTolerance.value()); + break; + } + case layergroupid::AdjustmentTypeID::TransferFunction: + break; + } +} + +void GPULayerAdjustment::bind(const LayerAdjustment& layerAdjustment, ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase) +{ + switch (layerAdjustment.type()) { + case layergroupid::AdjustmentTypeID::None: + break; + case layergroupid::AdjustmentTypeID::ChromaKey: { + gpuChromaKeyColor.bind(programObject, nameBase + "chromaKeyColor"); + gpuChromaKeyTolerance.bind(programObject, nameBase + "chromaKeyTolerance"); + break; + } + case layergroupid::AdjustmentTypeID::TransferFunction: + break; + } +} + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h new file mode 100644 index 0000000000..3a53b8808f --- /dev/null +++ b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__ + +#include + +namespace ghoul { namespace opengl { +class ProgramObject; +}} + +namespace openspace { +namespace globebrowsing { + +struct LayerAdjustment; + +class GPULayerAdjustment{ +public: + void setValue(ghoul::opengl::ProgramObject* programObject, + const LayerAdjustment& layerAdjustment); + + void bind(const LayerAdjustment& layerAdjustment, + ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase); + +private: + GPUData gpuChromaKeyColor; + GPUData gpuChromaKeyTolerance; +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__ diff --git a/modules/globebrowsing/rendering/layer/layer.cpp b/modules/globebrowsing/rendering/layer/layer.cpp index 5f50476aab..d4f482ba8c 100644 --- a/modules/globebrowsing/rendering/layer/layer.cpp +++ b/modules/globebrowsing/rendering/layer/layer.cpp @@ -30,60 +30,296 @@ namespace openspace { namespace globebrowsing { namespace { + const char* _loggerCat = "Layer"; + const char* keyName = "Name"; const char* keyEnabled = "Enabled"; const char* keyLayerGroupID = "LayerGroupID"; const char* keySettings = "Settings"; + const char* keyAdjustment = "Adjustment"; + const char* KeyBlendMode = "BlendMode"; } -Layer::Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict) +Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict) : properties::PropertyOwner(layerDict.value(keyName)) + , _typeOption( + "type", + "Type", + properties::OptionProperty::DisplayType::Dropdown + ) + , _blendModeOption( + "blendMode", + "Blend Mode", + properties::OptionProperty::DisplayType::Dropdown + ) , _enabled(properties::BoolProperty("enabled", "Enabled", false)) , _reset("reset", "Reset") -{ - // We add the id to the dictionary since it needs to be known by - // the tile provider - ghoul::Dictionary newLayerDict = layerDict; - newLayerDict.setValue(keyLayerGroupID, id); - - _tileProvider = std::shared_ptr( - tileprovider::TileProvider::createFromDictionary(newLayerDict)); - - // Something else went wrong and no exception was thrown - if (_tileProvider == nullptr) { - throw ghoul::RuntimeError("Unable to create TileProvider '" + name() + "'"); + , _tileProvider(nullptr) + , _otherTypesProperties{ + properties::Vec3Property ( + "color", + "Color", + glm::vec4(1.f, 1.f, 1.f, 1.f), + glm::vec4(0.f), + glm::vec4(1.f)) } + , _layerGroupId(id) +{ + layergroupid::TypeID typeID = parseTypeIdFromDictionary(layerDict); + if (typeID == layergroupid::TypeID::Unknown) { + throw ghoul::RuntimeError("Unknown layer type!"); + } + + initializeBasedOnType(typeID, layerDict); bool enabled = false; // defaults to false if unspecified layerDict.getValue(keyEnabled, enabled); _enabled.setValue(enabled); + // Initialize settings ghoul::Dictionary settingsDict; if (layerDict.getValue(keySettings, settingsDict)) { _renderSettings.setValuesFromDictionary(settingsDict); } - if (id == layergroupid::ID::GrayScaleColorOverlays) { - _renderSettings.addProperty(_renderSettings.valueBlending); - _renderSettings.useValueBlending = true; + + // Initiallize layer adjustment + ghoul::Dictionary adjustmentDict; + if (layerDict.getValue(keyAdjustment, adjustmentDict)) { + _layerAdjustment.setValuesFromDictionary(adjustmentDict); } - _reset.onChange([&](){ - _tileProvider->reset(); + // Add options to option properties + for (int i = 0; i < layergroupid::NUM_LAYER_TYPES; ++i) { + _typeOption.addOption(i, layergroupid::LAYER_TYPE_NAMES[i]); + } + _typeOption.setValue(static_cast(typeID)); + _type = static_cast(_typeOption.value()); + + for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) { + _blendModeOption.addOption(i, layergroupid::BLEND_MODE_NAMES[i]); + } + + // Initialize blend mode + std::string blendModeName; + if (layerDict.getValue(KeyBlendMode, blendModeName)) { + layergroupid::BlendModeID blendModeID = + layergroupid::getBlendModeIDFromName(blendModeName); + _blendModeOption.setValue(static_cast(blendModeID)); + } + else { + _blendModeOption.setValue(static_cast(layergroupid::BlendModeID::Normal)); + } + + // On change callbacks definitions + _enabled.onChange([&](){ + if (_onChangeCallback) { + _onChangeCallback(); + } }); + _reset.onChange([&](){ + if (_tileProvider) { + _tileProvider->reset(); + } + }); + + _typeOption.onChange([&](){ + removeVisibleProperties(); + _type = static_cast(_typeOption.value()); + ghoul::Dictionary dict; + initializeBasedOnType(type(), dict); + addVisibleProperties(); + if (_onChangeCallback) { + _onChangeCallback(); + } + }); + + _blendModeOption.onChange([&](){ + if (_onChangeCallback) { + _onChangeCallback(); + } + }); + + _layerAdjustment.onChange([&](){ + if (_onChangeCallback) { + _onChangeCallback(); + } + }); + + _typeOption.setReadOnly(true); + + // Add the properties + addProperty(_typeOption); + addProperty(_blendModeOption); addProperty(_enabled); addProperty(_reset); + _otherTypesProperties.color.setViewOption(properties::Property::ViewOptions::Color); + + addVisibleProperties(); + addPropertySubOwner(_renderSettings); - addPropertySubOwner(*_tileProvider); + addPropertySubOwner(_layerAdjustment); } ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const { - return _tileProvider->getChunkTilePile(tileIndex, pileSize); + if (_tileProvider) { + return _tileProvider->getChunkTilePile(tileIndex, pileSize); + } + else { + ChunkTilePile chunkTilePile; + chunkTilePile.resize(pileSize); + for (int i = 0; i < pileSize; ++i) { + chunkTilePile[i].tile = Tile::TileUnavailable; + chunkTilePile[i].uvTransform.uvOffset = { 0, 0 }; + chunkTilePile[i].uvTransform.uvScale = { 1, 1 }; + } + return chunkTilePile; + } +} + +Tile::Status Layer::getTileStatus(const TileIndex& index) const { + if (_tileProvider) { + return _tileProvider->getTileStatus(index); + } + else { + return Tile::Status::Unavailable; + } +} + +layergroupid::TypeID Layer::type() const { + return _type; +}; + +layergroupid::BlendModeID Layer::blendMode() const { + return static_cast(_blendModeOption.value()); +}; + + +TileDepthTransform Layer::depthTransform() const { + if (_tileProvider) { + return _tileProvider->depthTransform(); + } + else { + return {1.0f, 0.0f}; + } +} + +bool Layer::enabled() const { + return _enabled.value(); +} + +tileprovider::TileProvider* Layer::tileProvider() const { + return _tileProvider.get(); +} + +const Layer::OtherTypesProperties& Layer::otherTypesProperties() const { + return _otherTypesProperties; +} + +const LayerRenderSettings& Layer::renderSettings() const { + return _renderSettings; +} + +const LayerAdjustment& Layer::layerAdjustment() const { + return _layerAdjustment; } void Layer::onChange(std::function callback) { - _enabled.onChange(callback); + _onChangeCallback = callback; +} + +void Layer::update() { + if (_tileProvider) { + _tileProvider->update(); + } +} + +layergroupid::TypeID Layer::parseTypeIdFromDictionary( + const ghoul::Dictionary& initDict) const +{ + if (initDict.hasKeyAndValue("Type")) { + const std::string typeString = initDict.value("Type"); + return layergroupid::getTypeIDFromTypeString(typeString); + } + else { + return layergroupid::TypeID::DefaultTileLayer; + } +} + +void Layer::initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict) { + switch (typeId) { + // Intentional fall through. Same for all tile layers + case layergroupid::TypeID::DefaultTileLayer: + case layergroupid::TypeID::SingleImageTileLayer: + case layergroupid::TypeID::SizeReferenceTileLayer: + case layergroupid::TypeID::TemporalTileLayer: + case layergroupid::TypeID::TileIndexTileLayer: + case layergroupid::TypeID::ByIndexTileLayer: + case layergroupid::TypeID::ByLevelTileLayer: { + // We add the id to the dictionary since it needs to be known by + // the tile provider + ghoul::Dictionary tileProviderInitDict = initDict; + tileProviderInitDict.setValue(keyLayerGroupID, _layerGroupId); + if (tileProviderInitDict.hasKeyAndValue(keyName)) { + std::string name; + tileProviderInitDict.getValue(keyName, name); + LDEBUG("Initializing tile provider for layer: '" + name + "'"); + } + _tileProvider = std::shared_ptr( + tileprovider::TileProvider::createFromDictionary(typeId, tileProviderInitDict) + ); + break; + } + case layergroupid::TypeID::SolidColor: + break; + default: + throw ghoul::RuntimeError("Unable to create layer. Unknown type."); + break; + } +} + +void Layer::addVisibleProperties() { + switch (type()) { + // Intentional fall through. Same for all tile layers + case layergroupid::TypeID::DefaultTileLayer: + case layergroupid::TypeID::SingleImageTileLayer: + case layergroupid::TypeID::SizeReferenceTileLayer: + case layergroupid::TypeID::TemporalTileLayer: + case layergroupid::TypeID::TileIndexTileLayer: + case layergroupid::TypeID::ByIndexTileLayer: + case layergroupid::TypeID::ByLevelTileLayer: + if (_tileProvider) { + addPropertySubOwner(*_tileProvider); + } + break; + case layergroupid::TypeID::SolidColor: + addProperty(_otherTypesProperties.color); + default: + break; + } +} + +void Layer::removeVisibleProperties() { + switch (type()) { + // Intentional fall through. Same for all tile layers + case layergroupid::TypeID::DefaultTileLayer: + case layergroupid::TypeID::SingleImageTileLayer: + case layergroupid::TypeID::SizeReferenceTileLayer: + case layergroupid::TypeID::TemporalTileLayer: + case layergroupid::TypeID::TileIndexTileLayer: + case layergroupid::TypeID::ByIndexTileLayer: + case layergroupid::TypeID::ByLevelTileLayer: + if (_tileProvider) { + removePropertySubOwner(*_tileProvider); + } + break; + case layergroupid::TypeID::SolidColor: + removeProperty(_otherTypesProperties.color); + break; + default: + break; + } } } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/layer/layer.h b/modules/globebrowsing/rendering/layer/layer.h index 437eae8ef2..c8380e5b4f 100644 --- a/modules/globebrowsing/rendering/layer/layer.h +++ b/modules/globebrowsing/rendering/layer/layer.h @@ -25,14 +25,17 @@ #ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__ #define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__ -#include - #include + +#include #include #include +#include +#include #include #include +#include namespace openspace { namespace globebrowsing { @@ -41,29 +44,55 @@ namespace tileprovider { class TileProvider; } -/** - * Simple struct which is used to enable/disable TileProvider - * and associate is with a name. It also holds layer specific information - * which is used in rendering of layer. - */ class Layer : public properties::PropertyOwner { public: - Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict); + /** + * Properties used when the layer type is not a tile type layer. These properties + * can be added or removed depending on the layer type. + */ + struct OtherTypesProperties { + properties::Vec3Property color; + }; + + Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict); ChunkTilePile getChunkTilePile(const TileIndex& tileIndex, int pileSize) const; + Tile::Status getTileStatus(const TileIndex& index) const; - bool enabled() const { return _enabled.value(); } - tileprovider::TileProvider* tileProvider() const { return _tileProvider.get(); } - const LayerRenderSettings& renderSettings() const { return _renderSettings; } - + layergroupid::TypeID type() const; + layergroupid::BlendModeID blendMode() const; + TileDepthTransform depthTransform() const; + bool enabled() const; + tileprovider::TileProvider* tileProvider() const; + const OtherTypesProperties& otherTypesProperties() const; + const LayerRenderSettings& renderSettings() const; + const LayerAdjustment& layerAdjustment() const; + void onChange(std::function callback); + + void update(); private: + layergroupid::TypeID parseTypeIdFromDictionary(const ghoul::Dictionary& initDict) const; + void initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict); + void addVisibleProperties(); + void removeVisibleProperties(); + + properties::OptionProperty _typeOption; + properties::OptionProperty _blendModeOption; properties::BoolProperty _enabled; properties::TriggerProperty _reset; + + layergroupid::TypeID _type; std::shared_ptr _tileProvider; + OtherTypesProperties _otherTypesProperties; LayerRenderSettings _renderSettings; -}; + LayerAdjustment _layerAdjustment; + + const layergroupid::GroupID _layerGroupId; + + std::function _onChangeCallback; + }; } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/rendering/layer/layeradjustment.cpp b/modules/globebrowsing/rendering/layer/layeradjustment.cpp new file mode 100644 index 0000000000..80b038612b --- /dev/null +++ b/modules/globebrowsing/rendering/layer/layeradjustment.cpp @@ -0,0 +1,134 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { +namespace globebrowsing { + +namespace { + const char* keyType = "Type"; + const char* keyChromaKeyColor = "ChromaKeyColor"; + const char* keyChromaKeyTolerance = "ChromaKeyTolerance"; +} + +LayerAdjustment::LayerAdjustment() + : properties::PropertyOwner("adjustment") + , _typeOption( + "type", + "Type", + properties::OptionProperty::DisplayType::Dropdown + ) + , chromaKeyColor( + "chromaKeyColor", + "Chroma key color", + glm::vec3(0.f, 0.f, 0.f), + glm::vec3(0.f), + glm::vec3(1.f) + ) + , chromaKeyTolerance( + "chromaKeyTolerance", + "Chroma key tolerance", + 0, + 0, + 1 + ) + , _onChangeCallback([](){}) +{ + // Add options to option properties + for (int i = 0; i < layergroupid::NUM_ADJUSTMENT_TYPES; ++i) { + _typeOption.addOption(i, layergroupid::ADJUSTMENT_TYPE_NAMES[i]); + } + _typeOption.setValue(static_cast(layergroupid::AdjustmentTypeID::None)); + _type = static_cast(_typeOption.value()); + + _typeOption.onChange([&](){ + removeVisibleProperties(); + _type = static_cast(_typeOption.value()); + addVisibleProperties(); + _onChangeCallback(); + }); + chromaKeyColor.setViewOption(properties::Property::ViewOptions::Color); + + addProperty(_typeOption); + addVisibleProperties(); +} + +void LayerAdjustment::setValuesFromDictionary( + const ghoul::Dictionary& adjustmentDict) +{ + std::string dictType; + glm::vec3 dictChromaKeyColor; + float dictChromaKeyTolerance; + + if (adjustmentDict.getValue(keyType, dictType)) { + _typeOption.setValue( + static_cast(layergroupid::getAdjustmentTypeIDFromName(dictType))); + } + if (adjustmentDict.getValue(keyChromaKeyColor, dictChromaKeyColor)) { + chromaKeyColor.setValue(dictChromaKeyColor); + } + if (adjustmentDict.getValue(keyChromaKeyTolerance, dictChromaKeyTolerance)) { + chromaKeyTolerance.setValue(dictChromaKeyTolerance); + } +} + +layergroupid::AdjustmentTypeID LayerAdjustment::type() const { + return _type; +} + +void LayerAdjustment::addVisibleProperties() { + switch (type()) { + case layergroupid::AdjustmentTypeID::None: + break; + case layergroupid::AdjustmentTypeID::ChromaKey: { + addProperty(chromaKeyColor); + addProperty(chromaKeyTolerance); + break; + } + case layergroupid::AdjustmentTypeID::TransferFunction: + break; + } +} + +void LayerAdjustment::removeVisibleProperties() { + switch (type()) { + case layergroupid::AdjustmentTypeID::None: + break; + case layergroupid::AdjustmentTypeID::ChromaKey: { + removeProperty(chromaKeyColor); + removeProperty(chromaKeyTolerance); + break; + } + case layergroupid::AdjustmentTypeID::TransferFunction: + break; + } +} + +void LayerAdjustment::onChange(std::function callback) { + _onChangeCallback = std::move(callback); +} + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h b/modules/globebrowsing/rendering/layer/layeradjustment.h similarity index 64% rename from modules/globebrowsing/tile/tileprovider/presentationslideprovider.h rename to modules/globebrowsing/rendering/layer/layeradjustment.h index 4b331777a1..20b9f11a78 100644 --- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h +++ b/modules/globebrowsing/rendering/layer/layeradjustment.h @@ -22,48 +22,51 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ -#define __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__ -#include -#include +#include -#include -#include +#include #include - -#include -#include +#include +#include namespace openspace { namespace globebrowsing { + namespace tileprovider { + class TileProvider; +} -class PresentationSlideProvider : public TileProvider { +class LayerAdjustment : public properties::PropertyOwner +{ public: - PresentationSlideProvider(const ghoul::Dictionary& dictionary); - PresentationSlideProvider(const std::string& imagePath); - virtual ~PresentationSlideProvider() = default; + LayerAdjustment(); + ~LayerAdjustment() = default; - virtual Tile getTile(const TileIndex& tileIndex) override; - virtual Tile::Status getTileStatus(const TileIndex& index) override; - virtual TileDepthTransform depthTransform() override; - virtual void update() override; - virtual void reset() override; - virtual int maxLevel() override; + void setValuesFromDictionary(const ghoul::Dictionary& adjustmentDict); + + layergroupid::AdjustmentTypeID type() const; + + // Properties + properties::Vec3Property chromaKeyColor; + properties::FloatProperty chromaKeyTolerance; + + void onChange(std::function callback); private: - TileProvider* slideProvider(); + void addVisibleProperties(); + void removeVisibleProperties(); + + properties::OptionProperty _typeOption; + layergroupid::AdjustmentTypeID _type; - TileIndex _tileIndex; - properties::IntProperty _slideIndex; - std::vector> _slideProviders; - std::unique_ptr _defaultProvider; + std::function _onChangeCallback; }; -} // namespace tileprovider } // namespace globebrowsing } // namespace openspace -#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__ diff --git a/modules/globebrowsing/rendering/layer/layergroup.cpp b/modules/globebrowsing/rendering/layer/layergroup.cpp index 94f5d8cf5d..7b038c8f58 100644 --- a/modules/globebrowsing/rendering/layer/layergroup.cpp +++ b/modules/globebrowsing/rendering/layer/layergroup.cpp @@ -26,35 +26,36 @@ #include +namespace { + const char* _loggerCat = "LayerGroup"; +} + namespace openspace { namespace globebrowsing { -LayerGroup::LayerGroup(std::string name) - : properties::PropertyOwner(std::move(name)) +LayerGroup::LayerGroup(layergroupid::GroupID id) + : properties::PropertyOwner(std::move(layergroupid::LAYER_GROUP_NAMES[id])) + , _groupId(id) , _levelBlendingEnabled("blendTileLevels", "blend tile levels", false) { addProperty(_levelBlendingEnabled); } -LayerGroup::LayerGroup(layergroupid::ID id, const ghoul::Dictionary& dict) - : LayerGroup(layergroupid::LAYER_GROUP_NAMES[id]) +LayerGroup::LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict) + : LayerGroup(id) { for (size_t i = 0; i < dict.size(); i++) { std::string dictKey = std::to_string(i + 1); ghoul::Dictionary layerDict = dict.value(dictKey); try { - _layers.push_back(std::make_shared(id, layerDict)); + addLayer(layerDict); } catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); continue; } } - - for (const auto& layer : _layers) { - addPropertySubOwner(layer.get()); - } } void LayerGroup::update() { @@ -62,12 +63,48 @@ void LayerGroup::update() { for (const auto& layer : _layers) { if (layer->enabled()) { - layer->tileProvider()->update(); + layer->update(); _activeLayers.push_back(layer); } } } +void LayerGroup::addLayer(const ghoul::Dictionary& layerDict) { + if (!layerDict.hasKeyAndValue("Name")) { + LERROR("'Name' must be specified for layer."); + return; + } + auto layer = std::make_shared(_groupId, layerDict); + layer->onChange(_onChangeCallback); + if (hasPropertySubOwner(layer->name())) { + LINFO("Layer with name " + layer->name() + " already exists."); + } + else { + _layers.push_back(layer); + update(); + if(_onChangeCallback) { + _onChangeCallback(); + } + addPropertySubOwner(layer.get()); + } +} + +void LayerGroup::deleteLayer(const std::string& layerName) { + for (std::vector>::iterator it = _layers.begin(); it != _layers.end(); ++it) { + if (it->get()->name() == layerName) { + removePropertySubOwner(it->get()); + _layers.erase(it); + update(); + if(_onChangeCallback) { + _onChangeCallback(); + } + LINFO("Deleted layer " + layerName); + return; + } + } + LERROR("Could not find layer " + layerName); +} + const std::vector>& LayerGroup::layers() const { return _layers; } @@ -81,10 +118,10 @@ int LayerGroup::pileSize() const{ } void LayerGroup::onChange(std::function callback) { - _onChangeCallback = callback; - _levelBlendingEnabled.onChange(callback); + _onChangeCallback = std::move(callback); + _levelBlendingEnabled.onChange(_onChangeCallback); for (const std::shared_ptr& layer : _layers) { - layer->onChange(callback); + layer->onChange(_onChangeCallback); } } diff --git a/modules/globebrowsing/rendering/layer/layergroup.h b/modules/globebrowsing/rendering/layer/layergroup.h index d19e9b76d6..8cf6d22d9b 100644 --- a/modules/globebrowsing/rendering/layer/layergroup.h +++ b/modules/globebrowsing/rendering/layer/layergroup.h @@ -47,12 +47,15 @@ namespace tileprovider { * Convenience class for dealing with multiple Layers. */ struct LayerGroup : public properties::PropertyOwner { - LayerGroup(std::string name); - LayerGroup(layergroupid::ID id, const ghoul::Dictionary& dict); + LayerGroup(layergroupid::GroupID id); + LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict); /// Updates all layers tile providers within this group void update(); + void addLayer(const ghoul::Dictionary& layerDict); + void deleteLayer(const std::string& layerName); + /// @returns const vector of all layers const std::vector>& layers() const; @@ -67,6 +70,7 @@ struct LayerGroup : public properties::PropertyOwner { void onChange(std::function callback); private: + const layergroupid::GroupID _groupId; std::vector> _layers; std::vector> _activeLayers; diff --git a/modules/globebrowsing/rendering/layer/layergroupid.h b/modules/globebrowsing/rendering/layer/layergroupid.h index 07b58ca247..8445c4b962 100644 --- a/modules/globebrowsing/rendering/layer/layergroupid.h +++ b/modules/globebrowsing/rendering/layer/layergroupid.h @@ -25,32 +25,133 @@ #ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__ #define __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__ +#include namespace openspace { namespace globebrowsing { namespace layergroupid { -static const int NUM_LAYER_GROUPS = 7; -static const char* LAYER_GROUP_NAMES[NUM_LAYER_GROUPS] = { +static const int NUM_LAYER_GROUPS = 5; +static const std::string LAYER_GROUP_NAMES[NUM_LAYER_GROUPS] = { "HeightLayers", "ColorLayers", - "ColorOverlays", - "GrayScaleLayers", - "GrayScaleColorOverlays", + "Overlays", "NightLayers", "WaterMasks" }; -enum ID { +enum GroupID { HeightLayers, ColorLayers, - ColorOverlays, - GrayScaleLayers, - GrayScaleColorOverlays, + Overlays, NightLayers, - WaterMasks + WaterMasks, + Unknown, }; +static const int NUM_LAYER_TYPES = 8; +static const std::string LAYER_TYPE_NAMES[NUM_LAYER_TYPES] = { + "DefaultTileLayer", + "SingleImageTileLayer", + "SizeReferenceTileLayer", + "TemporalTileLayer", + "TileIndexTileLayer", + "ByIndexTileLayer", + "ByLevelTileLayer", + "SolidColor", +}; + +/** + This enumeration is specified explicitly since it is used in the shader as well. + */ +enum class TypeID { + Unknown = -1, + DefaultTileLayer = 0, + SingleImageTileLayer = 1, + SizeReferenceTileLayer = 2, + TemporalTileLayer = 3, + TileIndexTileLayer = 4, + ByIndexTileLayer = 5, + ByLevelTileLayer = 6, + SolidColor = 7, +}; + +static const int NUM_ADJUSTMENT_TYPES = 3; +static const std::string ADJUSTMENT_TYPE_NAMES[NUM_ADJUSTMENT_TYPES] = { + "None", + "ChromaKey", + "TransferFunction", +}; + +/** + This enumeration is specified explicitly since it is used in the shader as well. + */ +enum class AdjustmentTypeID { + None = 0, + ChromaKey = 1, + TransferFunction = 2, +}; + +static const int NUM_BLEND_MODES = 5; +static const std::string BLEND_MODE_NAMES[NUM_BLEND_MODES] = { + "Normal", + "Multiply", + "Add", + "Subtract", + "Color", +}; + +/** + This enumeration is specified explicitly since it is used in the shader as well. + */ +enum class BlendModeID { + Normal = 0, + Multiply = 1, + Add = 2, + Subtract = 3, + Color = 4, +}; + +static TypeID getTypeIDFromTypeString(std::string typeString) { + for (int i = 0; i < NUM_LAYER_TYPES; ++i) { + if (typeString == LAYER_TYPE_NAMES[i]) { + return static_cast(i); + } + } + return TypeID::Unknown; +} + +static layergroupid::GroupID getGroupIDFromName(std::string layerGroupName) { + for (int i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) { + if (layerGroupName == layergroupid::LAYER_GROUP_NAMES[i]) { + return static_cast(i); + } + } + return GroupID::Unknown; +} + +static layergroupid::AdjustmentTypeID getAdjustmentTypeIDFromName( + std::string adjustmentTypeName) +{ + for (int i = 0; i < layergroupid::NUM_ADJUSTMENT_TYPES; ++i) { + if (adjustmentTypeName == layergroupid::ADJUSTMENT_TYPE_NAMES[i]) { + return static_cast(i); + } + } + return AdjustmentTypeID::None; +} + +static layergroupid::BlendModeID getBlendModeIDFromName( + std::string blendModeName) +{ + for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) { + if (blendModeName == layergroupid::BLEND_MODE_NAMES[i]) { + return static_cast(i); + } + } + return BlendModeID::Normal; +} + } // namespace layergroupid } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/rendering/layer/layermanager.cpp b/modules/globebrowsing/rendering/layer/layermanager.cpp index df8165bc25..b3f2aabb8a 100644 --- a/modules/globebrowsing/rendering/layer/layermanager.cpp +++ b/modules/globebrowsing/rendering/layer/layermanager.cpp @@ -31,23 +31,38 @@ namespace openspace { namespace globebrowsing { +namespace { + const char* _loggerCat = "LayerManager"; +} + LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict) : properties::PropertyOwner("Layers") { - if (layergroupid::NUM_LAYER_GROUPS != layerGroupsDict.size()) { - throw ghoul::RuntimeError( - "Number of Layer Groups must be equal to " + layergroupid::NUM_LAYER_GROUPS); + // First create empty layer groups in case not all are specified + _layerGroups.resize(layergroupid::NUM_LAYER_GROUPS); + for (int i = 0; i < _layerGroups.size(); ++i) { + ghoul::Dictionary emptyDict; + _layerGroups[i] = std::make_shared( + static_cast(i), emptyDict + ); } - // Create all the categories of tile providers - for (size_t i = 0; i < layerGroupsDict.size(); i++) { - const std::string& groupName = layergroupid::LAYER_GROUP_NAMES[i]; - ghoul::Dictionary layerGroupDict = - layerGroupsDict.value(groupName); + std::vector layerGroupNamesInDict = layerGroupsDict.keys(); - _layerGroups.push_back( - std::make_shared( - static_cast(i), layerGroupDict)); + // Create all the layer groups + for (const std::string groupName : layerGroupNamesInDict) { + + layergroupid::GroupID groupId = layergroupid::getGroupIDFromName(groupName); + + if (groupId != layergroupid::GroupID::Unknown) { + ghoul::Dictionary layerGroupDict = + layerGroupsDict.value(groupName); + _layerGroups[static_cast(groupId)] = + std::make_shared(groupId, layerGroupDict); + } + else { + LWARNING("Unknown layer group: " + groupName); + } } for (const std::shared_ptr& layerGroup : _layerGroups) { @@ -55,11 +70,21 @@ LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict) } } +void LayerManager::addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict) { + ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known"); + _layerGroups[groupId]->addLayer(layerDict); +} + +void LayerManager::deleteLayer(layergroupid::GroupID groupId, std::string layerName) { + ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known"); + _layerGroups[groupId]->deleteLayer(layerName); +} + const LayerGroup& LayerManager::layerGroup(size_t groupId) { return *_layerGroups[groupId]; } -const LayerGroup& LayerManager::layerGroup(layergroupid::ID groupId) { +const LayerGroup& LayerManager::layerGroup(layergroupid::GroupID groupId) { return *_layerGroups[groupId]; } @@ -92,45 +117,35 @@ void LayerManager::reset(bool includeDisabled) { } } -TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::ID id, +TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::GroupID id, size_t preferredTileSize) { switch (id) { - case layergroupid::ID::HeightLayers: { + case layergroupid::GroupID::HeightLayers: { size_t tileSize = preferredTileSize ? preferredTileSize : 64; return TileTextureInitData(tileSize, tileSize, GL_FLOAT, ghoul::opengl::Texture::Format::Red, TileTextureInitData::ShouldAllocateDataOnCPU::Yes); } - case layergroupid::ID::ColorLayers: { + case layergroupid::GroupID::ColorLayers: { size_t tileSize = preferredTileSize ? preferredTileSize : 512; return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RGBA); + ghoul::opengl::Texture::Format::BGRA); } - case layergroupid::ID::ColorOverlays: { + case layergroupid::GroupID::Overlays: { size_t tileSize = preferredTileSize ? preferredTileSize : 512; return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RGBA); + ghoul::opengl::Texture::Format::BGRA); } - case layergroupid::ID::GrayScaleLayers: { + case layergroupid::GroupID::NightLayers: { size_t tileSize = preferredTileSize ? preferredTileSize : 512; return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RG); + ghoul::opengl::Texture::Format::BGRA); } - case layergroupid::ID::GrayScaleColorOverlays: { + case layergroupid::GroupID::WaterMasks: { size_t tileSize = preferredTileSize ? preferredTileSize : 512; return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RG); - } - case layergroupid::ID::NightLayers: { - size_t tileSize = preferredTileSize ? preferredTileSize : 512; - return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RGBA); - } - case layergroupid::ID::WaterMasks: { - size_t tileSize = preferredTileSize ? preferredTileSize : 512; - return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE, - ghoul::opengl::Texture::Format::RGBA); + ghoul::opengl::Texture::Format::BGRA); } default: { ghoul_assert(false, "Unknown layer group ID"); @@ -138,10 +153,10 @@ TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::ID id, } } -bool LayerManager::shouldPerformPreProcessingOnLayergroup(layergroupid::ID id) { +bool LayerManager::shouldPerformPreProcessingOnLayergroup(layergroupid::GroupID id) { // Only preprocess height layers by default switch (id) { - case layergroupid::ID::HeightLayers: return true; + case layergroupid::GroupID::HeightLayers: return true; default: return false; } } diff --git a/modules/globebrowsing/rendering/layer/layermanager.h b/modules/globebrowsing/rendering/layer/layermanager.h index 22ef5a79a3..454a02d9f8 100644 --- a/modules/globebrowsing/rendering/layer/layermanager.h +++ b/modules/globebrowsing/rendering/layer/layermanager.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -45,8 +46,11 @@ class LayerManager : public properties::PropertyOwner { public: LayerManager(const ghoul::Dictionary& textureCategoriesDictionary); + void addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict); + void deleteLayer(layergroupid::GroupID groupId, std::string layerName); + const LayerGroup& layerGroup(size_t groupId); - const LayerGroup& layerGroup(layergroupid::ID); + const LayerGroup& layerGroup(layergroupid::GroupID); bool hasAnyBlendingLayersEnabled() const; @@ -55,10 +59,10 @@ public: void update(); void reset(bool includingDisabled = false); - static TileTextureInitData getTileTextureInitData(layergroupid::ID id, + static TileTextureInitData getTileTextureInitData(layergroupid::GroupID id, size_t preferredTileSize = 0); - static bool shouldPerformPreProcessingOnLayergroup(layergroupid::ID id); + static bool shouldPerformPreProcessingOnLayergroup(layergroupid::GroupID id); void onChange(std::function callback); private: diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp index 6fe1474c58..8cbbd95a79 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp @@ -37,11 +37,12 @@ namespace { LayerRenderSettings::LayerRenderSettings() : properties::PropertyOwner("Settings") - , opacity(properties::FloatProperty("Opacity", "opacity", 1.f, 0.f, 1.f)) - , gamma(properties::FloatProperty("Gamma", "gamma", 1, 0, 5)) - , multiplier(properties::FloatProperty("Multiplier", "multiplier", 1.f, 0.f, 20.f)) - , offset(properties::FloatProperty("Offset", "offset", 0.f, -10000.f, 10000.f)) - , valueBlending(properties::FloatProperty("Value blending", "valueBlending", + , setDefault("setDefault", "Set Default") + , opacity(properties::FloatProperty("opacity", "Opacity", 1.f, 0.f, 1.f)) + , gamma(properties::FloatProperty("gamma", "Gamma", 1, 0, 5)) + , multiplier(properties::FloatProperty("multiplier", "Multiplier", 1.f, 0.f, 20.f)) + , offset(properties::FloatProperty("offset", "Offset", 0.f, -10000.f, 10000.f)) + , valueBlending(properties::FloatProperty("valueBlending", "Value Blending", 1.f, 0.f, 1.f)) , useValueBlending(false) { @@ -50,6 +51,9 @@ LayerRenderSettings::LayerRenderSettings() addProperty(gamma); addProperty(multiplier); addProperty(offset); + addProperty(setDefault); + + setDefault.onChange([this](){ setDefaultValues(); }); } void LayerRenderSettings::setValuesFromDictionary( @@ -62,19 +66,19 @@ void LayerRenderSettings::setValuesFromDictionary( float dictValueBlending; if(renderSettingsDict.getValue(keyOpacity, dictOpacity)) { - opacity.setValue(dictOpacity); + opacity = dictOpacity; } if(renderSettingsDict.getValue(keyGamma, dictGamma)) { - gamma.setValue(dictGamma); + gamma = dictGamma; } if(renderSettingsDict.getValue(keyMultiplier, dictMultiplier)) { - multiplier.setValue(dictMultiplier); + multiplier = dictMultiplier; } if(renderSettingsDict.getValue(keyOffset, dictOffset)) { - multiplier.setValue(dictOffset); + multiplier = dictOffset; } if(renderSettingsDict.getValue(keyValueBlending, dictValueBlending)) { - valueBlending.setValue(dictValueBlending); + valueBlending = dictValueBlending; useValueBlending = true; } } @@ -100,5 +104,13 @@ glm::vec4 LayerRenderSettings::performLayerSettings(glm::vec4 currentValue) cons return newValue; } +void LayerRenderSettings::setDefaultValues() { + opacity = 1.f; + gamma = 1.f; + multiplier = 1.f; + offset = 0.f; + valueBlending = 1.f; +} + } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.h b/modules/globebrowsing/rendering/layer/layerrendersettings.h index 2fb4ea2432..95538ee28d 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.h +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.h @@ -28,6 +28,7 @@ #include #include +#include namespace openspace { namespace globebrowsing { @@ -35,6 +36,8 @@ namespace globebrowsing { struct LayerRenderSettings : public properties::PropertyOwner { LayerRenderSettings(); + properties::TriggerProperty setDefault; + properties::FloatProperty opacity; properties::FloatProperty gamma; properties::FloatProperty multiplier; @@ -52,6 +55,9 @@ struct LayerRenderSettings : public properties::PropertyOwner { /// This function matches the function with the same name in the /// shader code glm::vec4 performLayerSettings(glm::vec4 currentValue) const; + +private: + void setDefaultValues(); }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/layershadermanager.cpp b/modules/globebrowsing/rendering/layershadermanager.cpp index 0dc6aceb99..502dbbc150 100644 --- a/modules/globebrowsing/rendering/layershadermanager.cpp +++ b/modules/globebrowsing/rendering/layershadermanager.cpp @@ -40,7 +40,10 @@ namespace globebrowsing { bool LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData::operator==( const LayerGroupPreprocessingData& other) const { - return lastLayerIdx == other.lastLayerIdx && + return layerType == other.layerType && + blendMode == other.blendMode && + layerAdjustmentType == other.layerAdjustmentType && + lastLayerIdx == other.lastLayerIdx && layerBlendingEnabled == other.layerBlendingEnabled; } @@ -72,10 +75,19 @@ LayerShaderManager::LayerShaderPreprocessingData for (size_t i = 0; i < layergroupid::NUM_LAYER_GROUPS; i++) { LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData layeredTextureInfo; - auto layerGroup = layerManager->layerGroup(i); + + const LayerGroup& layerGroup = layerManager->layerGroup(i); + std::vector> layers = layerGroup.activeLayers(); + layeredTextureInfo.lastLayerIdx = layerGroup.activeLayers().size() - 1; layeredTextureInfo.layerBlendingEnabled = layerGroup.layerBlendingEnabled(); + for (const std::shared_ptr& layer : layers) { + layeredTextureInfo.layerType.push_back(layer->type()); + layeredTextureInfo.blendMode.push_back(layer->blendMode()); + layeredTextureInfo.layerAdjustmentType.push_back(layer->layerAdjustment().type()); + } + preprocessingData.layeredTextureInfo[i] = layeredTextureInfo; } @@ -153,8 +165,41 @@ void LayerShaderManager::recompileShaderProgram( "blend" + groupName, textureTypes[i].layerBlendingEnabled ); + + // This is to avoid errors from shader preprocessor + std::string keyLayerType = groupName + "0" + "LayerType"; + shaderDictionary.setValue(keyLayerType, 0); + + for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) { + std::string key = groupName + std::to_string(j) + "LayerType"; + shaderDictionary.setValue(key, static_cast(textureTypes[i].layerType[j])); + } + + // This is to avoid errors from shader preprocessor + std::string keyBlendMode = groupName + "0" + "BlendMode"; + shaderDictionary.setValue(keyBlendMode, 0); + + for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) { + std::string key = groupName + std::to_string(j) + "BlendMode"; + shaderDictionary.setValue(key, static_cast(textureTypes[i].blendMode[j])); + } + + // This is to avoid errors from shader preprocessor + std::string keyLayerAdjustmentType = groupName + "0" + "LayerAdjustmentType"; + shaderDictionary.setValue(keyLayerAdjustmentType, 0); + + for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) { + std::string key = groupName + std::to_string(j) + "LayerAdjustmentType"; + shaderDictionary.setValue(key, static_cast(textureTypes[i].layerAdjustmentType[j])); + } } + ghoul::Dictionary layerGroupNames; + for (int i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) { + layerGroupNames.setValue(std::to_string(i), layergroupid::LAYER_GROUP_NAMES[i]); + } + shaderDictionary.setValue("layerGroups", layerGroupNames); + // Other settings such as "useAtmosphere" auto keyValuePairs = _preprocessingData.keyValuePairs; for (size_t i = 0; i < keyValuePairs.size(); i++) { diff --git a/modules/globebrowsing/rendering/layershadermanager.h b/modules/globebrowsing/rendering/layershadermanager.h index d6712c382b..026e98ecd0 100644 --- a/modules/globebrowsing/rendering/layershadermanager.h +++ b/modules/globebrowsing/rendering/layershadermanager.h @@ -26,6 +26,7 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__ #include +#include #include #include @@ -63,6 +64,9 @@ public: struct LayerGroupPreprocessingData { int lastLayerIdx; bool layerBlendingEnabled; + std::vector layerType; + std::vector blendMode; + std::vector layerAdjustmentType; bool operator==(const LayerGroupPreprocessingData& other) const; }; diff --git a/modules/globebrowsing/scripts/layer_support.lua b/modules/globebrowsing/scripts/layer_support.lua index 576fb52ed0..a1af426327 100644 --- a/modules/globebrowsing/scripts/layer_support.lua +++ b/modules/globebrowsing/scripts/layer_support.lua @@ -8,6 +8,55 @@ openspace.globebrowsing.documentation = { Name = "createHeightLayers", Arguments = "table", Documentation = "Creates a table used in the 'HeightLayers' of a RenderableGlobe." + }, + { + Name = "createTemporalGibsGdalXml", + Arguments = "string, string, string, string, string, string", + Documentation = + "Creates an XML configuration for a temporal GIBS dataset." .. + "Arguments are: Name, Start date, end date, time resolution, time format," .. + "resolution, file format. For all specifications, see " .. + "https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" .. + "Usage:" .. + "openspace.globebrowsing.addLayer(" .. + "\"Earth\"," .. + "\"ColorLayers\"," .. + "{" .. + "Type = \"TemporalTileLayer\"," .. + "Name = \"MODIS_Terra_Chlorophyll_A\"," .. + "FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(" .. + "\"MODIS_Terra_Chlorophyll_A\"," .. + "\"2013-07-02\"," .. + "\"Yesterday\"," .. + "\"1d\"," .. + "\"1km\"," .. + "\"png\"" .. + ")" .. + "}" .. + ")" + }, + { + Name = "createGibsGdalXml", + Arguments = "string, string, string, string", + Documentation = + "Creates an XML configuration for a GIBS dataset." .. + "Arguments are: layerName, date, resolution, format." .. + "For all specifications, see " .. + "https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" .. + "Usage:" .. + "openspace.globebrowsing.addLayer(" .. + "\"Earth\"," .. + "\"ColorLayers\"," .. + "{" .. + "Name = \"MODIS_Terra_Chlorophyll_A\"," .. + "FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(" .. + "\"MODIS_Terra_Chlorophyll_A\"," .. + "\"2013-07-02\"," .. + "\"1km\"," .. + "\"png\"" .. + ")" .. + "}" .. + ")" } } @@ -31,7 +80,86 @@ end openspace.globebrowsing.createHeightLayers = function (patches) result = {} for k,v in pairs(patches) do - table.insert(result, { Name = v["Name"], FilePath = v["Height"], TilePixelSize = 90, DoPreProcessing = true }) + table.insert(result, { Name = v["Name"], FilePath = v["Height"], TilePixelSize = 90, PerformPreProcessing = true }) end return result end + +openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, startDate, endDate, timeResolution, resolution, format) + temporalTemplate = + "" .. + "" .. startDate .. "" .. + "" .. endDate .. "" .. + "" .. timeResolution .. "" .. + "YYYY-MM-DD" .. + openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format) .. + "" + return temporalTemplate +end + +openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format) + tileLevel = 5 + -- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL + if resolution == "2km" then + tileLevel = 5 + elseif resolution == "1km" then + tileLevel = 6 + elseif resolution == "500m" then + tileLevel = 7 + elseif resolution == "250m" then + tileLevel = 8 + elseif resolution == "125m" then + tileLevel = 9 + elseif resolution == "62.5m" then + tileLevel = 10 + elseif resolution == "31.25m" then + tileLevel = 11 + elseif resolution == "15.625m" then + tileLevel = 12 + else + openspace.printError("Unknown resolution: " .. resolution) + return "" + end + + rasterCount = 3 + if format == "jpg" then + if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then + rasterCount = 1 + else + rasterCount = 3 + end + elseif format == "png" then + rasterCount = 4 + else + openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'") + return "" + end + + gdalWmsTemplate = + "" .. + "" .. + "https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" .. + layerName .. "/default/" .. date .. "/" .. resolution .. + "/${z}/${y}/${x}." .. format .. "" .. + "" .. + "" .. + "-180.0" .. + "90" .. + "396.0" .. + "-198" .. + "" .. tileLevel .. "" .. + "2" .. + "1" .. + "top" .. + "" .. + "EPSG:4326" .. + "512" .. + "512" .. + "" .. rasterCount .. "" .. + "true" .. + "400,204,404" .. + "true" .. + "" + + return gdalWmsTemplate +end \ No newline at end of file diff --git a/modules/globebrowsing/shaders/blending.hglsl b/modules/globebrowsing/shaders/blending.hglsl index e6b6b64bfd..ce64c9ce84 100644 --- a/modules/globebrowsing/shaders/blending.hglsl +++ b/modules/globebrowsing/shaders/blending.hglsl @@ -25,7 +25,7 @@ #ifndef BLENDING_HGLSL #define BLENDING_HGLSL -vec4 blendOver(vec4 oldColor, vec4 newColor) +vec4 blendNormal(vec4 oldColor, vec4 newColor) { vec4 toReturn; toReturn.rgb = diff --git a/modules/globebrowsing/shaders/pointglobe_fs.glsl b/modules/globebrowsing/shaders/pointglobe_fs.glsl index cafeb66d3b..5977cfddab 100644 --- a/modules/globebrowsing/shaders/pointglobe_fs.glsl +++ b/modules/globebrowsing/shaders/pointglobe_fs.glsl @@ -24,31 +24,22 @@ #include "fragment.glsl" -uniform vec3 directionToSunViewSpace; +//uniform vec3 directionToSunViewSpace; uniform vec3 positionCameraSpace; +//uniform float lightOverflow; in vec4 vs_positionClipSpace; +in vec2 vs_positionModelSpace; Fragment getFragment() { - vec2 pointCoord = (gl_PointCoord.xy - vec2(0.5)) * 2; - pointCoord.y = -pointCoord.y; // y should point up in cam space - if(length(pointCoord) > 1) // Outside of circle radius? - discard; - - // z_coord of sphere - float zCoord = sqrt(1 - pow(length(pointCoord),2)); - - // Light calculations - vec3 normal = normalize(vec3(pointCoord, zCoord)); - float cosTerm = max(dot(directionToSunViewSpace, normal), 0); - - vec3 color = vec3(1,1,1) * 0.7; - vec3 shadedColor = cosTerm * color; - + float alpha = 1 - sqrt(pow(vs_positionModelSpace.x, 2) + pow(vs_positionModelSpace.y, 2)); + alpha = pow(alpha, 3); Fragment frag; - frag.color = vec4(shadedColor,1); + frag.color = vec4(1,1,1, alpha);// + vec4(1,1,1,1) * 0.0000000001 * directionToSunViewSpace.x; + //frag.color *= 1 + (lightOverflow * lightOverflow) * 0.0001; frag.depth = vs_positionClipSpace.w; + frag.blend = BLEND_MODE_ADDITIVE; return frag; } diff --git a/modules/globebrowsing/shaders/pointglobe_vs.glsl b/modules/globebrowsing/shaders/pointglobe_vs.glsl index 011e9bdf07..c68b63d1bf 100644 --- a/modules/globebrowsing/shaders/pointglobe_vs.glsl +++ b/modules/globebrowsing/shaders/pointglobe_vs.glsl @@ -26,29 +26,28 @@ #include "PowerScaling/powerScaling_vs.hglsl" -layout(location = 0) in vec3 in_position; +layout(location = 0) in vec2 in_position; -uniform int windowWidth; -uniform float globeRadius; +uniform float lightIntensityClamped; uniform mat4 modelViewTransform; uniform mat4 projectionTransform; uniform mat4 directionToSunViewSpace; out vec4 vs_positionClipSpace; out vec4 vs_positionCameraSpace; +out vec2 vs_positionModelSpace; void main() { - vec4 positionCameraSpace = modelViewTransform * vec4(in_position, 1); - vs_positionClipSpace = projectionTransform * positionCameraSpace; + vs_positionModelSpace = in_position; - vs_positionClipSpace = z_normalization(vs_positionClipSpace); - - vec4 pointSizeCameraSpace = modelViewTransform * vec4(0,0, in_position.z, 1); - pointSizeCameraSpace.x = globeRadius; - pointSizeCameraSpace.y = globeRadius; - vec4 pointSizeClipSpace = projectionTransform * pointSizeCameraSpace; - vec4 pointSizeNDC = pointSizeClipSpace / pointSizeClipSpace.w; - - gl_PointSize = pointSizeNDC.x * 2 * windowWidth; - gl_Position = vs_positionClipSpace; + float totalIntensity = lightIntensityClamped; + + vec4 positionCameraSpace = modelViewTransform * vec4(in_position * totalIntensity, 0, 1); + + // Position + vec4 positionClipSpace = projectionTransform * positionCameraSpace; + + vs_positionClipSpace = z_normalization(positionClipSpace); + + gl_Position = z_normalization(positionClipSpace); } diff --git a/modules/globebrowsing/shaders/texturetilemapping.hglsl b/modules/globebrowsing/shaders/texturetilemapping.hglsl index a582abf800..42b9bf0551 100644 --- a/modules/globebrowsing/shaders/texturetilemapping.hglsl +++ b/modules/globebrowsing/shaders/texturetilemapping.hglsl @@ -38,10 +38,6 @@ #define USE_COLORTEXTURE #{useColorLayers} #define COLORTEXTURE_BLENDING_ENABLED #{blendColorLayers} -#define NUMLAYERS_GRAYSCALETEXTURE #{lastLayerIndexGrayScaleLayers} + 1 -#define USE_GRAYSCALETEXTURE #{useGrayScaleLayers} -#define GRAYSCALETEXTURE_BLENDING_ENABLED #{blendGrayScaleLayers} - // Third layer type from LayerShaderManager is water mask #define NUMLAYERS_WATERMASK #{lastLayerIndexWaterMasks} + 1 #define USE_WATERMASK #{useWaterMasks} @@ -53,14 +49,9 @@ #define NIGHTTEXTURE_BLENDING_ENABLED #{blendNightLayers} // Fifth layer type from LayerShaderManager is overlay -#define NUMLAYERS_OVERLAY #{lastLayerIndexColorOverlays} + 1 -#define USE_OVERLAY #{useColorOverlays} -#define OVERLAY_BLENDING_ENABLED #{blendColorOverlays} - -// Sixth layer type from LayerShaderManager is grayscale overlay -#define NUMLAYERS_GRAYSCALE_OVERLAY #{lastLayerIndexGrayScaleColorOverlays} + 1 -#define USE_GRAYSCALE_OVERLAY #{useGrayScaleColorOverlays} -#define GRAYSCALE_OVERLAY_BLENDING_ENABLED #{blendGrayScaleColorOverlays} +#define NUMLAYERS_OVERLAY #{lastLayerIndexOverlays} + 1 +#define USE_OVERLAY #{useOverlays} +#define OVERLAY_BLENDING_ENABLED #{blendOverlays} // Global constants #define CHUNK_DEFAULT_HEIGHT #{defaultHeight} @@ -72,32 +63,143 @@ #define SHOW_HEIGHT_RESOLUTION #{showHeightResolution} #define SHOW_HEIGHT_INTENSITIES #{showHeightIntensities} -float performLayerSettings(float currentValue, const LayerSettings settings) { +float performLayerSettingsRGB(float currentValue, const LayerSettings settings) { float newValue = currentValue; newValue = sign(newValue) * pow(abs(newValue), settings.gamma); newValue = newValue * settings.multiplier; newValue = newValue + settings.offset; - newValue = newValue * settings.opacity; return newValue; } +vec4 performLayerSettingsRGB(vec4 currentValue, const LayerSettings settings) { + vec4 newValue = vec4( + performLayerSettingsRGB(currentValue.r, settings), + performLayerSettingsRGB(currentValue.g, settings), + performLayerSettingsRGB(currentValue.b, settings), + currentValue.a); + + return newValue; +} + +float performLayerSettingsAlpha(float currentValue, const LayerSettings settings) { + float newValue = currentValue; + newValue = newValue * settings.opacity; + return newValue; +} + +vec4 performLayerSettingsAlpha(vec4 currentValue, const LayerSettings settings) { + vec4 newValue = currentValue; + newValue.a = performLayerSettingsAlpha(currentValue.a, settings); + return newValue; +} + +float performLayerSettings(float currentValue, const LayerSettings settings) { + float newValue = performLayerSettingsRGB(currentValue, settings); + newValue = performLayerSettingsAlpha(newValue, settings); + return newValue; +} vec4 performLayerSettings(vec4 currentValue, const LayerSettings settings) { - vec4 newValue = vec4( - performLayerSettings(currentValue.r, settings), - performLayerSettings(currentValue.g, settings), - performLayerSettings(currentValue.b, settings), - performLayerSettings(currentValue.a, settings)); - + vec4 newValue = performLayerSettingsRGB(currentValue, settings); + newValue = performLayerSettingsAlpha(newValue, settings); return newValue; } + +#for id, layerGroup in layerGroups +#for i in 0..#{lastLayerIndex#{layerGroup}} + +vec4 getSample#{layerGroup}#{i}( + const vec2 uv, + const LevelWeights levelWeights, + const Layer #{layerGroup}[#{lastLayerIndex#{layerGroup}} + 1]) +{ + vec4 color = vec4(0,0,0,1); + + // All tile layers are the same. Sample from texture +#if (#{#{layerGroup}#{i}LayerType} == 0) // DefaultTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 1) // SingleImageTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 2) // SizeReferenceTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 3) // TemporalTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 4) // TileIndexTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 5) // ByIndexTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 6) // ByLevelTileLayer + color = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv); +#elif (#{#{layerGroup}#{i}LayerType} == 7) // SolidColor + color.rgb = #{layerGroup}[#{i}].color; +#endif + + return color; +} + +#endfor +#endfor + +#for id, layerGroup in layerGroups +#for i in 0..#{lastLayerIndex#{layerGroup}} + +vec4 blend#{layerGroup}#{i}(vec4 currentColor, vec4 newColor, float blendFactor) { +#if (#{#{layerGroup}#{i}BlendMode} == 0) // Default, Normal + return blendNormal(currentColor, vec4(newColor.rgb, newColor.a * blendFactor)); +#elif (#{#{layerGroup}#{i}BlendMode} == 1) // Multiply + return blendMultiply(currentColor, newColor * blendFactor); +#elif (#{#{layerGroup}#{i}BlendMode} == 2) // Add + return blendAdd(currentColor, newColor * blendFactor); +#elif (#{#{layerGroup}#{i}BlendMode} == 3) // Subtract + return blendSubtract(currentColor, newColor * blendFactor); +#elif (#{#{layerGroup}#{i}BlendMode} == 4) // Color + // Convert color to grayscale + float gray = (newColor.r + newColor.g + newColor.b) / 3.0; + + vec3 hsvCurrent = rgb2hsv(currentColor.rgb); + // Use gray from new color as value in hsv + vec3 hsvNew = vec3(hsvCurrent.x, hsvCurrent.y, gray); + vec3 rgbNew = hsv2rgb(hsvNew); + + vec4 color = blendNormal(currentColor, vec4(rgbNew, newColor.a * blendFactor)); + return color; +#endif +} + +#endfor +#endfor + + +#for id, layerGroup in layerGroups +#for i in 0..#{lastLayerIndex#{layerGroup}} + +vec4 performAdjustment#{layerGroup}#{i}(vec4 currentColor, const LayerAdjustment adjustment) { +#if (#{#{layerGroup}#{i}LayerAdjustmentType} == 0) // Default, None + return currentColor; +#elif (#{#{layerGroup}#{i}LayerAdjustmentType} == 1) // ChromaKey + if (distance(currentColor.rgb, adjustment.chromaKeyColor) <= adjustment.chromaKeyTolerance) { + return vec4(0,0,0,0); + } + else { + return currentColor; + } +#elif (#{#{layerGroup}#{i}LayerAdjustmentType} == 2) // TransferFunction + return currentColor; +#else + return currentColor; +#endif +} + +#endfor +#endfor + float calculateUntransformedHeight( vec2 uv, LevelWeights levelWeights, - const Layer HeightTextures[NUMLAYERS_HEIGHTMAP]) { + const Layer HeightLayers[NUMLAYERS_HEIGHTMAP]) { float height = 0; @@ -107,12 +209,13 @@ float calculateUntransformedHeight( levelWeights = getDefaultLevelWeights(); #endif // HEIGHTMAP_BLENDING_ENABLED - #for i in 0..#{lastLayerIndexHeightLayers} { - height = getTexVal(HeightTextures[#{i}].pile, levelWeights, uv).r; + vec4 colorSample = getSampleHeightLayers#{i}(uv, levelWeights, HeightLayers); + colorSample = performAdjustmentHeightLayers#{i}(colorSample, HeightLayers[#{i}].adjustment); + height = colorSample.r; - height = performLayerSettings(height, HeightTextures[#{i}].settings); + height = performLayerSettings(height, HeightLayers[#{i}].settings); } #endfor return height; @@ -121,7 +224,7 @@ float calculateUntransformedHeight( float calculateHeight( vec2 uv, LevelWeights levelWeights, - const Layer HeightTextures[NUMLAYERS_HEIGHTMAP]) { + const Layer HeightLayers[NUMLAYERS_HEIGHTMAP]) { float height = 0; @@ -134,11 +237,13 @@ float calculateHeight( #for i in 0..#{lastLayerIndexHeightLayers} { - float untransformedHeight = getTexVal(HeightTextures[#{i}].pile, levelWeights, uv).r; + vec4 colorSample = getSampleHeightLayers#{i}(uv, levelWeights, HeightLayers); + colorSample = performAdjustmentHeightLayers#{i}(colorSample, HeightLayers[#{i}].adjustment); + float untransformedHeight = colorSample.r; - float heightSample = getTransformedTexVal(HeightTextures[#{i}].depthTransform, untransformedHeight); + float heightSample = getTransformedTexVal(HeightLayers[#{i}].depthTransform, untransformedHeight); if (heightSample > -100000) { - heightSample = performLayerSettings(heightSample, HeightTextures[#{i}].settings); + heightSample = performLayerSettings(heightSample, HeightLayers[#{i}].settings); height = heightSample; } } @@ -162,45 +267,17 @@ vec4 calculateColor( #for i in 0..#{lastLayerIndexColorLayers} { - vec4 colorSample = getTexVal(ColorLayers[#{i}].pile, levelWeights, uv); - + vec4 colorSample = getSampleColorLayers#{i}(uv, levelWeights, ColorLayers); + colorSample = performAdjustmentColorLayers#{i}(colorSample, ColorLayers[#{i}].adjustment); colorSample = performLayerSettings(colorSample, ColorLayers[#{i}].settings); - color = blendOver(color, colorSample); + color = blendColorLayers#{i}(color, colorSample, 1.0); } #endfor return color; } -vec4 calculateGrayScale( - const vec4 currentColor, - const vec2 uv, - LevelWeights levelWeights, - const Layer GrayScaleLayers[NUMLAYERS_GRAYSCALETEXTURE]) { - - vec4 colorGrayScale = currentColor; - - // The shader compiler will remove unused code when variables are multiplied by - // a constant 0 -#if !GRAYSCALETEXTURE_BLENDING_ENABLED - levelWeights = getDefaultLevelWeights(); -#endif // GRAYSCALE_OVERLAY_BLENDING_ENABLED - - #for i in 0..#{lastLayerIndexGrayScaleLayers} - { - vec4 colorSample = getTexVal(GrayScaleLayers[#{i}].pile, levelWeights, uv); - - colorSample = vec4(colorSample.r, colorSample.r, colorSample.r, 1); - colorSample = performLayerSettings(colorSample, GrayScaleLayers[#{i}].settings); - - colorGrayScale = blendOver(colorGrayScale, colorSample); - } - #endfor - - return colorGrayScale; -} - float gridDots(vec2 uv, vec2 gridResolution){ vec2 uvVertexSpace = fract((gridResolution) * uv) + 0.5; @@ -223,7 +300,6 @@ float tileResolution(vec2 tileUV, const ChunkTile chunkTile){ return gridDots(uv, heightResolution); } - vec4 calculateNight( const vec4 currentColor, const vec2 uv, @@ -233,6 +309,7 @@ vec4 calculateNight( const vec3 lightDirectionCameraSpace) { vec4 nightColor = vec4(0,0,0,0); + vec4 color = currentColor; // The shader compiler will remove unused code when variables are multiplied by // a constant 0 @@ -240,23 +317,23 @@ vec4 calculateNight( levelWeights = getDefaultLevelWeights(); #endif // NIGHTTEXTURE_BLENDING_ENABLED - #for i in 0..#{lastLayerIndexNightLayers} - { - vec4 colorSample = getTexVal(NightLayers[#{i}].pile, levelWeights, uv); - colorSample = performLayerSettings(colorSample, NightLayers[#{i}].settings); - - nightColor = blendOver(nightColor, colorSample); - } - #endfor - - vec3 n = normalize(ellipsoidNormalCameraSpace); vec3 l = lightDirectionCameraSpace; - float cosineFactor = clamp(dot(l, normalize(n + 0.15 * l)) * 3 , 0, 1); - // Blend shaded color with base color - vec4 color = vec4(currentColor.rgb + (cosineFactor) * nightColor.xyz, currentColor.a); + #for i in 0..#{lastLayerIndexNightLayers} + { + vec4 colorSample = getSampleNightLayers#{i}(uv, levelWeights, NightLayers); + colorSample = performAdjustmentNightLayers#{i}(colorSample, NightLayers[#{i}].adjustment); + colorSample = performLayerSettings(colorSample, NightLayers[#{i}].settings); + + float adjustedAlpha = cosineFactor * colorSample.a; + // Filter to night side + vec4 newColor = vec4(cosineFactor * colorSample.xyz, adjustedAlpha); + + color = blendNightLayers#{i}(currentColor, newColor, adjustedAlpha); + } + #endfor return color; } @@ -282,7 +359,7 @@ vec4 calculateOverlay( const vec4 currentColor, const vec2 uv, LevelWeights levelWeights, - const Layer ColorOverlays[NUMLAYERS_OVERLAY]) { + const Layer Overlays[NUMLAYERS_OVERLAY]) { vec4 color = currentColor; @@ -292,67 +369,21 @@ vec4 calculateOverlay( levelWeights = getDefaultLevelWeights(); #endif // OVERLAY_BLENDING_ENABLED - #for i in 0..#{lastLayerIndexColorOverlays} + #for i in 0..#{lastLayerIndexOverlays} { - vec4 colorSample = getTexVal(ColorOverlays[#{i}].pile, levelWeights, uv); - colorSample = performLayerSettings(colorSample, ColorOverlays[#{i}].settings); + vec4 colorSample = getSampleOverlays#{i}(uv, levelWeights, Overlays); + colorSample = performAdjustmentOverlays#{i}(colorSample, Overlays[#{i}].adjustment); - color = blendOver(color, colorSample); + colorSample = performLayerSettings(colorSample, Overlays[#{i}].settings); + + color = blendNormal(color, colorSample); + color = blendOverlays#{i}(color, colorSample, 1.0); } #endfor return color; } -vec4 calculateGrayScaleOverlay( - const vec4 currentColor, - const vec2 uv, - LevelWeights levelWeights, - const Layer GrayScaleColorOverlays[NUMLAYERS_GRAYSCALE_OVERLAY]) { - - vec4 colorGrayScale = currentColor; - // HSV blending - vec3 hsvCurrent = rgb2hsv(currentColor.rgb); - vec4 value = vec4(0,0,0,1); - - // The shader compiler will remove unused code when variables are multiplied by - // a constant 0 -#if !GRAYSCALE_OVERLAY_BLENDING_ENABLED - levelWeights = getDefaultLevelWeights(); -#endif // GRAYSCALE_OVERLAY_BLENDING_ENABLED - - #for i in 0..#{lastLayerIndexGrayScaleColorOverlays} - { - vec4 colorSample = getTexVal(GrayScaleColorOverlays[#{i}].pile, levelWeights, uv); - - colorSample = vec4(colorSample.r, colorSample.r, colorSample.r, colorSample.g); - colorSample = performLayerSettings(colorSample, GrayScaleColorOverlays[#{i}].settings); - - colorGrayScale = blendOver(colorGrayScale, colorSample); - - float valueBlending = GrayScaleColorOverlays[#{i}].settings.valueBlending; - - hsvCurrent.z = colorGrayScale.r * valueBlending + hsvCurrent.z * (1 - valueBlending); - colorGrayScale.rgb = vec3(hsvCurrent.z); - } - #endfor - - vec3 hsvNew = vec3(hsvCurrent.x, hsvCurrent.y, hsvCurrent.z); - vec3 rgbNew = hsv2rgb(hsvNew); -/* - // HSL blending - vec3 hslCurrent = rgb2hsl(currentColor.rgb); - //hslCurrent.y = hslCurrent.z > 0.7 ? 0 : hslCurrent.y; - vec3 hslNew = vec3(hslCurrent.x, hslCurrent.y, colorGrayScale.r); - vec3 rgbNew = hsl2rgb(hslNew); -*/ - // No color blending, use grayscale - //vec3 rgbNew = colorGrayScale.rgb; - vec4 color = blendOver(currentColor, vec4(rgbNew, colorGrayScale.a)); - - return color; -} - vec4 calculateWater( const vec4 currentColor, const vec2 uv, @@ -372,11 +403,13 @@ vec4 calculateWater( #for i in 0..#{lastLayerIndexWaterMasks} { - vec4 colorSample = getTexVal(WaterMasks[#{i}].pile, levelWeights, uv); + vec4 colorSample = getSampleWaterMasks#{i}(uv, levelWeights, WaterMasks); + colorSample = performAdjustmentWaterMasks#{i}(colorSample, WaterMasks[#{i}].adjustment); - colorSample = performLayerSettings(colorSample, WaterMasks[#{i}].settings); + colorSample = performLayerSettingsAlpha(colorSample, WaterMasks[#{i}].settings); + colorSample.a = performLayerSettingsRGB(colorSample.a, WaterMasks[#{i}].settings); - waterColor = blendOver(waterColor, colorSample); + waterColor = blendWaterMasks#{i}(waterColor, colorSample, 1.0); } #endfor @@ -390,7 +423,7 @@ vec4 calculateWater( vec3 specularTotal = specularColor * cosineFactor * specularIntensity * waterColor.a; - //return blendOver(currentColor, waterColor); + //return blendNormal(currentColor, waterColor); return currentColor + vec4(specularTotal, 1); } diff --git a/modules/globebrowsing/shaders/tile.hglsl b/modules/globebrowsing/shaders/tile.hglsl index 9d5e1c79a8..bc93dfcf58 100644 --- a/modules/globebrowsing/shaders/tile.hglsl +++ b/modules/globebrowsing/shaders/tile.hglsl @@ -116,10 +116,19 @@ struct LayerSettings { float valueBlending; }; +struct LayerAdjustment { + vec3 chromaKeyColor; + float chromaKeyTolerance; +}; + struct Layer { ChunkTilePile pile; TileDepthTransform depthTransform; LayerSettings settings; + LayerAdjustment adjustment; + + // Other layer type properties stuff + vec3 color; }; struct LevelWeights { diff --git a/modules/globebrowsing/shaders/tilefragcolor.hglsl b/modules/globebrowsing/shaders/tilefragcolor.hglsl index 6cf772c073..e1dca0d4a9 100644 --- a/modules/globebrowsing/shaders/tilefragcolor.hglsl +++ b/modules/globebrowsing/shaders/tilefragcolor.hglsl @@ -37,22 +37,14 @@ uniform Layer ColorLayers[NUMLAYERS_COLORTEXTURE]; #endif // USE_COLORTEXTURE -#if USE_GRAYSCALETEXTURE -uniform Layer GrayScaleLayers[NUMLAYERS_GRAYSCALETEXTURE]; -#endif // USE_GRAYSCALETEXTURE - #if USE_NIGHTTEXTURE uniform Layer NightLayers[NUMLAYERS_NIGHTTEXTURE]; #endif // USE_NIGHTTEXTURE #if USE_OVERLAY -uniform Layer ColorOverlays[NUMLAYERS_OVERLAY]; +uniform Layer Overlays[NUMLAYERS_OVERLAY]; #endif // USE_OVERLAY -#if USE_GRAYSCALE_OVERLAY -uniform Layer GrayScaleColorOverlays[NUMLAYERS_GRAYSCALE_OVERLAY]; -#endif // USE_GRAYSCALE_OVERLAY - #if USE_WATERMASK uniform Layer WaterMasks[NUMLAYERS_WATERMASK]; #endif // USE_WATERMASK @@ -128,24 +120,6 @@ vec4 getTileFragColor(){ ColorLayers); #endif // USE_COLORTEXTURE -#if USE_GRAYSCALETEXTURE - color = calculateGrayScale( - color, - fs_uv, - levelWeights, - GrayScaleLayers); -#endif // USE_GRAYSCALETEXTURE - -#if USE_GRAYSCALE_OVERLAY - - color = calculateGrayScaleOverlay( - color, - fs_uv, - levelWeights, - GrayScaleColorOverlays); - -#endif // USE_COLORTEXTURE - #if USE_WATERMASK color = calculateWater( color, @@ -203,7 +177,7 @@ vec4 getTileFragColor(){ color, fs_uv, levelWeights, - ColorOverlays); + Overlays); #endif // USE_OVERLAY diff --git a/modules/globebrowsing/tile/asynctiledataprovider.cpp b/modules/globebrowsing/tile/asynctiledataprovider.cpp index 31ece2f257..ec4feedef3 100644 --- a/modules/globebrowsing/tile/asynctiledataprovider.cpp +++ b/modules/globebrowsing/tile/asynctiledataprovider.cpp @@ -47,10 +47,10 @@ AsyncTileDataProvider::AsyncTileDataProvider(const std::string& name, const std::shared_ptr rawTileDataReader) : _name(name) , _rawTileDataReader(rawTileDataReader) - , _concurrentJobManager( - std::make_shared>(1, 10)) + , _concurrentJobManager(LRUThreadPool(1, 10)) , _pboContainer(nullptr) , _resetMode(ResetMode::ShouldResetAllButRawTileDataReader) + , _shouldBeDeleted(false) { _globeBrowsingModule = OsEng.moduleEngine().module(); performReset(ResetRawTileDataReader::No); @@ -176,7 +176,6 @@ void AsyncTileDataProvider::updatePboUsage() { } void AsyncTileDataProvider::update() { - updatePboUsage(); endUnfinishedJobs(); // May reset @@ -203,8 +202,19 @@ void AsyncTileDataProvider::update() { } break; } - case ResetMode::ShouldNotReset: + case ResetMode::ShouldBeDeleted: { + // Clean all finished jobs + getRawTiles(); + // Only allow resetting if there are no jobs currently running + if (_enqueuedTileRequests.size() == 0) { + _shouldBeDeleted = true; + } break; + } + case ResetMode::ShouldNotReset: { + updatePboUsage(); + break; + } default: break; } @@ -219,6 +229,15 @@ void AsyncTileDataProvider::reset() { "'" + _name + "'"); } +void AsyncTileDataProvider::prepairToBeDeleted() { + _resetMode = ResetMode::ShouldBeDeleted; + endEnqueuedJobs(); +} + +bool AsyncTileDataProvider::shouldBeDeleted() { + return _shouldBeDeleted; +} + void AsyncTileDataProvider::performReset(ResetRawTileDataReader resetRawTileDataReader) { ghoul_assert(_enqueuedTileRequests.size() == 0, "No enqueued requests left"); diff --git a/modules/globebrowsing/tile/asynctiledataprovider.h b/modules/globebrowsing/tile/asynctiledataprovider.h index c84c4e5d92..d318eb3851 100644 --- a/modules/globebrowsing/tile/asynctiledataprovider.h +++ b/modules/globebrowsing/tile/asynctiledataprovider.h @@ -76,6 +76,9 @@ public: void update(); void reset(); + void prepairToBeDeleted(); + + bool shouldBeDeleted(); std::shared_ptr getRawTileDataReader() const; float noDataValueAsFloat() const; @@ -86,6 +89,7 @@ protected: enum class ResetMode { ShouldResetAll, ShouldResetAllButRawTileDataReader, + ShouldBeDeleted, ShouldNotReset }; @@ -121,6 +125,7 @@ private: std::set _enqueuedTileRequests; ResetMode _resetMode; + bool _shouldBeDeleted; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp index 8bb8f7edc1..45eaa90a8b 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp @@ -1,339 +1,403 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ -#ifdef GLOBEBROWSING_USE_GDAL - -#include - -#include -#include -#include -#include - -#include -#include // abspath -#include -#include -#include - -#include -#include -#include - -#include - -#include - -namespace { - const std::string _loggerCat = "GdalRawTileDataReader"; -} - -namespace openspace { -namespace globebrowsing { - -std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { - return os << pr.start.x << ", " << pr.start.y << " with size " << pr.numPixels.x << - ", " << pr.numPixels.y; -} - -GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath, - const TileTextureInitData& initData, - const std::string& baseDirectory, - RawTileDataReader::PerformPreprocessing preprocess) - : RawTileDataReader(initData, preprocess) - , _dataset(nullptr) -{ - _initDirectory = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory; - _datasetFilePath = filePath; - - { // Aquire lock - std::lock_guard lockGuard(_datasetLock); - initialize(); - } -} - -GdalRawTileDataReader::~GdalRawTileDataReader() { - std::lock_guard lockGuard(_datasetLock); - if (_dataset != nullptr) { - GDALClose(_dataset); - _dataset = nullptr; - } -} - -void GdalRawTileDataReader::reset() { - std::lock_guard lockGuard(_datasetLock); - _cached._maxLevel = -1; - if (_dataset != nullptr) { - GDALClose(_dataset); - _dataset = nullptr; - } - initialize(); -} - -int GdalRawTileDataReader::maxChunkLevel() const { - return _cached._maxLevel; -} - -float GdalRawTileDataReader::noDataValueAsFloat() const { - return _gdalDatasetMetaDataCached.noDataValue; -} - -int GdalRawTileDataReader::rasterXSize() const { - return _gdalDatasetMetaDataCached.rasterXSize; -} - -int GdalRawTileDataReader::rasterYSize() const { - return _gdalDatasetMetaDataCached.rasterYSize; -} - -float GdalRawTileDataReader::depthOffset() const { - return _gdalDatasetMetaDataCached.offset; -} - -float GdalRawTileDataReader::depthScale() const { - return _gdalDatasetMetaDataCached.scale; -} - -std::array GdalRawTileDataReader::getGeoTransform() const { - return _gdalDatasetMetaDataCached.padfTransform; -} - -IODescription GdalRawTileDataReader::getIODescription(const TileIndex& tileIndex) const { - IODescription io; - io.read.region = highestResPixelRegion(tileIndex); - - // write region starts in origin - io.write.region.start = PixelRegion::PixelCoordinate(0, 0); - io.write.region.numPixels = PixelRegion::PixelCoordinate( - _initData.dimensionsWithoutPadding().x, _initData.dimensionsWithoutPadding().y); - - io.read.overview = 0; - io.read.fullRegion = fullPixelRegion(); - // For correct sampling in dataset, we need to pad the texture tile - - PixelRegion scaledPadding = padding; - double scale = - io.read.region.numPixels.x / static_cast(io.write.region.numPixels.x); - scaledPadding.numPixels *= scale; - scaledPadding.start *= scale; - - io.read.region.pad(scaledPadding); - io.write.region.pad(padding); - io.write.region.start = PixelRegion::PixelCoordinate(0, 0); - - io.write.bytesPerLine = _initData.bytesPerLine(); - io.write.totalNumBytes = _initData.totalNumBytes(); - - ghoul_assert(io.write.region.numPixels.x == io.write.region.numPixels.y, ""); - ghoul_assert(io.write.region.numPixels.x == _initData.dimensionsWithPadding().x, ""); - - return io; -} - -void GdalRawTileDataReader::initialize() { - _dataset = openGdalDataset(_datasetFilePath); - - // Assume all raster bands have the same data type - _gdalDatasetMetaDataCached.rasterCount = _dataset->GetRasterCount(); - _gdalDatasetMetaDataCached.scale = _dataset->GetRasterBand(1)->GetScale(); - _gdalDatasetMetaDataCached.offset = _dataset->GetRasterBand(1)->GetOffset(); - _gdalDatasetMetaDataCached.rasterXSize = _dataset->GetRasterXSize(); - _gdalDatasetMetaDataCached.rasterYSize = _dataset->GetRasterYSize(); - _gdalDatasetMetaDataCached.noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue(); - _gdalDatasetMetaDataCached.dataType = tiledatatype::getGdalDataType(_initData.glType()); - - CPLErr err = _dataset->GetGeoTransform(&_gdalDatasetMetaDataCached.padfTransform[0]); - if (err == CE_Failure) { - _gdalDatasetMetaDataCached.padfTransform = RawTileDataReader::getGeoTransform(); - } - - _depthTransform = calculateTileDepthTransform(); - _cached._tileLevelDifference = - calculateTileLevelDifference(_initData.dimensionsWithoutPadding().x); - - int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - _cached._maxLevel = -_cached._tileLevelDifference; - if (numOverviews > 0) { - _cached._maxLevel += numOverviews - 1; - } -} - -void GdalRawTileDataReader::readImageData( - IODescription& io, RawTile::ReadError& worstError, char* imageDataDest) const { - - // Only read the minimum number of rasters - int nRastersToRead = std::min(_gdalDatasetMetaDataCached.rasterCount, - static_cast(_initData.nRasters())); - - switch (_initData.ghoulTextureFormat()) { - case ghoul::opengl::Texture::Format::Red: - case ghoul::opengl::Texture::Format::RG: - case ghoul::opengl::Texture::Format::RGB: - case ghoul::opengl::Texture::Format::RGBA: { - // Read the data (each rasterband is a separate channel) - for (int i = 0; i < nRastersToRead; i++) { - // The final destination pointer is offsetted by one datum byte size - // for every raster (or data channel, i.e. R in RGB) - char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); - - RawTile::ReadError err = repeatedRasterRead(i + 1, io, dataDestination); - - // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 - worstError = std::max(worstError, err); - } - break; - } - case ghoul::opengl::Texture::Format::BGR: { - // Read the data (each rasterband is a separate channel) - for (int i = 0; i < 3 && i < nRastersToRead; i++) { - // The final destination pointer is offsetted by one datum byte size - // for every raster (or data channel, i.e. R in RGB) - char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); - - RawTile::ReadError err = repeatedRasterRead(3 - i, io, dataDestination); - - // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 - worstError = std::max(worstError, err); - } - break; - } - case ghoul::opengl::Texture::Format::BGRA: { - for (int i = 0; i < 3 && i < nRastersToRead; i++) { - // The final destination pointer is offsetted by one datum byte size - // for every raster (or data channel, i.e. R in RGB) - char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); - - RawTile::ReadError err = repeatedRasterRead(3 - i, io, dataDestination); - - // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 - worstError = std::max(worstError, err); - } - if (nRastersToRead > 3) { // Alpha channel exists - // Last read is the alpha channel - char* dataDestination = imageDataDest + (3 * _initData.bytesPerDatum()); - RawTile::ReadError err = repeatedRasterRead(4, io, dataDestination); - - // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 - worstError = std::max(worstError, err); - } - break; - } - default: { - ghoul_assert(false, "Texture format not supported for tiles"); - break; - } - } -} - -RawTile::ReadError GdalRawTileDataReader::rasterRead( - int rasterBand, const IODescription& io, char* dataDestination) const -{ - ghoul_assert(io.read.region.isInside(io.read.fullRegion), "write region of bounds!"); - ghoul_assert( - io.write.region.start.x >= 0 && io.write.region.start.y >= 0, - "Invalid write region" - ); - - PixelRegion::PixelCoordinate end = io.write.region.end(); - size_t largestIndex = - (end.y - 1) * io.write.bytesPerLine + (end.x - 1) * _initData.bytesPerPixel(); - ghoul_assert(largestIndex <= io.write.totalNumBytes, "Invalid write region"); - - char* dataDest = dataDestination; - - // GDAL reads pixels top to bottom, but we want our pixels bottom to top. - // Therefore, we increment the destination pointer to the last line on in the - // buffer, and the we specify in the rasterIO call that we want negative line - // spacing. Doing this compensates the flipped Y axis - dataDest += (io.write.totalNumBytes - io.write.bytesPerLine); - - // handle requested write region. Note -= since flipped y axis - dataDest -= io.write.region.start.y * io.write.bytesPerLine; - dataDest += io.write.region.start.x * _initData.bytesPerPixel(); - - GDALRasterBand* gdalRasterBand = _dataset->GetRasterBand(rasterBand); - CPLErr readError = CE_Failure; - readError = gdalRasterBand->RasterIO( - GF_Read, - io.read.region.start.x, // Begin read x - io.read.region.start.y, // Begin read y - io.read.region.numPixels.x, // width to read x - io.read.region.numPixels.y, // width to read y - dataDest, // Where to put data - io.write.region.numPixels.x, // width to write x in destination - io.write.region.numPixels.y, // width to write y in destination - _gdalDatasetMetaDataCached.dataType, // Type - _initData.bytesPerPixel(), // Pixel spacing - -io.write.bytesPerLine // Line spacing - ); - - // Convert error to RawTile::ReadError - RawTile::ReadError error; - switch (readError) { - case CE_None: error = RawTile::ReadError::None; break; - case CE_Debug: error = RawTile::ReadError::Debug; break; - case CE_Warning: error = RawTile::ReadError::Warning; break; - case CE_Failure: error = RawTile::ReadError::Failure; break; - case CE_Fatal: error = RawTile::ReadError::Fatal; break; - default: error = RawTile::ReadError::Failure; break; - } - return error; -} - -GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath) { - GDALDataset* dataset = static_cast( - GDALOpen(filePath.c_str(), GA_ReadOnly)); - if (!dataset) { - using namespace ghoul::filesystem; - std::string correctedPath = FileSystem::ref().pathByAppendingComponent( - _initDirectory, filePath - ); - - dataset = static_cast(GDALOpen(correctedPath.c_str(), GA_ReadOnly)); - if (!dataset) { - throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath); - } - } - return dataset; -} - -int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) const { - GDALRasterBand* firstBand = _dataset->GetRasterBand(1); - GDALRasterBand* maxOverview; - int numOverviews = firstBand->GetOverviewCount(); - int sizeLevel0; - if (numOverviews <= 0) { // No overviews. Use first band. - maxOverview = firstBand; - } - else { // Pick the highest overview. - maxOverview = firstBand->GetOverview(numOverviews - 1); - } - sizeLevel0 = maxOverview->GetXSize(); - double diff = log2(minimumPixelSize) - log2(sizeLevel0); - return diff; -} - -} // namespace globebrowsing -} // namespace openspace - -#endif // GLOBEBROWSING_USE_GDAL +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ +#ifdef GLOBEBROWSING_USE_GDAL + +#include + +#include +#include +#include +#include + +#include +#include // abspath +#include +#include +#include + +#include +#include +#include + +#include + +#include + +namespace { + const std::string _loggerCat = "GdalRawTileDataReader"; +} + +namespace openspace { +namespace globebrowsing { + +std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { + return os << pr.start.x << ", " << pr.start.y << " with size " << pr.numPixels.x << + ", " << pr.numPixels.y; +} + +GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath, + const TileTextureInitData& initData, + const std::string& baseDirectory, + RawTileDataReader::PerformPreprocessing preprocess) + : RawTileDataReader(initData, preprocess) + , _dataset(nullptr) +{ + _initDirectory = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory; + _datasetFilePath = filePath; + + { // Aquire lock + std::lock_guard lockGuard(_datasetLock); + initialize(); + } +} + +GdalRawTileDataReader::~GdalRawTileDataReader() { + std::lock_guard lockGuard(_datasetLock); + if (_dataset != nullptr) { + GDALClose(_dataset); + _dataset = nullptr; + } +} + +void GdalRawTileDataReader::reset() { + std::lock_guard lockGuard(_datasetLock); + _cached._maxLevel = -1; + if (_dataset != nullptr) { + GDALClose(_dataset); + _dataset = nullptr; + } + initialize(); +} + +int GdalRawTileDataReader::maxChunkLevel() const { + return _cached._maxLevel; +} + +float GdalRawTileDataReader::noDataValueAsFloat() const { + return _gdalDatasetMetaDataCached.noDataValue; +} + +int GdalRawTileDataReader::rasterXSize() const { + return _gdalDatasetMetaDataCached.rasterXSize; +} + +int GdalRawTileDataReader::rasterYSize() const { + return _gdalDatasetMetaDataCached.rasterYSize; +} + +float GdalRawTileDataReader::depthOffset() const { + return _gdalDatasetMetaDataCached.offset; +} + +float GdalRawTileDataReader::depthScale() const { + return _gdalDatasetMetaDataCached.scale; +} + +std::array GdalRawTileDataReader::getGeoTransform() const { + return _gdalDatasetMetaDataCached.padfTransform; +} + +IODescription GdalRawTileDataReader::getIODescription(const TileIndex& tileIndex) const { + IODescription io; + io.read.region = highestResPixelRegion(tileIndex); + + // write region starts in origin + io.write.region.start = PixelRegion::PixelCoordinate(0, 0); + io.write.region.numPixels = PixelRegion::PixelCoordinate( + _initData.dimensionsWithoutPadding().x, _initData.dimensionsWithoutPadding().y); + + io.read.overview = 0; + io.read.fullRegion = fullPixelRegion(); + // For correct sampling in dataset, we need to pad the texture tile + + PixelRegion scaledPadding = padding; + double scale = + io.read.region.numPixels.x / static_cast(io.write.region.numPixels.x); + scaledPadding.numPixels *= scale; + scaledPadding.start *= scale; + + io.read.region.pad(scaledPadding); + io.write.region.pad(padding); + io.write.region.start = PixelRegion::PixelCoordinate(0, 0); + + io.write.bytesPerLine = _initData.bytesPerLine(); + io.write.totalNumBytes = _initData.totalNumBytes(); + + ghoul_assert(io.write.region.numPixels.x == io.write.region.numPixels.y, ""); + ghoul_assert(io.write.region.numPixels.x == _initData.dimensionsWithPadding().x, ""); + + return io; +} + +void GdalRawTileDataReader::initialize() { + if (_datasetFilePath.empty()) { + throw ghoul::RuntimeError("File path must not be empty"); + } + _dataset = openGdalDataset(_datasetFilePath); + + // Assume all raster bands have the same data type + _gdalDatasetMetaDataCached.rasterCount = _dataset->GetRasterCount(); + _gdalDatasetMetaDataCached.scale = _dataset->GetRasterBand(1)->GetScale(); + _gdalDatasetMetaDataCached.offset = _dataset->GetRasterBand(1)->GetOffset(); + _gdalDatasetMetaDataCached.rasterXSize = _dataset->GetRasterXSize(); + _gdalDatasetMetaDataCached.rasterYSize = _dataset->GetRasterYSize(); + _gdalDatasetMetaDataCached.noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue(); + _gdalDatasetMetaDataCached.dataType = tiledatatype::getGdalDataType(_initData.glType()); + + CPLErr err = _dataset->GetGeoTransform(&_gdalDatasetMetaDataCached.padfTransform[0]); + if (err == CE_Failure) { + _gdalDatasetMetaDataCached.padfTransform = RawTileDataReader::getGeoTransform(); + } + + _depthTransform = calculateTileDepthTransform(); + _cached._tileLevelDifference = + calculateTileLevelDifference(_initData.dimensionsWithoutPadding().x); + + int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); + _cached._maxLevel = -_cached._tileLevelDifference; + if (numOverviews > 0) { + _cached._maxLevel += numOverviews - 1; + } + _cached._maxLevel = std::max(_cached._maxLevel, 2); +} + +void GdalRawTileDataReader::readImageData( + IODescription& io, RawTile::ReadError& worstError, char* imageDataDest) const { + + // Only read the minimum number of rasters + int nRastersToRead = std::min(_gdalDatasetMetaDataCached.rasterCount, + static_cast(_initData.nRasters())); + + switch (_initData.ghoulTextureFormat()) { + case ghoul::opengl::Texture::Format::Red: + if (nRastersToRead == 1) { // One channel + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + _initData.bytesPerDatum(); + + RawTile::ReadError err = repeatedRasterRead(1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + break; + case ghoul::opengl::Texture::Format::RG: + case ghoul::opengl::Texture::Format::RGB: + case ghoul::opengl::Texture::Format::RGBA: { + if (nRastersToRead == 1) { // Grayscale + for (int i = 0; i < 3; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + else if (nRastersToRead == 2) { // Grayscale + alpha + for (int i = 0; i < 3; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + // Last read is the alpha channel + char* dataDestination = imageDataDest + (3 * _initData.bytesPerDatum()); + RawTile::ReadError err = repeatedRasterRead(2, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + else { // Three or more rasters + for (int i = 0; i < nRastersToRead; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(i + 1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + break; + } + case ghoul::opengl::Texture::Format::BGR: + case ghoul::opengl::Texture::Format::BGRA: { + if (nRastersToRead == 1) { // Grayscale + for (int i = 0; i < 3; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + else if (nRastersToRead == 2) { // Grayscale + alpha + for (int i = 0; i < 3; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + // Last read is the alpha channel + char* dataDestination = imageDataDest + (3 * _initData.bytesPerDatum()); + RawTile::ReadError err = repeatedRasterRead(2, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + else { // Three or more rasters + for (int i = 0; i < 3 && i < nRastersToRead; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageDataDest + (i * _initData.bytesPerDatum()); + + RawTile::ReadError err = repeatedRasterRead(3 - i, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + if (nRastersToRead > 3) { // Alpha channel exists + // Last read is the alpha channel + char* dataDestination = imageDataDest + (3 * _initData.bytesPerDatum()); + RawTile::ReadError err = repeatedRasterRead(4, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + break; + } + default: { + ghoul_assert(false, "Texture format not supported for tiles"); + break; + } + } +} + +RawTile::ReadError GdalRawTileDataReader::rasterRead( + int rasterBand, const IODescription& io, char* dataDestination) const +{ + ghoul_assert(io.read.region.isInside(io.read.fullRegion), "write region of bounds!"); + ghoul_assert( + io.write.region.start.x >= 0 && io.write.region.start.y >= 0, + "Invalid write region" + ); + + PixelRegion::PixelCoordinate end = io.write.region.end(); + size_t largestIndex = + (end.y - 1) * io.write.bytesPerLine + (end.x - 1) * _initData.bytesPerPixel(); + ghoul_assert(largestIndex <= io.write.totalNumBytes, "Invalid write region"); + + char* dataDest = dataDestination; + + // GDAL reads pixels top to bottom, but we want our pixels bottom to top. + // Therefore, we increment the destination pointer to the last line on in the + // buffer, and the we specify in the rasterIO call that we want negative line + // spacing. Doing this compensates the flipped Y axis + dataDest += (io.write.totalNumBytes - io.write.bytesPerLine); + + // handle requested write region. Note -= since flipped y axis + dataDest -= io.write.region.start.y * io.write.bytesPerLine; + dataDest += io.write.region.start.x * _initData.bytesPerPixel(); + + GDALRasterBand* gdalRasterBand = _dataset->GetRasterBand(rasterBand); + CPLErr readError = CE_Failure; + readError = gdalRasterBand->RasterIO( + GF_Read, + io.read.region.start.x, // Begin read x + io.read.region.start.y, // Begin read y + io.read.region.numPixels.x, // width to read x + io.read.region.numPixels.y, // width to read y + dataDest, // Where to put data + io.write.region.numPixels.x, // width to write x in destination + io.write.region.numPixels.y, // width to write y in destination + _gdalDatasetMetaDataCached.dataType, // Type + _initData.bytesPerPixel(), // Pixel spacing + -io.write.bytesPerLine // Line spacing + ); + + // Convert error to RawTile::ReadError + RawTile::ReadError error; + switch (readError) { + case CE_None: error = RawTile::ReadError::None; break; + case CE_Debug: error = RawTile::ReadError::Debug; break; + case CE_Warning: error = RawTile::ReadError::Warning; break; + case CE_Failure: error = RawTile::ReadError::Failure; break; + case CE_Fatal: error = RawTile::ReadError::Fatal; break; + default: error = RawTile::ReadError::Failure; break; + } + return error; +} + +GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath) { + GDALDataset* dataset = static_cast( + GDALOpen(filePath.c_str(), GA_ReadOnly)); + if (!dataset) { + using namespace ghoul::filesystem; + std::string correctedPath = FileSystem::ref().pathByAppendingComponent( + _initDirectory, filePath + ); + + dataset = static_cast(GDALOpen(correctedPath.c_str(), GA_ReadOnly)); + if (!dataset) { + throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath); + } + } + return dataset; +} + +int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) const { + GDALRasterBand* firstBand = _dataset->GetRasterBand(1); + GDALRasterBand* maxOverview; + int numOverviews = firstBand->GetOverviewCount(); + if (numOverviews <= 0) { // No overviews. Use first band. + maxOverview = firstBand; + } + else { // Pick the highest overview. + maxOverview = firstBand->GetOverview(numOverviews - 1); + } + int sizeLevel0 = maxOverview->GetXSize(); + double diff = log2(minimumPixelSize) - log2(sizeLevel0); + return diff; +} + +} // namespace globebrowsing +} // namespace openspace + +#endif // GLOBEBROWSING_USE_GDAL \ No newline at end of file diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp index a2f9e000b6..b88fb167ed 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp @@ -330,6 +330,8 @@ std::shared_ptr RawTileDataReader::getTileMetaData( noDataValues[raster] = noDataValueAsFloat(); } + bool allIsMissing = true; + for (int y = 0; y < region.numPixels.y; ++y) { size_t yi = (region.numPixels.y - 1 - y) * bytesPerLine; size_t i = 0; @@ -340,7 +342,9 @@ std::shared_ptr RawTileDataReader::getTileMetaData( _initData.glType(), &(rawTile->imageData[yi + i]) ); - if (val != noDataValue && val == val) { + if (val != noDataValue && + val == val) + { preprocessData->maxValues[raster] = std::max( val, preprocessData->maxValues[raster] @@ -349,14 +353,21 @@ std::shared_ptr RawTileDataReader::getTileMetaData( val, preprocessData->minValues[raster] ); + allIsMissing = false; } else { preprocessData->hasMissingData[raster] = true; + float& floatToRewrite = reinterpret_cast(rawTile->imageData[yi + i]); + floatToRewrite = -FLT_MAX; } i += _initData.bytesPerDatum(); } } } + + if (allIsMissing) { + rawTile->error = RawTile::ReadError::Failure; + } return std::shared_ptr(preprocessData); } diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp deleted file mode 100644 index eb2d003bf8..0000000000 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace { - const char* KeyPerformPreProcessing = "PerformPreProcessing"; - const char* KeyTilePixelSize = "TilePixelSize"; - const char* KeyFilePath = "FilePath"; - const char* KeyBasePath = "BasePath"; - const char* KeyPreCacheLevel = "PreCacheLevel"; -} - -namespace openspace { -namespace globebrowsing { -namespace tileprovider { - -CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) - : TileProvider(dictionary) -{ - _tileCache = OsEng.moduleEngine().module()->tileCache(); - _name = "Name unspecified"; - dictionary.getValue("Name", _name); - std::string _loggerCat = "CachingTileProvider : " + _name; - - // 1. Get required Keys - std::string filePath; - if (!dictionary.getValue(KeyFilePath, filePath)) { - throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); - } - - layergroupid::ID layerGroupID; - if (!dictionary.getValue("LayerGroupID", layerGroupID)) { - ghoul_assert(false, "Unknown layer group id"); - } - - // 2. Initialize default values for any optional Keys - // getValue does not work for integers - double pixelSize = 0.0; - int tilePixelSize = 0; - if (dictionary.getValue(KeyTilePixelSize, pixelSize)) { - LDEBUG("Default pixel size overridden: " << pixelSize); - tilePixelSize = static_cast(pixelSize); - } - - TileTextureInitData initData(LayerManager::getTileTextureInitData( - layerGroupID, tilePixelSize)); - - bool performPreProcessing = - LayerManager::shouldPerformPreProcessingOnLayergroup(layerGroupID); - if (dictionary.getValue(KeyPerformPreProcessing, performPreProcessing)) { - LDEBUG("Default PerformPreProcessing overridden: " << performPreProcessing); - } - RawTileDataReader::PerformPreprocessing preprocess = - performPreProcessing ? RawTileDataReader::PerformPreprocessing::Yes : - RawTileDataReader::PerformPreprocessing::No; - - std::string basePath; - dictionary.getValue(KeyBasePath, basePath); - - // Initialize instance variables -#ifdef GLOBEBROWSING_USE_GDAL - auto tileDataset = std::make_shared(filePath, initData, - basePath, preprocess); -#else // GLOBEBROWSING_USE_GDAL - auto tileDataset = std::make_shared(filePath, initData, - preprocess); -#endif // GLOBEBROWSING_USE_GDAL - - _asyncTextureDataProvider = std::make_shared(_name, tileDataset); - - if (dictionary.hasKeyAndValue(KeyPreCacheLevel)) { - int preCacheLevel = static_cast(dictionary.value(KeyPreCacheLevel)); - LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'"); - for (int level = 0; level <= preCacheLevel; ++level) { - for (int x = 0; x <= level * 2; ++x) { - for (int y = 0; y <= level; ++y) { - _asyncTextureDataProvider->enqueueTileIO({ x, y, level }); - } - } - } - } -} - -CachingTileProvider::CachingTileProvider( - std::shared_ptr tileReader) - : _asyncTextureDataProvider(tileReader) -{ } - -CachingTileProvider::~CachingTileProvider() -{ } - -void CachingTileProvider::update() { - _asyncTextureDataProvider->update(); - initTexturesFromLoadedData(); -} - -void CachingTileProvider::reset() { - _tileCache->clear(); - _asyncTextureDataProvider->reset(); -} - -int CachingTileProvider::maxLevel() { - return _asyncTextureDataProvider->getRawTileDataReader()->maxChunkLevel(); -} - -Tile CachingTileProvider::getTile(const TileIndex& tileIndex) { - if (tileIndex.level > maxLevel()) { - return Tile(nullptr, nullptr, Tile::Status::OutOfRange); - } - - cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; - - Tile tile = _tileCache->get(key); - - if (tile.texture() == nullptr) { - _asyncTextureDataProvider->enqueueTileIO(tileIndex); - } - - return tile; -} - -float CachingTileProvider::noDataValueAsFloat() { - return _asyncTextureDataProvider->noDataValueAsFloat(); -} - -void CachingTileProvider::initTexturesFromLoadedData() { - std::shared_ptr rawTile = _asyncTextureDataProvider->popFinishedRawTile(); - if (rawTile) { - cache::ProviderTileKey key = { rawTile->tileIndex, uniqueIdentifier() }; - ghoul_assert(!_tileCache->exist(key), "Tile must not be existing in cache"); - _tileCache->createTileAndPut(key, rawTile); - } -} - -Tile::Status CachingTileProvider::getTileStatus(const TileIndex& tileIndex) { - auto rawTileDataReader = _asyncTextureDataProvider->getRawTileDataReader(); - if (tileIndex.level > rawTileDataReader->maxChunkLevel()) { - return Tile::Status::OutOfRange; - } - - cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; - - return _tileCache->get(key).status(); -} - -TileDepthTransform CachingTileProvider::depthTransform() { - return _asyncTextureDataProvider->getRawTileDataReader()->getDepthTransform(); -} - -} // namespace tileprovider -} // namespace globebrowsing -} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp new file mode 100644 index 0000000000..e763c7e5b7 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.cpp @@ -0,0 +1,255 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace { + const char* KeyPerformPreProcessing = "PerformPreProcessing"; + const char* KeyTilePixelSize = "TilePixelSize"; + const char* KeyFilePath = "FilePath"; + const char* KeyBasePath = "BasePath"; + const char* KeyPreCacheLevel = "PreCacheLevel"; +} + +namespace openspace { +namespace globebrowsing { +namespace tileprovider { + +DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary) + : TileProvider(dictionary) + , _filePath("filePath", "File Path", "") + , _tilePixelSize("tilePixelSize", "Tile Pixel Size", 32, 32, 1024) + , _preCacheLevel(0) +{ + _tileCache = OsEng.moduleEngine().module()->tileCache(); + _name = "Name unspecified"; + dictionary.getValue("Name", _name); + std::string _loggerCat = "DefaultTileProvider : " + _name; + + // 1. Get required Keys + std::string filePath; + dictionary.getValue(KeyFilePath, filePath); + //filePath = absPath(filePath); + _filePath.setValue(filePath); + + if (!dictionary.getValue("LayerGroupID", _layerGroupID)) { + ghoul_assert(false, "Unknown layer group id"); + } + + // 2. Initialize default values for any optional Keys + // getValue does not work for integers + double pixelSize = 0.0; + int tilePixelSize = 0; + if (dictionary.getValue(KeyTilePixelSize, pixelSize)) { + LDEBUG("Default pixel size overridden: " << pixelSize); + tilePixelSize = pixelSize; + } + TileTextureInitData initData(LayerManager::getTileTextureInitData( + _layerGroupID, tilePixelSize)); + _tilePixelSize.setValue(initData.dimensionsWithoutPadding().x); + + _performPreProcessing = + LayerManager::shouldPerformPreProcessingOnLayergroup(_layerGroupID); + if (dictionary.getValue(KeyPerformPreProcessing, _performPreProcessing)) { + LDEBUG("Default PerformPreProcessing overridden: " << _performPreProcessing); + } + + if (dictionary.hasKeyAndValue(KeyPreCacheLevel)) { + _preCacheLevel = static_cast(dictionary.value(KeyPreCacheLevel)); + } + + dictionary.getValue(KeyBasePath, _basePath); + + initAsyncTileDataReader(initData); + + // Properties + addProperty(_filePath); + addProperty(_tilePixelSize); +} + +DefaultTileProvider::DefaultTileProvider( + std::shared_ptr tileReader) + : _asyncTextureDataProvider(tileReader) + , _filePath("filePath", "File Path", "") + , _tilePixelSize("tilePixelSize", "Tile Pixel Size", 32, 32, 1024) +{ } + +DefaultTileProvider::~DefaultTileProvider() +{ } + +void DefaultTileProvider::update() { + if (_asyncTextureDataProvider) { + _asyncTextureDataProvider->update(); + initTexturesFromLoadedData(); + if (_asyncTextureDataProvider->shouldBeDeleted()) { + _asyncTextureDataProvider = nullptr; + TileTextureInitData initData(LayerManager::getTileTextureInitData( + _layerGroupID, _tilePixelSize)); + initAsyncTileDataReader(initData); + } + } +} + +void DefaultTileProvider::reset() { + _tileCache->clear(); + if (_asyncTextureDataProvider) { + _asyncTextureDataProvider->prepairToBeDeleted(); + } + else { + TileTextureInitData initData(LayerManager::getTileTextureInitData( + _layerGroupID, _tilePixelSize)); + initAsyncTileDataReader(initData); + } +} + +int DefaultTileProvider::maxLevel() { + if (_asyncTextureDataProvider) { + return _asyncTextureDataProvider->getRawTileDataReader()->maxChunkLevel(); + } + else { + // Current theoretical maximum based on the number of hashes that are possible + // to uniquely identify a tile. See ProviderTileHasher in memoryawaretilecache.h + return 22; + } +} + +Tile DefaultTileProvider::getTile(const TileIndex& tileIndex) { + if (_asyncTextureDataProvider) { + if (tileIndex.level > maxLevel()) { + return Tile(nullptr, nullptr, Tile::Status::OutOfRange); + } + + cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; + + Tile tile = _tileCache->get(key); + + if (tile.texture() == nullptr) { + _asyncTextureDataProvider->enqueueTileIO(tileIndex); + } + + return tile; + } + else { + return Tile(nullptr, nullptr, Tile::Status::Unavailable); + } +} + +float DefaultTileProvider::noDataValueAsFloat() { + if (_asyncTextureDataProvider) { + return _asyncTextureDataProvider->noDataValueAsFloat(); + } + else { + return std::numeric_limits::min(); + } +} + +void DefaultTileProvider::initTexturesFromLoadedData() { + if (_asyncTextureDataProvider) { + std::shared_ptr rawTile = _asyncTextureDataProvider->popFinishedRawTile(); + if (rawTile) { + cache::ProviderTileKey key = { rawTile->tileIndex, uniqueIdentifier() }; + ghoul_assert(!_tileCache->exist(key), "Tile must not be existing in cache"); + _tileCache->createTileAndPut(key, rawTile); + } + } +} + +void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData) { + std::string _loggerCat = "DefaultTileProvider : " + _name; + + RawTileDataReader* tileDataReader = nullptr; + + RawTileDataReader::PerformPreprocessing preprocess = + _performPreProcessing ? RawTileDataReader::PerformPreprocessing::Yes : + RawTileDataReader::PerformPreprocessing::No; + + // Initialize instance variables +#ifdef GLOBEBROWSING_USE_GDAL + auto tileDataset = std::make_shared(_filePath, initData, + _basePath, preprocess); +#else // GLOBEBROWSING_USE_GDAL + auto tileDataset = std::make_shared(_filePath, initData, + preprocess); +#endif // GLOBEBROWSING_USE_GDAL + + _asyncTextureDataProvider = std::make_shared(_name, tileDataset); + + if (_preCacheLevel > -1) { + LDEBUG("Precaching '" << _filePath << "' with level '" << _preCacheLevel << "'"); + for (int level = 0; level <= _preCacheLevel; ++level) { + for (int x = 0; x <= level * 2; ++x) { + for (int y = 0; y <= level; ++y) { + _asyncTextureDataProvider->enqueueTileIO({ x, y, level }); + } + } + } + } +} + +Tile::Status DefaultTileProvider::getTileStatus(const TileIndex& tileIndex) { + if (_asyncTextureDataProvider) { + auto rawTileDataReader = _asyncTextureDataProvider->getRawTileDataReader(); + if (tileIndex.level > rawTileDataReader->maxChunkLevel()) { + return Tile::Status::OutOfRange; + } + + cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; + + return _tileCache->get(key).status(); + } + else { + return Tile::Status::Unavailable; + } +} + +TileDepthTransform DefaultTileProvider::depthTransform() { + if (_asyncTextureDataProvider) { + return _asyncTextureDataProvider->getRawTileDataReader()->getDepthTransform(); + } + else { + return { 1.0f, 0.0f }; + } +} + +} // namespace tileprovider +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.h similarity index 86% rename from modules/globebrowsing/tile/tileprovider/cachingtileprovider.h rename to modules/globebrowsing/tile/tileprovider/defaulttileprovider.h index 6fd5c0fa03..bf2928dd37 100644 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/defaulttileprovider.h @@ -28,6 +28,9 @@ #include #include +#include +#include + namespace openspace { class PixelBuffer; @@ -43,12 +46,12 @@ namespace tileprovider { * Provides tiles loaded by AsyncTileDataProvider and * caches them in memory using LRU caching */ -class CachingTileProvider : public TileProvider { +class DefaultTileProvider : public TileProvider { public: - CachingTileProvider(const ghoul::Dictionary& dictionary); - CachingTileProvider(std::shared_ptr tileReader); + DefaultTileProvider(const ghoul::Dictionary& dictionary); + DefaultTileProvider(std::shared_ptr tileReader); - virtual ~CachingTileProvider() override; + virtual ~DefaultTileProvider() override; /** * \returns a Tile with status OK iff it exists in in-memory @@ -73,9 +76,18 @@ private: */ void initTexturesFromLoadedData(); + void initAsyncTileDataReader(TileTextureInitData initData); + std::shared_ptr _asyncTextureDataProvider; cache::MemoryAwareTileCache* _tileCache; + + properties::StringProperty _filePath; + properties::IntProperty _tilePixelSize; + layergroupid::GroupID _layerGroupID; + std::string _basePath; + int _preCacheLevel; + bool _performPreProcessing; }; } // namespace tileprovider diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp index 8c16349993..0cca078164 100644 --- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp @@ -22,6 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#if 0 + #include #include #include @@ -112,3 +114,5 @@ TileProvider* PresentationSlideProvider::slideProvider() { } // namespace tileprovider } // namespace globebrowsing } // namespace openspace + +#endif diff --git a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp deleted file mode 100644 index 944c4594ed..0000000000 --- a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace { - const char* _loggerCat = "ProjectionTileProvider"; - - const char* keyGeometry = "Geometry"; - const char* keyProjection = "Projection"; - const char* keyMeridianShift = "Textures.MeridianShift"; - const char* keyColorTexture = "Textures.Color"; - const char* keyHeightTexture = "Textures.Height"; - - const char* keyRadius = "Geometry.Radius"; - const char* keyShading = "PerformShading"; - const char* _mainFrame = "GALACTIC"; -} - -namespace openspace { -namespace globebrowsing { -namespace tileprovider { - -/* -documentation::Documentation ProjectionTileProvider::Documentation() { - using namespace openspace::documentation; - return { - "Renderable Planet Projection", - "newhorizons_renderable_planetprojection", - { - { - "Type", - new StringEqualVerifier("RenderablePlanetProjection"), - "", - Optional::No - }, - { - keyGeometry, - new ReferencingVerifier("space_geometry_planet"), - "The geometry that is used for rendering this planet.", - Optional::No - }, - { - keyProjection, - new ReferencingVerifier("newhorizons_projectioncomponent"), - "Contains information about projecting onto this planet.", - Optional::No - }, - { - keyMeridianShift, - new BoolVerifier, - "Determines whether the meridian of the planet should be shifted by 180 " - "degrees. The default value is 'false'", - Optional::Yes - }, - { - keyColorTexture, - new StringVerifier, - "The path to the base color texture that is used on the planet prior to " - "any image projection. The path can use tokens of the form '${...}' or " - "be specified relative to the directory of the mod file.", - Optional::No - }, - { - keyHeightTexture, - new StringVerifier, - "The path to the height map texture that is used on the planet. The path " - "can use tokens of the form '${...}' or be specified relative to the " - "directory of the mod file. If no height map is specified the planet " - "does not use a height field.", - Optional::Yes - } - } - }; -} -*/ - -ProjectionTileProvider::ProjectionTileProvider(const ghoul::Dictionary& dictionary) - : _fboProgramObject(nullptr) - , _capture(false) - , _defaultTile(Tile::TileUnavailable) -{ - - ghoul::Dictionary geometryDictionary; - bool success = dictionary.getValue( - keyGeometry, geometryDictionary); - if (success) { - geometryDictionary.setValue(SceneGraphNode::KeyName, "TestGeometry"); - using planetgeometry::PlanetGeometry; - _geometry = std::unique_ptr( - PlanetGeometry::createFromDictionary(geometryDictionary) - ); - } - - _projectionComponent.initialize(dictionary.value(keyProjection)); - - - addPropertySubOwner(_geometry.get()); - addPropertySubOwner(_projectionComponent); -} - -ProjectionTileProvider::~ProjectionTileProvider(){ - -} - -bool ProjectionTileProvider::initialize() { - bool completeSuccess = true; - completeSuccess &= TileProvider::initialize(); - - _fboProgramObject = ghoul::opengl::ProgramObject::Build("fboPassProgram", - "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_vs.glsl", - "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_fs.glsl" - ); - - completeSuccess &= _projectionComponent.initializeGL(); - completeSuccess &= _geometry->initialize(nullptr); - - if (completeSuccess) { - //completeSuccess &= auxiliaryRendertarget(); - // SCREEN-QUAD - const GLfloat size = 1.f; - const GLfloat w = 1.f; - const GLfloat vertex_data[] = { - -size, -size, 0.f, w, 0.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - -size, size, 0.f, w, 0.f, 1.f, - -size, -size, 0.f, w, 0.f, 0.f, - size, -size, 0.f, w, 1.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - }; - - glGenVertexArrays(1, &_quad); - glBindVertexArray(_quad); - glGenBuffers(1, &_vertexPositionBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(0)); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(sizeof(GLfloat) * 4)); - - glBindVertexArray(0); - } - - return completeSuccess; -} - -bool ProjectionTileProvider::deinitialize() { - _projectionComponent.deinitialize(); - _geometry = nullptr; - - glDeleteVertexArrays(1, &_quad); - glDeleteBuffers(1, &_vertexPositionBuffer); - - _fboProgramObject = nullptr; - - return true; -} - -void ProjectionTileProvider::update() { - // Update - if (_fboProgramObject->isDirty()) { - _fboProgramObject->rebuildFromFile(); - } - - _projectionComponent.update(); - - _time = Time::ref().j2000Seconds(); - _capture = false; - - if (openspace::ImageSequencer::ref().isReady()){ - openspace::ImageSequencer::ref().updateSequencer(_time); - if (_projectionComponent.doesPerformProjection()) { - _capture = openspace::ImageSequencer::ref().getImagePaths( - _imageTimes, - _projectionComponent.projecteeId(), - _projectionComponent.instrumentId() - ); - } - } - - _stateMatrix = glm::dmat3(1.0); - - - - - - - - - - - - - - - // Projection - - if (_projectionComponent.needsClearProjection()) - _projectionComponent.clearAllProjections(); - - _camScaling = glm::vec2(1.0);// data.camera.scaling(); - _up = glm::vec3(0,1,0);// data.camera.lookUpVectorCameraSpace(); - - if (_capture && _projectionComponent.doesPerformProjection()) { - for (const Image& img : _imageTimes) { - attitudeParameters(img.timeRange.start); - imageProjectGPU(_projectionComponent.loadProjectionTexture(img.path)); - } - _capture = false; - } - attitudeParameters(_time); - _imageTimes.clear(); - -} - -void ProjectionTileProvider::reset() { -} - -int ProjectionTileProvider::maxLevel() { - return 3; -} - -Tile ProjectionTileProvider::getTile(const TileIndex& tileIndex) { - _projectionComponent.projectionTexture(); -} - -float ProjectionTileProvider::noDataValueAsFloat() { - -} - -Tile ProjectionTileProvider::getDefaultTile() { - -} - -Tile::Status ProjectionTileProvider::getTileStatus(const TileIndex& tileIndex) { - return Tile::Status::OK; -} - -TileDepthTransform ProjectionTileProvider::depthTransform() { - -} - -void ProjectionTileProvider::attitudeParameters(double time) { - // precomputations for shader - _instrumentMatrix = SpiceManager::ref().positionTransformMatrix( - _projectionComponent.instrumentId(), _mainFrame, time - ); - - _transform = glm::mat4(1); - //90 deg rotation w.r.t spice req. - glm::mat4 rot = glm::rotate( - _transform, - static_cast(M_PI_2), - glm::vec3(1, 0, 0) - ); - glm::mat4 roty = glm::rotate( - _transform, - static_cast(M_PI_2), - glm::vec3(0, -1, 0) - ); - - _transform = glm::mat4(_stateMatrix); - - glm::dvec3 bs; - try { - SpiceManager::FieldOfViewResult res = SpiceManager::ref().fieldOfView(_projectionComponent.instrumentId()); - bs = std::move(res.boresightVector); - } - catch (const SpiceManager::SpiceException& e) { - LERRORC(e.component, e.what()); - return; - } - - double lightTime; - glm::dvec3 p = SpiceManager::ref().targetPosition( - _projectionComponent.projectorId(), - _projectionComponent.projecteeId(), - _mainFrame, - _projectionComponent.aberration(), - time, - lightTime - ); - psc position = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); - - //change to KM and add psc camera scaling. - position[3] += (3 + _camScaling[1]); - //position[3] += 3; - glm::vec3 cpos = position.vec3(); - - float distance = glm::length(cpos); - float radius = 1185000.0f; - - _projectorMatrix = _projectionComponent.computeProjectorMatrix( - cpos, - bs, - _up, - _instrumentMatrix, - _projectionComponent.fieldOfViewY(), - _projectionComponent.aspectRatio(), - distance - radius, - distance + radius, - _boresight - ); -} - -void ProjectionTileProvider::imageProjectGPU( - std::shared_ptr projectionTexture) -{ - _projectionComponent.imageProjectBegin(); - - _fboProgramObject->activate(); - - ghoul::opengl::TextureUnit unitFbo; - unitFbo.activate(); - projectionTexture->bind(); - _fboProgramObject->setUniform("projectionTexture", unitFbo); - - _fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix); - _fboProgramObject->setUniform("ModelTransform" , _transform); - _fboProgramObject->setUniform("_scaling" , _camScaling); - _fboProgramObject->setUniform("boresight" , _boresight); - - if (_geometry->hasProperty("radius")){ - ghoul::any r = _geometry->property("radius")->get(); - if (glm::vec4* radius = ghoul::any_cast(&r)){ - _fboProgramObject->setUniform("_radius", radius); - } - }else{ - LERROR("Geometry object needs to provide radius"); - } - if (_geometry->hasProperty("segments")){ - ghoul::any s = _geometry->property("segments")->get(); - if (int* segments = ghoul::any_cast(&s)){ - _fboProgramObject->setUniform("_segments", segments[0]); - } - }else{ - LERROR("Geometry object needs to provide segment count"); - } - - glBindVertexArray(_quad); - glDrawArrays(GL_TRIANGLES, 0, 6); - _fboProgramObject->deactivate(); - - _projectionComponent.imageProjectEnd(); -} - - -} // namespace tileprovider -} // namespace globebrowsing -} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp index 413784a698..38efce4ba6 100644 --- a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp @@ -38,18 +38,21 @@ namespace tileprovider { SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary) : _tile(nullptr, nullptr, Tile::Status::Unavailable) + , _filePath("filePath", "File Path", "") { // Required input - if (!dictionary.getValue(KeyFilePath, _imagePath)) { - throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); - } + std::string filePath; + dictionary.getValue(KeyFilePath, filePath); + _filePath.setValue(filePath); + + addProperty(_filePath); reset(); } SingleImageProvider::SingleImageProvider(const std::string& imagePath) - : _imagePath(imagePath) - , _tile(nullptr, nullptr, Tile::Status::Unavailable) + : _tile(nullptr, nullptr, Tile::Status::Unavailable) + , _filePath("filePath", "File Path", imagePath) { reset(); } @@ -74,12 +77,15 @@ void SingleImageProvider::update() { } void SingleImageProvider::reset() { - _tileTexture = ghoul::io::TextureReader::ref().loadTexture(_imagePath); + if (_filePath.value().empty()) { + return; + } + _tileTexture = ghoul::io::TextureReader::ref().loadTexture(_filePath); Tile::Status tileStatus = _tileTexture ? Tile::Status::OK : Tile::Status::IOError; if (!_tileTexture) { throw std::runtime_error(std::string("Unable to load texture '") - + _imagePath + "'"); + + _filePath.value() + "'"); } _tileTexture->uploadTexture(); diff --git a/modules/globebrowsing/tile/tileprovider/singleimageprovider.h b/modules/globebrowsing/tile/tileprovider/singleimageprovider.h index e4f0ac7f34..d15aaa77f7 100644 --- a/modules/globebrowsing/tile/tileprovider/singleimageprovider.h +++ b/modules/globebrowsing/tile/tileprovider/singleimageprovider.h @@ -27,6 +27,8 @@ #include +#include + namespace openspace { namespace globebrowsing { namespace tileprovider { @@ -46,8 +48,9 @@ public: private: std::unique_ptr _tileTexture; - std::string _imagePath; Tile _tile; + + properties::StringProperty _filePath; }; } // namespace tileprovider diff --git a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp index 042d06c9cb..fb12db848a 100644 --- a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp @@ -47,7 +47,7 @@ namespace { } SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary) - : TextTileProvider(LayerManager::getTileTextureInitData(layergroupid::ID::ColorLayers)) + : TextTileProvider(LayerManager::getTileTextureInitData(layergroupid::GroupID::ColorLayers)) , _backgroundTile(Tile::TileUnavailable) { @@ -55,9 +55,7 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di _font = OsEng.fontManager().font("Mono", _fontSize); glm::dvec3 radii(1,1,1); - if (!dictionary.getValue(KeyRadii, radii)) { - throw std::runtime_error("Must define key '" + std::string(KeyRadii) + "'"); - } + dictionary.getValue(KeyRadii, radii); _ellipsoid = Ellipsoid(radii); } diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index e7a622e5ac..1c3666e0eb 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -26,7 +26,7 @@ #include -#include +#include #include #include @@ -57,47 +57,73 @@ const char* TemporalTileProvider::TemporalXMLTags::TIME_RESOLUTION = const char* TemporalTileProvider::TemporalXMLTags::TIME_FORMAT = "OpenSpaceTimeIdFormat"; TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) - : _initDict(dictionary) + : _initDict(dictionary) + , _filePath("filePath", "File Path", "") + , _successfulInitialization(false) { - if (!dictionary.getValue(KeyFilePath, _datasetFile)) { - throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); + std::string filePath; + dictionary.getValue(KeyFilePath, filePath); + try { + filePath = absPath(filePath); + } + catch (const std::runtime_error& e) { + // File path was not a path to a file but a GDAL config or empty + } + + _filePath.setValue(filePath); + addProperty(_filePath); + + if (readFilePath()) { + const bool hasStart = dictionary.hasKeyAndValue(KeyPreCacheStartTime); + const bool hasEnd = dictionary.hasKeyAndValue(KeyPreCacheEndTime); + if (hasStart && hasEnd) { + const std::string start = dictionary.value(KeyPreCacheStartTime); + const std::string end = dictionary.value(KeyPreCacheEndTime); + std::vector