mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-24 04:58:59 -05:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
-5
@@ -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>
|
||||
|
||||
-5
@@ -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>
|
||||
|
||||
-6
@@ -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 = { },
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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 },
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -40,15 +40,8 @@ return {
|
||||
Name = "Texture",
|
||||
FilePath = "textures/neptune.jpg",
|
||||
Enabled = true,
|
||||
TilePixelSize = 256,
|
||||
},
|
||||
},
|
||||
GrayScaleLayers = { },
|
||||
GrayScaleColorOverlays = { },
|
||||
NightLayers = { },
|
||||
WaterMasks = { },
|
||||
ColorOverlays = { },
|
||||
HeightLayers = { },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -40,15 +40,8 @@ return {
|
||||
Name = "Saturn Texture",
|
||||
FilePath = "textures/saturn.jpg",
|
||||
Enabled = true,
|
||||
TilePixelSize = 256,
|
||||
},
|
||||
},
|
||||
GrayScaleLayers = { },
|
||||
GrayScaleColorOverlays = { },
|
||||
NightLayers = { },
|
||||
WaterMasks = { },
|
||||
ColorOverlays = { },
|
||||
HeightLayers = { },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -40,15 +40,8 @@ return {
|
||||
Name = "Texture",
|
||||
FilePath = "textures/uranus.jpg",
|
||||
Enabled = true,
|
||||
TilePixelSize = 256,
|
||||
},
|
||||
},
|
||||
GrayScaleLayers = { },
|
||||
GrayScaleColorOverlays = { },
|
||||
NightLayers = { },
|
||||
WaterMasks = { },
|
||||
ColorOverlays = { },
|
||||
HeightLayers = { },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -45,15 +45,8 @@ return {
|
||||
Name = "Venus Texture",
|
||||
FilePath = "textures/venus.jpg",
|
||||
Enabled = true,
|
||||
TilePixelSize = 256,
|
||||
},
|
||||
},
|
||||
GrayScaleLayers = { },
|
||||
GrayScaleColorOverlays = { },
|
||||
NightLayers = { },
|
||||
WaterMasks = { },
|
||||
ColorOverlays = { },
|
||||
HeightLayers = { },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
+29
-26
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
+16
-4
@@ -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
Reference in New Issue
Block a user