Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Bock
2017-07-10 15:08:08 -04:00
105 changed files with 2745 additions and 1783 deletions
+1 -1
View File
@@ -285,7 +285,7 @@ void MainWindow::initialize() {
_syncWidget->setSceneFiles(_sceneFiles);
// Load all available configuration files
QString configurationDirectory = QString::fromStdString(absPath("${SGCT}"));
QString configurationDirectory = QString::fromStdString(absPath("${CONFIG}"));
d = QDir(configurationDirectory);
d.setFilter(QDir::Files);
list = d.entryInfoList();
+30 -16
View File
@@ -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 = {
@@ -13,10 +13,5 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/ESRI_Imagery_World_2d</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
</GDAL_WMS>
@@ -3,19 +3,7 @@
<ServerUrl>http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d?</ServerUrl>
<TiledGroupName>GCS_Elevation</TiledGroupName>
</Service>
<DataWindow>
<UpperLeftX>-180.0</UpperLeftX>
<UpperLeftY>90.0</UpperLeftY>
<LowerRightX>180.0</LowerRightX>
<LowerRightY>-90.0</LowerRightY>
<YOrigin>bottom</YOrigin>
</DataWindow>
<Timeout>2</Timeout>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/TERRAIN</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
</GDAL_WMS>
@@ -20,10 +20,4 @@
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/Coastlines</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
</GDAL_WMS>
@@ -17,11 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/GIBS_Aqua_MODIS_true</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
@@ -17,11 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>4</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/MODIS_Terra_Brightness_Temp_Band31_Day</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
@@ -17,11 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/MODIS_Terra_CorrectedReflectance_TrueColor</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
@@ -17,13 +17,7 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>4</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/MODIS_Water_Mask</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
</GDAL_WMS>
@@ -17,12 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>4</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/Reference_Features</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
@@ -17,12 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>4</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/Reference_Labels</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
@@ -17,12 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>4</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/VIIRS_CityLights_2012</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
@@ -17,12 +17,6 @@
<BlockSizeY>512</BlockSizeY>
<BandsCount>3</BandsCount>
<MaxConnections>5</MaxConnections>
<Cache>
<Path>./GDAL_Cache/VIIRS_SNPP_CorrectedReflectance_TrueColor</Path>
<Depth>4</Depth>
<Extension>.jpg</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
@@ -3,5 +3,4 @@
<ServerUrl>http://a${server_num}.ortho.tiles.virtualearth.net/tiles/a${quadkey}.jpeg?g=90</ServerUrl>
</Service>
<MaxConnections>4</MaxConnections>
<Cache/>
</GDAL_WMS>
@@ -32,15 +32,8 @@ return {
Name = "Callisto Texture",
FilePath = "textures/callisto.jpg",
Enabled = true,
TilePixelSize = 112,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},
@@ -32,15 +32,8 @@ return {
Name = "Europa Texture",
FilePath = "textures/europa.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},
@@ -32,15 +32,8 @@ return {
Name = "Ganymede Texture",
FilePath = "textures/ganymede.jpg",
Enabled = true,
TilePixelSize = 112,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},
-6
View File
@@ -34,12 +34,6 @@ return {
Enabled = true,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},
@@ -45,12 +45,6 @@ return {
Enabled = true,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},
@@ -12,10 +12,6 @@
<BlockSizeX>256</BlockSizeX>
<BlockSizeY>256</BlockSizeY>
</DataWindow>
<Cache>
<Path>./GDAL_CTX_cache</Path>
<Depth>3</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
</GDAL_WMS>
@@ -10,10 +10,5 @@
<LowerRightY>-90.0</LowerRightY>
<YOrigin>bottom</YOrigin>
</DataWindow>
<Cache>
<Path>./GDAL_MOLA_cache</Path>
<Depth>3</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
</GDAL_WMS>
@@ -17,4 +17,6 @@
<BlockSizeY>256</BlockSizeY>
<BandsCount>2</BandsCount>
<MaxConnections>10</MaxConnections>
<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
</GDAL_WMS>
@@ -10,10 +10,5 @@
<LowerRightY>-90.0</LowerRightY>
<YOrigin>bottom</YOrigin>
</DataWindow>
<Cache>
<Path>./GDAL_MOLA_cache</Path>
<Depth>3</Depth>
<Extension>.png</Extension>
</Cache>
<OfflineMode>false</OfflineMode>
</GDAL_WMS>
+8 -106
View File
@@ -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",
},
]]
},
},
}
@@ -25,6 +25,7 @@
<TileCountY>1</TileCountY>
<YOrigin>top</YOrigin>
</DataWindow>
<Timeout>5</Timeout>
<BlockSizeX>512</BlockSizeX>
<BlockSizeY>512</BlockSizeY>
</GDAL_WMS>
+74
View File
@@ -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
}
}
}
@@ -61,13 +61,8 @@
<YOrigin>top</YOrigin>
</DataWindow>
<BlockSizeX>512</BlockSizeX>
<BlockSizeY>512</BlockSizeY>
<BlockSizeY>512</BlockSizeY>
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
<Cache>
<Path>./GDAL_Cache/OnMoonColor</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
</GDAL_WMS>
@@ -19,9 +19,4 @@
<UnsafeSSL>true</UnsafeSSL>
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
<Cache>
<Path>./GDAL_Cache/OnMoonHeight</Path>
<Depth>4</Depth>
<Extension>.png</Extension>
</Cache>
</GDAL_WMS>
+3 -24
View File
@@ -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 },
}
},
},
-7
View File
@@ -40,15 +40,8 @@ return {
Name = "Texture",
FilePath = "textures/neptune.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},
-7
View File
@@ -40,15 +40,8 @@ return {
Name = "Saturn Texture",
FilePath = "textures/saturn.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},
-7
View File
@@ -40,15 +40,8 @@ return {
Name = "Texture",
FilePath = "textures/uranus.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},
-7
View File
@@ -45,15 +45,8 @@ return {
Name = "Venus Texture",
FilePath = "textures/venus.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},
+11 -4
View File
@@ -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
+1
View File
@@ -70,6 +70,7 @@ public:
*/
Item popLRU();
size_t size() const;
size_t maximumCacheSize() const;
private:
void putWithoutCleaning(const KeyType& key, const ValueType& value);
+5
View File
@@ -120,6 +120,11 @@ size_t LRUCache<KeyType, ValueType, HasherType>::size() const {
return _itemMap.size();
}
template<typename KeyType, typename ValueType, typename HasherType>
size_t LRUCache<KeyType, ValueType, HasherType>::maximumCacheSize() const {
return _maximumCacheSize;
}
template<typename KeyType, typename ValueType, typename HasherType>
void LRUCache<KeyType, ValueType, HasherType>::putWithoutCleaning(const KeyType& key,
const ValueType& value)
+1 -1
View File
@@ -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);
}
}
@@ -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;
}
+84 -23
View File
@@ -28,7 +28,7 @@
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/other/distanceswitch.h>
#include <modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h>
#include <modules/globebrowsing/tile/tileprovider/cachingtileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/singleimageprovider.h>
#include <modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/temporaltileprovider.h>
@@ -37,10 +37,11 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/tile/tileprovider/presentationslideprovider.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/templatefactory.h>
@@ -48,6 +49,8 @@
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
#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<globebrowsing::cache::MemoryAwareTileCache>();
addPropertySubOwner(*_tileCache);
_tileCache = std::make_unique<globebrowsing::cache::MemoryAwareTileCache>();
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<Renderable>();
ghoul_assert(fRenderable, "Renderable factory was not created");
// Create factory for TileProviders
auto fTileProvider =
std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
ghoul_assert(fTileProvider, "TileProvider factory was not created");
// Register renderable class
fRenderable->registerClass<globebrowsing::RenderableGlobe>("RenderableGlobe");
// add Tile Provider factory
auto fTileProvider = std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
fTileProvider->registerClass<tileprovider::CachingTileProvider>("LRUCaching");
fTileProvider->registerClass<tileprovider::SingleImageProvider>("SingleImage");
// Register TileProvider classes
fTileProvider->registerClass<tileprovider::DefaultTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::DefaultTileLayer)]);
fTileProvider->registerClass<tileprovider::SingleImageProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::SingleImageTileLayer)]);
#ifdef GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TemporalTileProvider>("Temporal");
fTileProvider->registerClass<tileprovider::TemporalTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::TemporalTileLayer)]);
#endif // GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>("TileIndex");
fTileProvider->registerClass<tileprovider::SizeReferenceTileProvider>("SizeReference");
// Combining Tile Providers
fTileProvider->registerClass<tileprovider::TileProviderByLevel>("ByLevel");
fTileProvider->registerClass<tileprovider::TileProviderByIndex>("ByIndex");
fTileProvider->registerClass<tileprovider::PresentationSlideProvider>("PresentationSlides");
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::TileIndexTileLayer)]);
fTileProvider->registerClass<tileprovider::SizeReferenceTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::SizeReferenceTileLayer)]);
fTileProvider->registerClass<tileprovider::TileProviderByLevel>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::ByLevelTileLayer)]);
fTileProvider->registerClass<tileprovider::TileProviderByIndex>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(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
+10 -1
View File
@@ -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<globebrowsing::cache::MemoryAwareTileCache> _tileCache;
};
@@ -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 <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
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<RenderableGlobe*>(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<RenderableGlobe*>(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
@@ -178,6 +178,9 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const {
for (const std::shared_ptr<Layer>& 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();
}
+61 -19
View File
@@ -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<glm::vec2, 6> 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();
}
@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_GLOBEBROWSING___POINTGLOBE___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/scalarproperty.h>
#include <ghoul/opengl/ghoul_gl.h>
@@ -55,6 +56,9 @@ private:
GLuint _vertexBufferID;
GLuint _vaoID;
properties::FloatProperty _intensityClamp;
properties::FloatProperty _lightIntensity;
};
} // namespace globebrowsing
@@ -26,6 +26,7 @@
#include <modules/debugging/rendering/debugrenderer.h>
#include <modules/globebrowsing/globes/chunkedlodglobe.h>
#include <modules/globebrowsing/globes/pointglobe.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
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<ChunkedLodGlobe>(
*this, patchSegments, _layerManager);
//_pointGlobe = std::make_shared<PointGlobe>(*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<double>() / 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<ChunkedLodGlobe> RenderableGlobe::chunkedLodGlobe() const{
return _chunkedLodGlobe;
}
LayerManager* RenderableGlobe::layerManager() const {
return _layerManager.get();
}
const Ellipsoid& RenderableGlobe::ellipsoid() const{
return _ellipsoid;
}
@@ -37,6 +37,7 @@ namespace openspace {
namespace globebrowsing {
class ChunkedLodGlobe;
class PointGlobe;
class LayerManager;
/**
@@ -93,6 +94,7 @@ public:
// Getters
std::shared_ptr<ChunkedLodGlobe> 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
// <code>ChunkedLodGlobe</code> does not have to be rendered at far distances.
std::shared_ptr<ChunkedLodGlobe> _chunkedLodGlobe;
//std::shared_ptr<PointGlobe> _pointGlobe;
Ellipsoid _ellipsoid;
std::shared_ptr<LayerManager> _layerManager;
@@ -51,7 +51,7 @@ struct Job {
template<typename P>
class ConcurrentJobManager {
public:
ConcurrentJobManager(std::shared_ptr<ThreadPool> pool);
ConcurrentJobManager(ThreadPool pool);
void enqueueJob(std::shared_ptr<Job<P>> job);
@@ -63,8 +63,8 @@ public:
private:
ConcurrentQueue<std::shared_ptr<Job<P>>> _finishedJobs;
std::shared_ptr<ThreadPool> threadPool;
std::mutex _finishedJobsMutex;
ThreadPool threadPool;
};
} // namespace globebrowsing
@@ -34,13 +34,13 @@ template<typename P>
Job<P>::~Job() {}
template<typename P>
ConcurrentJobManager<P>::ConcurrentJobManager(std::shared_ptr<ThreadPool> pool)
ConcurrentJobManager<P>::ConcurrentJobManager(ThreadPool pool)
: threadPool(pool)
{ }
template<typename P>
void ConcurrentJobManager<P>::enqueueJob(std::shared_ptr<Job<P>> job) {
threadPool->enqueue([this, job]() {
threadPool.enqueue([this, job]() {
job->execute();
std::lock_guard<std::mutex> lock(_finishedJobsMutex);
_finishedJobs.push(job);
@@ -49,7 +49,7 @@ void ConcurrentJobManager<P>::enqueueJob(std::shared_ptr<Job<P>> job) {
template<typename P>
void ConcurrentJobManager<P>::clearEnqueuedJobs() {
threadPool->clearTasks();
threadPool.clearTasks();
}
template<typename P>
+14 -27
View File
@@ -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<double>() / 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> 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> renderable : _renderables) {
renderable->update(data);
}
}
void DistanceSwitch::addSwitchValue(std::shared_ptr<Renderable> 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> renderable) {
_renderables.push_back(renderable);
_maxDistances.push_back(maxDistance);
}
} // namespace globebrowsing
+5 -8
View File
@@ -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> renderable, double maxDistance);
* Adds a new renderable
*/
void addSwitchValue(std::shared_ptr<Renderable> renderable);
private:
std::vector<std::shared_ptr<Renderable>> _renderables;
std::vector<double> _maxDistances;
double _objectScale;
};
} // namespace globebrowsing
@@ -33,6 +33,7 @@
#include <queue>
#include <thread>
#include <vector>
#include <atomic>
// Implementatin based on http://progsch.net/wordpress/?p=81
@@ -65,6 +66,7 @@ template<typename KeyType>
class LRUThreadPool {
public:
LRUThreadPool(size_t numThreads, size_t queueSize);
LRUThreadPool(const LRUThreadPool& toCopy);
~LRUThreadPool();
void enqueue(std::function<void()> f, KeyType key);
@@ -68,11 +68,18 @@ LRUThreadPool<KeyType>::LRUThreadPool(size_t numThreads, size_t queueSize)
}
}
template<typename KeyType>
LRUThreadPool<KeyType>::LRUThreadPool(const LRUThreadPool& toCopy)
: LRUThreadPool(toCopy._workers.size(), toCopy._queuedTasks.maximumCacheSize())
{ }
// the destructor joins all threads
template<typename KeyType>
LRUThreadPool<KeyType>::~LRUThreadPool() {
// Stop all threads
_stop = true;
{
std::unique_lock<std::mutex> lock(_queueMutex);
_stop = true;
}
_condition.notify_all();
// join them
@@ -43,7 +43,7 @@ namespace globebrowsing {
template<typename P, typename KeyType>
class PrioritizingConcurrentJobManager {
public:
PrioritizingConcurrentJobManager(std::shared_ptr<LRUThreadPool<KeyType>> pool);
PrioritizingConcurrentJobManager(LRUThreadPool<KeyType> pool);
/**
* Enqueues a job which is identified using a given key
@@ -85,9 +85,10 @@ public:
private:
ConcurrentQueue<std::shared_ptr<Job<P>>> _finishedJobs;
/// An LRU thread pool is used since the jobs can be bumped and hence prioritized.
std::shared_ptr<LRUThreadPool<KeyType>> _threadPool;
std::mutex _finishedJobsMutex;
/// An LRU thread pool is used since the jobs can be bumped and hence prioritized.
LRUThreadPool<KeyType> _threadPool;
};
} // namespace globebrowsing
@@ -29,7 +29,7 @@ namespace globebrowsing {
template<typename P, typename KeyType>
PrioritizingConcurrentJobManager<P, KeyType>::PrioritizingConcurrentJobManager(
std::shared_ptr<LRUThreadPool<KeyType>> pool)
LRUThreadPool<KeyType> pool)
: _threadPool(pool)
{ }
@@ -37,7 +37,7 @@ template<typename P, typename KeyType>
void PrioritizingConcurrentJobManager<P, KeyType>::enqueueJob(std::shared_ptr<Job<P>> job,
KeyType key)
{
_threadPool->enqueue([this, job]() {
_threadPool.enqueue([this, job]() {
job->execute();
std::lock_guard<std::mutex> lock(_finishedJobsMutex);
_finishedJobs.push(job);
@@ -47,23 +47,23 @@ void PrioritizingConcurrentJobManager<P, KeyType>::enqueueJob(std::shared_ptr<Jo
template<typename P, typename KeyType>
std::vector<KeyType>
PrioritizingConcurrentJobManager<P, KeyType>::getKeysToUnfinishedJobs() {
return _threadPool->getUnqueuedTasksKeys();
return _threadPool.getUnqueuedTasksKeys();
}
template<typename P, typename KeyType>
std::vector<KeyType>
PrioritizingConcurrentJobManager<P, KeyType>::getKeysToEnqueuedJobs() {
return _threadPool->getQueuedTasksKeys();
return _threadPool.getQueuedTasksKeys();
}
template<typename P, typename KeyType>
bool PrioritizingConcurrentJobManager<P, KeyType>::touch(KeyType key) {
return _threadPool->touch(key);
return _threadPool.touch(key);
}
template<typename P, typename KeyType>
void PrioritizingConcurrentJobManager<P, KeyType>::clearEnqueuedJobs() {
_threadPool->clearEnqueuedTasks();
_threadPool.clearEnqueuedTasks();
}
template<typename P, typename KeyType>
+8 -1
View File
@@ -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<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
// join them
+2
View File
@@ -31,6 +31,7 @@
#include <queue>
#include <thread>
#include <vector>
#include <atomic>
// 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<void()> f);
@@ -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,
@@ -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() {
@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__
#include <modules/globebrowsing/rendering/gpu/gpuchunktilepile.h>
#include <modules/globebrowsing/rendering/gpu/gpulayeradjustment.h>
#include <modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h>
#include <openspace/util/gpudata.h>
#include <string>
@@ -73,6 +74,10 @@ public:
private:
GPUChunkTilePile gpuChunkTilePile;
GPULayerRenderSettings gpuRenderSettings;
GPULayerAdjustment gpuLayerAdjustment;
// Adjustment layer stuff
GPUData<glm::vec3> gpuColor;
};
} // namespace globebrowsing
@@ -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 <modules/globebrowsing/rendering/gpu/gpulayeradjustment.h>
#include <modules/globebrowsing/rendering/layer/layeradjustment.h>
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
@@ -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 <openspace/util/gpudata.h>
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<glm::vec3> gpuChromaKeyColor;
GPUData<float> gpuChromaKeyTolerance;
};
} // namespace globebrowsing
} // namespace openspace
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__
+257 -21
View File
@@ -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<std::string>(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>(
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<int>(typeID));
_type = static_cast<layergroupid::TypeID>(_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<int>(blendModeID));
}
else {
_blendModeOption.setValue(static_cast<int>(layergroupid::BlendModeID::Normal));
}
// On change callbacks definitions
_enabled.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_reset.onChange([&](){
if (_tileProvider) {
_tileProvider->reset();
}
});
_typeOption.onChange([&](){
removeVisibleProperties();
_type = static_cast<layergroupid::TypeID>(_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<layergroupid::BlendModeID>(_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<void(void)> 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<std::string>("Type")) {
const std::string typeString = initDict.value<std::string>("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<std::string>(keyName)) {
std::string name;
tileProviderInitDict.getValue(keyName, name);
LDEBUG("Initializing tile provider for layer: '" + name + "'");
}
_tileProvider = std::shared_ptr<tileprovider::TileProvider>(
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
+42 -13
View File
@@ -25,14 +25,17 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/rendering/layer/layeradjustment.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <modules/globebrowsing/rendering/layer/layerrendersettings.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/properties/vectorproperty.h>
namespace openspace {
namespace globebrowsing {
@@ -41,29 +44,55 @@ namespace tileprovider {
class TileProvider;
}
/**
* Simple struct which is used to enable/disable <code>TileProvider</code>
* 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<void(void)> 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::TileProvider> _tileProvider;
OtherTypesProperties _otherTypesProperties;
LayerRenderSettings _renderSettings;
};
LayerAdjustment _layerAdjustment;
const layergroupid::GroupID _layerGroupId;
std::function<void(void)> _onChangeCallback;
};
} // namespace globebrowsing
} // namespace openspace
@@ -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 <modules/globebrowsing/rendering/layer/layeradjustment.h>
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<int>(layergroupid::AdjustmentTypeID::None));
_type = static_cast<layergroupid::AdjustmentTypeID>(_typeOption.value());
_typeOption.onChange([&](){
removeVisibleProperties();
_type = static_cast<layergroupid::AdjustmentTypeID>(_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<int>(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<void(void)> callback) {
_onChangeCallback = std::move(callback);
}
} // namespace globebrowsing
} // namespace openspace
@@ -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 <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <openspace/properties/propertyowner.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/opengl/texture.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <openspace/properties/scalarproperty.h>
#include <memory>
#include <unordered_map>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/vectorproperty.h>
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<void(void)> callback);
private:
TileProvider* slideProvider();
void addVisibleProperties();
void removeVisibleProperties();
properties::OptionProperty _typeOption;
layergroupid::AdjustmentTypeID _type;
TileIndex _tileIndex;
properties::IntProperty _slideIndex;
std::vector<std::unique_ptr<TileProvider>> _slideProviders;
std::unique_ptr<TileProvider> _defaultProvider;
std::function<void(void)> _onChangeCallback;
};
} // namespace tileprovider
} // namespace globebrowsing
} // namespace openspace
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__
@@ -26,35 +26,36 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
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<ghoul::Dictionary>(dictKey);
try {
_layers.push_back(std::make_shared<Layer>(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<std::string>("Name")) {
LERROR("'Name' must be specified for layer.");
return;
}
auto layer = std::make_shared<Layer>(_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<std::shared_ptr<Layer>>::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<std::shared_ptr<Layer>>& LayerGroup::layers() const {
return _layers;
}
@@ -81,10 +118,10 @@ int LayerGroup::pileSize() const{
}
void LayerGroup::onChange(std::function<void(void)> callback) {
_onChangeCallback = callback;
_levelBlendingEnabled.onChange(callback);
_onChangeCallback = std::move(callback);
_levelBlendingEnabled.onChange(_onChangeCallback);
for (const std::shared_ptr<Layer>& layer : _layers) {
layer->onChange(callback);
layer->onChange(_onChangeCallback);
}
}
@@ -47,12 +47,15 @@ namespace tileprovider {
* Convenience class for dealing with multiple <code>Layer</code>s.
*/
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<std::shared_ptr<Layer>>& layers() const;
@@ -67,6 +70,7 @@ struct LayerGroup : public properties::PropertyOwner {
void onChange(std::function<void(void)> callback);
private:
const layergroupid::GroupID _groupId;
std::vector<std::shared_ptr<Layer>> _layers;
std::vector<std::shared_ptr<Layer>> _activeLayers;
@@ -25,32 +25,133 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__
#include <string>
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<TypeID>(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<layergroupid::GroupID>(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<layergroupid::AdjustmentTypeID>(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<layergroupid::BlendModeID>(i);
}
}
return BlendModeID::Normal;
}
} // namespace layergroupid
} // namespace globebrowsing
} // namespace openspace
@@ -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<LayerGroup>(
static_cast<layergroupid::GroupID>(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<ghoul::Dictionary>(groupName);
std::vector<std::string> layerGroupNamesInDict = layerGroupsDict.keys();
_layerGroups.push_back(
std::make_shared<LayerGroup>(
static_cast<layergroupid::ID>(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<ghoul::Dictionary>(groupName);
_layerGroups[static_cast<int>(groupId)] =
std::make_shared<LayerGroup>(groupId, layerGroupDict);
}
else {
LWARNING("Unknown layer group: " + groupName);
}
}
for (const std::shared_ptr<LayerGroup>& 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;
}
}
@@ -28,6 +28,7 @@
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/tile/tiletextureinitdata.h>
@@ -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<void(void)> callback);
private:
@@ -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
@@ -28,6 +28,7 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/triggerproperty.h>
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
@@ -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<std::shared_ptr<Layer>> layers = layerGroup.activeLayers();
layeredTextureInfo.lastLayerIdx = layerGroup.activeLayers().size() - 1;
layeredTextureInfo.layerBlendingEnabled = layerGroup.layerBlendingEnabled();
for (const std::shared_ptr<Layer>& 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<int>(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<int>(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<int>(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++) {
@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <array>
#include <string>
@@ -63,6 +64,9 @@ public:
struct LayerGroupPreprocessingData {
int lastLayerIdx;
bool layerBlendingEnabled;
std::vector<layergroupid::TypeID> layerType;
std::vector<layergroupid::BlendModeID> blendMode;
std::vector<layergroupid::AdjustmentTypeID> layerAdjustmentType;
bool operator==(const LayerGroupPreprocessingData& other) const;
};
+129 -1
View File
@@ -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 =
"<OpenSpaceTemporalGDALDataset>" ..
"<OpenSpaceTimeStart>" .. startDate .. "</OpenSpaceTimeStart>" ..
"<OpenSpaceTimeEnd>" .. endDate .. "</OpenSpaceTimeEnd>" ..
"<OpenSpaceTimeResolution>" .. timeResolution .. "</OpenSpaceTimeResolution>" ..
"<OpenSpaceTimeIdFormat>YYYY-MM-DD</OpenSpaceTimeIdFormat>" ..
openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format) ..
"</OpenSpaceTemporalGDALDataset>"
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 =
"<GDAL_WMS>" ..
"<Service name=\"TMS\">" ..
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
layerName .. "/default/" .. date .. "/" .. resolution ..
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
"</Service>" ..
"<DataWindow>" ..
"<UpperLeftX>-180.0</UpperLeftX>" ..
"<UpperLeftY>90</UpperLeftY>" ..
"<LowerRightX>396.0</LowerRightX>" ..
"<LowerRightY>-198</LowerRightY>" ..
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
"<TileCountX>2</TileCountX>" ..
"<TileCountY>1</TileCountY>" ..
"<YOrigin>top</YOrigin>" ..
"</DataWindow>" ..
"<Projection>EPSG:4326</Projection>" ..
"<BlockSizeX>512</BlockSizeX>" ..
"<BlockSizeY>512</BlockSizeY>" ..
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
"<UnsafeSSL>true</UnsafeSSL>" ..
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
"</GDAL_WMS>"
return gdalWmsTemplate
end
+1 -1
View File
@@ -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 =
@@ -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;
}
@@ -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);
}
@@ -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);
}
+9
View File
@@ -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 {
@@ -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
@@ -47,10 +47,10 @@ AsyncTileDataProvider::AsyncTileDataProvider(const std::string& name,
const std::shared_ptr<RawTileDataReader> rawTileDataReader)
: _name(name)
, _rawTileDataReader(rawTileDataReader)
, _concurrentJobManager(
std::make_shared<LRUThreadPool<TileIndex::TileHashKey>>(1, 10))
, _concurrentJobManager(LRUThreadPool<TileIndex::TileHashKey>(1, 10))
, _pboContainer(nullptr)
, _resetMode(ResetMode::ShouldResetAllButRawTileDataReader)
, _shouldBeDeleted(false)
{
_globeBrowsingModule = OsEng.moduleEngine().module<GlobeBrowsingModule>();
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");
@@ -76,6 +76,9 @@ public:
void update();
void reset();
void prepairToBeDeleted();
bool shouldBeDeleted();
std::shared_ptr<RawTileDataReader> getRawTileDataReader() const;
float noDataValueAsFloat() const;
@@ -86,6 +89,7 @@ protected:
enum class ResetMode {
ShouldResetAll,
ShouldResetAllButRawTileDataReader,
ShouldBeDeleted,
ShouldNotReset
};
@@ -121,6 +125,7 @@ private:
std::set<TileIndex::TileHashKey> _enqueuedTileRequests;
ResetMode _resetMode;
bool _shouldBeDeleted;
};
} // namespace globebrowsing
@@ -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 <modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/geometry/geodeticpatch.h>
#include <modules/globebrowsing/geometry/angle.h>
#include <modules/globebrowsing/tile/rawtiledatareader/tiledatatype.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h> // abspath
#include <ghoul/filesystem/file.h>
#include <ghoul/misc/assert.h>
#include <ghoul/misc/dictionary.h>
#include <ogr_featurestyle.h>
#include <ogr_spatialref.h>
#include <cpl_virtualmem.h>
#include <gdal_priv.h>
#include <algorithm>
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<std::mutex> lockGuard(_datasetLock);
initialize();
}
}
GdalRawTileDataReader::~GdalRawTileDataReader() {
std::lock_guard<std::mutex> lockGuard(_datasetLock);
if (_dataset != nullptr) {
GDALClose(_dataset);
_dataset = nullptr;
}
}
void GdalRawTileDataReader::reset() {
std::lock_guard<std::mutex> 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<double, 6> 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<double>(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<int>(_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<GDALDataset*>(
GDALOpen(filePath.c_str(), GA_ReadOnly));
if (!dataset) {
using namespace ghoul::filesystem;
std::string correctedPath = FileSystem::ref().pathByAppendingComponent(
_initDirectory, filePath
);
dataset = static_cast<GDALDataset*>(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 <modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h>
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/geometry/geodeticpatch.h>
#include <modules/globebrowsing/geometry/angle.h>
#include <modules/globebrowsing/tile/rawtiledatareader/tiledatatype.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h> // abspath
#include <ghoul/filesystem/file.h>
#include <ghoul/misc/assert.h>
#include <ghoul/misc/dictionary.h>
#include <ogr_featurestyle.h>
#include <ogr_spatialref.h>
#include <cpl_virtualmem.h>
#include <gdal_priv.h>
#include <algorithm>
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<std::mutex> lockGuard(_datasetLock);
initialize();
}
}
GdalRawTileDataReader::~GdalRawTileDataReader() {
std::lock_guard<std::mutex> lockGuard(_datasetLock);
if (_dataset != nullptr) {
GDALClose(_dataset);
_dataset = nullptr;
}
}
void GdalRawTileDataReader::reset() {
std::lock_guard<std::mutex> 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<double, 6> 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<double>(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<int>(_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<GDALDataset*>(
GDALOpen(filePath.c_str(), GA_ReadOnly));
if (!dataset) {
using namespace ghoul::filesystem;
std::string correctedPath = FileSystem::ref().pathByAppendingComponent(
_initDirectory, filePath
);
dataset = static_cast<GDALDataset*>(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
@@ -330,6 +330,8 @@ std::shared_ptr<TileMetaData> 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<TileMetaData> 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<TileMetaData> RawTileDataReader::getTileMetaData(
val,
preprocessData->minValues[raster]
);
allIsMissing = false;
}
else {
preprocessData->hasMissingData[raster] = true;
float& floatToRewrite = reinterpret_cast<float&>(rawTile->imageData[yi + i]);
floatToRewrite = -FLT_MAX;
}
i += _initData.bytesPerDatum();
}
}
}
if (allIsMissing) {
rawTile->error = RawTile::ReadError::Failure;
}
return std::shared_ptr<TileMetaData>(preprocessData);
}
@@ -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 <modules/globebrowsing/tile/tileprovider/cachingtileprovider.h>
#include <modules/globebrowsing/cache/memoryawaretilecache.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/asynctiledataprovider.h>
#include <modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtile.h>
#include <modules/globebrowsing/tile/rawtiledatareader/iodescription.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/moduleengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/texture.h>
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<GlobeBrowsingModule>()->tileCache();
_name = "Name unspecified";
dictionary.getValue("Name", _name);
std::string _loggerCat = "CachingTileProvider : " + _name;
// 1. Get required Keys
std::string filePath;
if (!dictionary.getValue<std::string>(KeyFilePath, filePath)) {
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
}
layergroupid::ID layerGroupID;
if (!dictionary.getValue<layergroupid::ID>("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<double>(KeyTilePixelSize, pixelSize)) {
LDEBUG("Default pixel size overridden: " << pixelSize);
tilePixelSize = static_cast<int>(pixelSize);
}
TileTextureInitData initData(LayerManager::getTileTextureInitData(
layerGroupID, tilePixelSize));
bool performPreProcessing =
LayerManager::shouldPerformPreProcessingOnLayergroup(layerGroupID);
if (dictionary.getValue<bool>(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<GdalRawTileDataReader>(filePath, initData,
basePath, preprocess);
#else // GLOBEBROWSING_USE_GDAL
auto tileDataset = std::make_shared<SimpleRawTileDataReader>(filePath, initData,
preprocess);
#endif // GLOBEBROWSING_USE_GDAL
_asyncTextureDataProvider = std::make_shared<AsyncTileDataProvider>(_name, tileDataset);
if (dictionary.hasKeyAndValue<double>(KeyPreCacheLevel)) {
int preCacheLevel = static_cast<int>(dictionary.value<double>(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<AsyncTileDataProvider> 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> 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
@@ -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 <modules/globebrowsing/tile/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/cache/memoryawaretilecache.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/asynctiledataprovider.h>
#include <modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h>
#include <modules/globebrowsing/tile/rawtile.h>
#include <modules/globebrowsing/tile/rawtiledatareader/iodescription.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/moduleengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/texture.h>
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<GlobeBrowsingModule>()->tileCache();
_name = "Name unspecified";
dictionary.getValue("Name", _name);
std::string _loggerCat = "DefaultTileProvider : " + _name;
// 1. Get required Keys
std::string filePath;
dictionary.getValue<std::string>(KeyFilePath, filePath);
//filePath = absPath(filePath);
_filePath.setValue(filePath);
if (!dictionary.getValue<layergroupid::GroupID>("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<double>(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<bool>(KeyPerformPreProcessing, _performPreProcessing)) {
LDEBUG("Default PerformPreProcessing overridden: " << _performPreProcessing);
}
if (dictionary.hasKeyAndValue<double>(KeyPreCacheLevel)) {
_preCacheLevel = static_cast<int>(dictionary.value<double>(KeyPreCacheLevel));
}
dictionary.getValue(KeyBasePath, _basePath);
initAsyncTileDataReader(initData);
// Properties
addProperty(_filePath);
addProperty(_tilePixelSize);
}
DefaultTileProvider::DefaultTileProvider(
std::shared_ptr<AsyncTileDataProvider> 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<float>::min();
}
}
void DefaultTileProvider::initTexturesFromLoadedData() {
if (_asyncTextureDataProvider) {
std::shared_ptr<RawTile> 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<GdalRawTileDataReader>(_filePath, initData,
_basePath, preprocess);
#else // GLOBEBROWSING_USE_GDAL
auto tileDataset = std::make_shared<SimpleRawTileDataReader>(_filePath, initData,
preprocess);
#endif // GLOBEBROWSING_USE_GDAL
_asyncTextureDataProvider = std::make_shared<AsyncTileDataProvider>(_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
@@ -28,6 +28,9 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/cache/memoryawaretilecache.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/numericalproperty.h>
namespace openspace {
class PixelBuffer;
@@ -43,12 +46,12 @@ namespace tileprovider {
* Provides tiles loaded by <code>AsyncTileDataProvider</code> 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<AsyncTileDataProvider> tileReader);
DefaultTileProvider(const ghoul::Dictionary& dictionary);
DefaultTileProvider(std::shared_ptr<AsyncTileDataProvider> 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<AsyncTileDataProvider> _asyncTextureDataProvider;
cache::MemoryAwareTileCache* _tileCache;
properties::StringProperty _filePath;
properties::IntProperty _tilePixelSize;
layergroupid::GroupID _layerGroupID;
std::string _basePath;
int _preCacheLevel;
bool _performPreProcessing;
};
} // namespace tileprovider
@@ -22,6 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#if 0
#include <modules/globebrowsing/geometry/geodetic2.h>
#include <modules/globebrowsing/tile/tileprovider/presentationslideprovider.h>
#include <modules/globebrowsing/tile/tileindex.h>
@@ -112,3 +114,5 @@ TileProvider* PresentationSlideProvider::slideProvider() {
} // namespace tileprovider
} // namespace globebrowsing
} // namespace openspace
#endif
@@ -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 <modules/globebrowsing/tile/tileprovider/projectiontileprovider.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/time.h>
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/scene/scenegraphnode.h>
#include <modules/space/rendering/planetgeometry.h>
#include <modules/newhorizons/util/imagesequencer.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionary.h>
#include <ghoul/opengl/textureunit.h>
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>(
PlanetGeometry::createFromDictionary(geometryDictionary)
);
}
_projectionComponent.initialize(dictionary.value<ghoul::Dictionary>(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<void*>(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(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<float>(M_PI_2),
glm::vec3(1, 0, 0)
);
glm::mat4 roty = glm::rotate(
_transform,
static_cast<float>(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<ghoul::opengl::Texture> 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<glm::vec4>(&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<int>(&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
@@ -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<std::string>(KeyFilePath, _imagePath)) {
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
}
std::string filePath;
dictionary.getValue<std::string>(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();
@@ -27,6 +27,8 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <openspace/properties/stringproperty.h>
namespace openspace {
namespace globebrowsing {
namespace tileprovider {
@@ -46,8 +48,9 @@ public:
private:
std::unique_ptr<ghoul::opengl::Texture> _tileTexture;
std::string _imagePath;
Tile _tile;
properties::StringProperty _filePath;
};
} // namespace tileprovider
@@ -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);
}
@@ -26,7 +26,7 @@
#include <modules/globebrowsing/tile/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/cachingtileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/defaulttileprovider.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/logging/logmanager.h>
@@ -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<std::string>(KeyFilePath, _datasetFile)) {
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
std::string filePath;
dictionary.getValue<std::string>(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<std::string>(KeyPreCacheStartTime);
const bool hasEnd = dictionary.hasKeyAndValue<std::string>(KeyPreCacheEndTime);
if (hasStart && hasEnd) {
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
Time(Time::convertTime(start)),
Time(Time::convertTime(end))
);
LINFO("Preloading: " << _filePath.value());
for (const Time& t : preCacheTimes) {
getTileProvider(t);
}
}
_successfulInitialization = true;
}
else {
LERROR("Unable to read file " + _filePath.value());
_successfulInitialization = false;
}
}
bool TemporalTileProvider::readFilePath() {
std::ifstream in(_filePath.value().c_str());
std::string xml;
if (in.is_open()) {
// read file
xml = std::string(
std::istreambuf_iterator<char>(in),
(std::istreambuf_iterator<char>())
);
}
else {
// Assume that it is already an xml
xml = _filePath.value();
}
_datasetFile = absPath(_datasetFile);
std::ifstream in(_datasetFile.c_str());
if (!in.is_open()) {
throw ghoul::FileNotFoundError(_datasetFile);
try {
_initDict.setValue<std::string>(
KeyBasePath,
ghoul::filesystem::File(_filePath.value()).directoryName()
);
}
catch (const std::runtime_error& e) {
// File path was not a path to a file but a GDAL config or empty
}
// read file
std::string xml(
std::istreambuf_iterator<char>(in),
(std::istreambuf_iterator<char>())
);
_initDict.setValue<std::string>(
KeyBasePath,
ghoul::filesystem::File(_datasetFile).directoryName()
);
_gdalXmlTemplate = consumeTemporalMetaData(xml);
const bool hasStart = dictionary.hasKeyAndValue<std::string>(KeyPreCacheStartTime);
const bool hasEnd = dictionary.hasKeyAndValue<std::string>(KeyPreCacheEndTime);
if (hasStart && hasEnd) {
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
Time(Time::convertTime(start)),
Time(Time::convertTime(end))
);
LINFO("Preloading: " << _datasetFile);
for (Time& t : preCacheTimes) {
getTileProvider(t);
}
}
return true;
}
std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml) {
@@ -139,12 +165,12 @@ std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml
catch (const ghoul::RuntimeError& e) {
throw ghoul::RuntimeError(
"Could not create time quantizer for Temporal GDAL dataset '" +
_datasetFile + "'. " + e.message);
_filePath.value() + "'. " + e.message);
}
_timeFormat = TimeIdProviderFactory::getProvider(timeIdFormat);
if (!_timeFormat) {
throw ghoul::RuntimeError(
"Invalid Time Format " + timeIdFormat + " in " + _datasetFile
"Invalid Time Format " + timeIdFormat + " in " + _filePath.value()
);
}
@@ -167,7 +193,7 @@ std::string TemporalTileProvider::getXMLValue(CPLXMLNode* root, const std::strin
CPLXMLNode * n = CPLSearchXMLNode(root, key.c_str());
if (!n) {
throw ghoul::RuntimeError(
"Unable to parse file " + _datasetFile + ". " + key + " missing."
"Unable to parse file " + _filePath.value() + ". " + key + " missing."
);
}
@@ -177,23 +203,43 @@ std::string TemporalTileProvider::getXMLValue(CPLXMLNode* root, const std::strin
}
TileDepthTransform TemporalTileProvider::depthTransform() {
ensureUpdated();
return _currentTileProvider->depthTransform();
if (_successfulInitialization) {
ensureUpdated();
return _currentTileProvider->depthTransform();
}
else {
return { 1.0f, 0.0f};
}
}
Tile::Status TemporalTileProvider::getTileStatus(const TileIndex& tileIndex) {
ensureUpdated();
return _currentTileProvider->getTileStatus(tileIndex);
if (_successfulInitialization) {
ensureUpdated();
return _currentTileProvider->getTileStatus(tileIndex);
}
else {
return Tile::Status::Unavailable;
}
}
Tile TemporalTileProvider::getTile(const TileIndex& tileIndex) {
ensureUpdated();
return _currentTileProvider->getTile(tileIndex);
if (_successfulInitialization) {
ensureUpdated();
return _currentTileProvider->getTile(tileIndex);
}
else {
return Tile::TileUnavailable;
}
}
int TemporalTileProvider::maxLevel() {
ensureUpdated();
return _currentTileProvider->maxLevel();
if (_successfulInitialization) {
ensureUpdated();
return _currentTileProvider->maxLevel();
}
else {
return 0;
}
}
void TemporalTileProvider::ensureUpdated() {
@@ -204,24 +250,23 @@ void TemporalTileProvider::ensureUpdated() {
}
void TemporalTileProvider::update() {
auto newCurrent = getTileProvider();
if (newCurrent) {
_currentTileProvider = newCurrent;
if (_successfulInitialization) {
std::shared_ptr<TileProvider> newCurrent = getTileProvider();
if (newCurrent) {
_currentTileProvider = newCurrent;
}
_currentTileProvider->update();
}
_currentTileProvider->update();
}
void TemporalTileProvider::reset() {
for (auto& it : _tileProviderMap) {
it.second->reset();
if (_successfulInitialization) {
for (std::pair<const TimeKey, std::shared_ptr<TileProvider>>& it : _tileProviderMap) {
it.second->reset();
}
}
//auto end = _tileProviderMap.end();
//for (auto it = _tileProviderMap.begin(); it != end; it++) {
// it->second->reset();
//}
}
std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(Time t) {
std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(const Time& t) {
Time tCopy(t);
if (_timeQuantizer.quantize(tCopy, true)) {
TimeKey timekey = _timeFormat->stringify(tCopy);
@@ -236,13 +281,15 @@ std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(Time t) {
return nullptr;
}
std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(TimeKey timekey) {
auto it = _tileProviderMap.find(timekey);
std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(
const TimeKey& timekey)
{
std::unordered_map<TimeKey, std::shared_ptr<TileProvider>>::iterator it = _tileProviderMap.find(timekey);
if (it != _tileProviderMap.end()) {
return it->second;
}
else {
auto tileProvider = initTileProvider(timekey);
std::shared_ptr<TileProvider> tileProvider = initTileProvider(timekey);
_tileProviderMap[timekey] = tileProvider;
return tileProvider;
@@ -266,7 +313,7 @@ std::shared_ptr<TileProvider> TemporalTileProvider::initTileProvider(TimeKey tim
FileSys.expandPathTokens(gdalDatasetXml, AllowedToken);
_initDict.setValue<std::string>(KeyFilePath, gdalDatasetXml);
auto tileProvider = std::make_shared<CachingTileProvider>(_initDict);
auto tileProvider = std::make_shared<DefaultTileProvider>(_initDict);
return tileProvider;
}
@@ -280,7 +327,6 @@ std::string TemporalTileProvider::getGdalDatasetXML(TimeKey timeKey) {
size_t pos = xmlTemplate.find(URL_TIME_PLACEHOLDER);
//size_t numChars = std::string(URL_TIME_PLACEHOLDER).length();
size_t numChars = strlen(URL_TIME_PLACEHOLDER);
ghoul_assert(pos != std::string::npos, "Invalid dataset file");
// @FRAGILE: This will only find the first instance. Dangerous if that instance is
// commented out ---abock
std::string timeSpecifiedXml = xmlTemplate.replace(pos, numChars, timeKey);
@@ -34,6 +34,8 @@
#include <openspace/util/timemanager.h>
#include <openspace/util/timerange.h>
#include <openspace/properties/stringproperty.h>
#include <ghoul/misc/dictionary.h>
#include <memory>
@@ -212,8 +214,10 @@ public:
typedef std::string TimeKey;
std::shared_ptr<TileProvider> getTileProvider(Time t = OsEng.timeManager().time());
std::shared_ptr<TileProvider> getTileProvider(TimeKey timekey);
std::shared_ptr<TileProvider> getTileProvider(
const Time& t = OsEng.timeManager().time());
std::shared_ptr<TileProvider> getTileProvider(
const TimeKey& timekey);
private:
/**
@@ -312,8 +316,10 @@ private:
* Ensures that the TemporalTileProvider is up to date.
*/
void ensureUpdated();
bool readFilePath();
std::string _datasetFile;
properties::StringProperty _filePath;
std::string _gdalXmlTemplate;
std::unordered_map<TimeKey, std::shared_ptr<TileProvider>> _tileProviderMap;
@@ -325,6 +331,7 @@ private:
TimeFormat* _timeFormat;
TimeQuantizer _timeQuantizer;
bool _successfulInitialization;
};
} // namespace tileprovider
@@ -33,7 +33,7 @@ namespace globebrowsing {
namespace tileprovider {
TileIndexTileProvider::TileIndexTileProvider(const ghoul::Dictionary& dict)
: TextTileProvider(LayerManager::getTileTextureInitData(layergroupid::ID::ColorLayers))
: TextTileProvider(LayerManager::getTileTextureInitData(layergroupid::GroupID::ColorLayers))
{ }
void TileIndexTileProvider::renderText(const ghoul::fontrendering::FontRenderer&
@@ -45,12 +45,15 @@ namespace tileprovider {
unsigned int TileProvider::_numTileProviders = 0;
std::unique_ptr<TileProvider> TileProvider::createFromDictionary(
layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary)
{
std::string type = "LRUCaching";
dictionary.getValue(KeyType, type);
std::string type = layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layerTypeID)];
auto factory = FactoryManager::ref().factory<TileProvider>();
std::unique_ptr<TileProvider> result = factory->create(type, dictionary);
if (!result) {
throw ghoul::RuntimeError("Unable to create tile provider");
}
return result;
}
@@ -28,7 +28,8 @@
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/tile/tile.h>
#include <modules/globebrowsing/cache/lrucache.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <openspace/properties/propertyowner.h>
#include <ghoul/opengl/texture.h>
@@ -52,6 +53,7 @@ public:
* to be instantiated.
*/
static std::unique_ptr<TileProvider> createFromDictionary(
layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary);
/**
@@ -43,8 +43,23 @@ TileProviderByIndex::TileProviderByIndex(const ghoul::Dictionary& dictionary) {
ghoul::Dictionary defaultProviderDict = dictionary.value<ghoul::Dictionary>(
KeyDefaultProvider
);
std::string typeString;
defaultProviderDict.getValue("Type", typeString);
layergroupid::TypeID typeID = layergroupid::TypeID::Unknown;
if (typeString.empty()) {
typeID = layergroupid::TypeID::DefaultTileLayer;
}
else {
typeID = layergroupid::getTypeIDFromTypeString(typeString);
}
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + typeString);
}
_defaultTileProvider = TileProvider::createFromDictionary(
defaultProviderDict
typeID, defaultProviderDict
);
ghoul::Dictionary indexProvidersDict = dictionary.value<ghoul::Dictionary>(
@@ -63,7 +78,23 @@ TileProviderByIndex::TileProviderByIndex(const ghoul::Dictionary& dictionary) {
);
TileIndex tileIndex(tileIndexDict);
std::string providerTypeString;
defaultProviderDict.getValue("Type", providerTypeString);
layergroupid::TypeID providerTypeID = layergroupid::TypeID::Unknown;
if (providerTypeString.empty()) {
providerTypeID = layergroupid::TypeID::DefaultTileLayer;
}
else {
providerTypeID = layergroupid::getTypeIDFromTypeString(providerTypeString);
}
if (providerTypeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + providerTypeString);
}
std::shared_ptr<TileProvider> stp = TileProvider::createFromDictionary(
providerTypeID,
providerDict
);
TileIndex::TileHashKey key = tileIndex.hashKey();
@@ -39,16 +39,20 @@ namespace openspace {
namespace globebrowsing {
namespace tileprovider {
TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary)
{
std::string name = "Name unspecified";
dictionary.getValue("Name", name);
layergroupid::ID layerGroupID;
layergroupid::GroupID layerGroupID;
dictionary.getValue(KeyLayerGroupID, layerGroupID);
const char* _loggerCat = ("TileProviderByLevel" + name).c_str();
ghoul::Dictionary providers = dictionary.value<ghoul::Dictionary>(KeyProviders);
ghoul::Dictionary providers;
if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyProviders)) {
providers = dictionary.value<ghoul::Dictionary>(KeyProviders);
}
for (size_t i = 0; i < providers.size(); i++) {
try {
std::string dictKey = std::to_string(i + 1);
@@ -71,10 +75,29 @@ TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
);
}
providerDict.setValue(KeyLayerGroupID, layerGroupID);
std::string typeString;
providerDict.getValue("Type", typeString);
layergroupid::TypeID typeID = layergroupid::TypeID::Unknown;
if (typeString.empty()) {
typeID = layergroupid::TypeID::DefaultTileLayer;
}
else {
typeID = layergroupid::getTypeIDFromTypeString(typeString);
}
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + typeString);
}
_levelTileProviders.push_back(
std::shared_ptr<TileProvider>(TileProvider::createFromDictionary(providerDict))
std::shared_ptr<TileProvider>(TileProvider::createFromDictionary(typeID, providerDict))
);
std::string providerName;
providerDict.getValue("Name", providerName);
_levelTileProviders.back()->setName(providerName);
addPropertySubOwner(_levelTileProviders.back().get());
// Ensure we can represent the max level
if(static_cast<int>(_providerIndices.size()) < maxLevel){
@@ -89,11 +112,6 @@ TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
}
}
// If all failed
if (_levelTileProviders.size() == 0) {
throw ghoul::RuntimeError("Failed to create tile provider: " + name);
}
// Fill in the gaps (value -1) in provider indices, from back to end
for(int i = _providerIndices.size() - 2; i >= 0; --i){
if(_providerIndices[i] == -1){
@@ -103,11 +121,23 @@ TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
}
Tile TileProviderByLevel::getTile(const TileIndex& tileIndex) {
return levelProvider(tileIndex.level)->getTile(tileIndex);
TileProvider* provider = levelProvider(tileIndex.level);
if (provider) {
return provider->getTile(tileIndex);
}
else {
return Tile::TileUnavailable;
}
}
Tile::Status TileProviderByLevel::getTileStatus(const TileIndex& index) {
return levelProvider(index.level)->getTileStatus(index);
TileProvider* provider = levelProvider(index.level);
if (provider) {
return provider->getTileStatus(index);
}
else {
return Tile::Status::Unavailable;
}
}
TileDepthTransform TileProviderByLevel::depthTransform() {
@@ -142,7 +172,12 @@ int TileProviderByLevel::providerIndex(int level) const {
}
TileProvider* TileProviderByLevel::levelProvider(int level) const {
return _levelTileProviders[providerIndex(level)].get();
if (_levelTileProviders.size() > 0) {
return _levelTileProviders[providerIndex(level)].get();
}
else {
return nullptr;
}
}
} // namespace tileprovider

Some files were not shown because too many files have changed in this diff Show More