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