Merge remote-tracking branch 'origin/master' into feature/statlogs

This commit is contained in:
Matthew Territo
2017-07-11 12:07:06 -06:00
107 changed files with 2778 additions and 1796 deletions

View File

@@ -1,9 +1,11 @@
OpenSpace is an open source, non-commercial, and freely available interactive data visualization software designed to visualize the entire known universe and portray our ongoing efforts to investigate the cosmos. Bringing the latest techniques from data visualization research to the general public, OpenSpace supports interactive presentation of dynamic data from observations, simulations, and space mission planning and operations. The software works on multiple operating systems (Windows, Linux, MacOS) with an extensible architecture powering high resolution tiled displays and planetarium domes, making use of the latest graphic card technologies for rapid data throughput. In addition, OpenSpace enables simultaneous connections across the globe creating opportunity for shared experiences among audiences worldwide.
[OpenSpace](http://openspaceproject.com) is an open source, non-commercial, and freely available interactive data visualization software designed to visualize the entire known universe and portray our ongoing efforts to investigate the cosmos. Bringing the latest techniques from data visualization research to the general public, OpenSpace supports interactive presentation of dynamic data from observations, simulations, and space mission planning and operations. The software works on multiple operating systems (Windows, Linux, MacOS) with an extensible architecture powering high resolution tiled displays and planetarium domes, making use of the latest graphic card technologies for rapid data throughput. In addition, OpenSpace enables simultaneous connections across the globe creating opportunity for shared experiences among audiences worldwide.
The project stems from the same academic collaboration between Swedens Linköping University (LiU) and the American Museum of Natural History (AMNH) that led to the creation of Uniview and its parent company SCISS. Development of the software began several years ago through a close collaboration with NASA Goddards Community Coordinated Modeling Center (CCMC) to model space weather forecasting and continued last year with visualization of NASAs New Horizons mission to Pluto and ESAs Rosetta mission. This promising set of preliminary work provided a foundation for recent NASA funding, which has extended the collaboration to include the University of Utahs Scientific Computing and Imaging (SCI) Institute, New York Universitys Tandon School of Engineering, multiple informal science institutions across the United States, and multiple, international vendors. Current areas of focus within OpenSpace include:
The project stems from the same academic collaboration between Swedens [Linköping University](https://www.liu.se) (LiU) and the [American Museum of Natural History](https://www.amnh.org) (AMNH) that led to the creation of Uniview and its parent company [SCISS](http://sciss.se). Development of the software began several years ago through a close collaboration with NASA Goddards [Community Coordinated Modeling Center](https://ccmc.gsfc.nasa.gov) (CCMC) to model space weather forecasting and continued with visualizations of NASAs New Horizons mission to Pluto and ESAs Rosetta mission. This promising set of preliminary work provided a foundation for recent NASA funding, which has extended the collaboration to include the University of Utahs [Scientific Computing and Imaging](https://www.sci.utah.edu) (SCI) Institute, [New York University](https://www.nyu.edu)s Tandon School of Engineering, multiple informal science institutions across the United States, and multiple, international vendors. Current areas of focus within OpenSpace include:
- Visualization of dynamic simulations via interactive volumetric rendering, as a priority for communicating research in astrophysics.
- Utilization of NASAs SPICE observational geometry system with its Planetary Data Service (PDS) to enable space mission visualization that reveal how missions are designed to gather science.
- Globe browsing techniques across spatial and temporal scales to examine scientific campaigns on multiple planets, including close up surface exploration.
This repository contains the source code and example scenes for OpenSpace, but does not contain any data. To build and install the client, we refer to the [Wiki](https://github.com/OpenSpace/OpenSpace/wiki) pages here on GitHub, specifically [building](https://github.com/OpenSpace/OpenSpace/wiki/General-Getting-Started-Guide%3A-Compiling-OpenSpace) for [Windows](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Windows), [Linux](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Linux), and [MacOS](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-OSX). Required preexisting dependencies are: [NASM](http://www.nasm.us/), [Boost](http://www.boost.org/), and [Qt](http://www.qt.io/download). Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace:).
This repository contains the source code and example scenes for OpenSpace, but does not contain any data. To build and install the client, we refer to the [Wiki](https://github.com/OpenSpace/OpenSpace/wiki) pages here on GitHub, specifically [building](https://github.com/OpenSpace/OpenSpace/wiki/General-Getting-Started-Guide%3A-Compiling-OpenSpace) for [Windows](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Windows), [Linux](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Linux), and [MacOS](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-OSX). Required preexisting dependencies are: [Boost](http://www.boost.org/) and [Qt](http://www.qt.io/download). Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace:).
Regarding any issues, you are very welcome on our [Slack support channel](https://openspacesupport.slack.com) to which you can freely [sign-up](https://join.slack.com/openspacesupport/shared_invite/MjA4ODY1MDQzNTUzLTE0OTk0MzUyODEtOGZkYTMwNmI5ZA).

View File

@@ -285,7 +285,7 @@ void MainWindow::initialize() {
_syncWidget->setSceneFiles(_sceneFiles);
// Load all available configuration files
QString configurationDirectory = QString::fromStdString(absPath("${SGCT}"));
QString configurationDirectory = QString::fromStdString(absPath("${CONFIG}"));
d = QDir(configurationDirectory);
d.setFilter(QDir::Files);
list = d.entryInfoList();

View File

@@ -70,12 +70,12 @@ return {
ColorLayers = {
{
Name = "ESRI VIIRS Combo",
Type = "ByLevel",
Type = "ByLevelTileLayer",
LevelTileProviders = {
{
MaxLevel = 3,
TileProvider = {
Type = "Temporal",
Type = "TemporalTileLayer",
Name = "Temporal VIIRS SNPP",
FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", },
},
@@ -90,22 +90,37 @@ return {
Enabled = true,
},
{
Type = "Temporal",
Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature",
FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml",
Name = "BMNG",
FilePath = "map_service_configs/Utah/Bmng.wms"
},
{
Type = "Temporal",
Type = "TemporalTileLayer",
Name = "Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration",
FilePath = "map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml",
},
{
Name = "BMNG",
FilePath = "map_service_configs/Utah/Bmng.wms"
}
Type = "TemporalTileLayer",
Name = "MODIS_Terra_Chlorophyll_A",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Terra_Chlorophyll_A",
"2013-07-02",
"Yesterday",
"1d",
"1km",
"png")
},
{
Type = "TemporalTileLayer",
Name = "GHRSST_L4_G1SST_Sea_Surface_Temperature",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"GHRSST_L4_G1SST_Sea_Surface_Temperature",
"2010-06-21",
"Yesterday",
"1d",
"1km",
"png")
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = {
{
Name = "Earth at Night 2012",
@@ -118,7 +133,7 @@ return {
},
},
{
Type = "Temporal",
Type = "TemporalTileLayer",
Name = "Temporal Earth at Night",
FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml"
}
@@ -134,7 +149,7 @@ return {
FilePath = "map_service_configs/Utah/Gebco.wms",
}
},
ColorOverlays = {
Overlays = {
{
Name = "Coastlines",
FilePath = "map_service_configs/GIBS/Coastlines.xml",
@@ -148,14 +163,13 @@ return {
FilePath = "map_service_configs/GIBS/Reference_Labels.xml",
},
{
Type = "TileIndex",
Type = "TileIndexTileLayer",
Name = "Tile Indices",
},
{
Type = "SizeReference",
Type = "SizeReferenceTileLayer",
Name = "Size Reference",
Radii = earthEllipsoid,
BackgroundImagePath = "../arrows.png",
},
},
HeightLayers = {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -32,15 +32,8 @@ return {
Name = "Callisto Texture",
FilePath = "textures/callisto.jpg",
Enabled = true,
TilePixelSize = 112,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},

View File

@@ -32,15 +32,8 @@ return {
Name = "Europa Texture",
FilePath = "textures/europa.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},

View File

@@ -32,15 +32,8 @@ return {
Name = "Ganymede Texture",
FilePath = "textures/ganymede.jpg",
Enabled = true,
TilePixelSize = 112,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},

View File

@@ -34,12 +34,6 @@ return {
Enabled = true,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},

View File

@@ -45,12 +45,6 @@ return {
Enabled = true,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
}
},

View File

@@ -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>

View File

@@ -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>

View File

@@ -17,4 +17,6 @@
<BlockSizeY>256</BlockSizeY>
<BandsCount>2</BandsCount>
<MaxConnections>10</MaxConnections>
<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
</GDAL_WMS>

View File

@@ -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>

View File

@@ -1,4 +1,5 @@
local marsEllipsoid = {3396190.0, 3396190.0, 3376200.0}
return {
-- Barycenter module
{
@@ -34,7 +35,8 @@ return {
CameraMinHeight = 10,
SegmentsPerPatch = 90,
-- Allows camera to go down 10000 meters below the reference ellipsoid
InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values
-- Useful when having negative height map values
InteractionDepthBelowEllipsoid = 10000,
Layers = {
ColorLayers = {
{
@@ -42,87 +44,30 @@ return {
FilePath = "map_service_configs/MARS_Viking_MDIM21.xml",
Enabled = true,
},
-- {
-- Type = "SingleImage",
-- Name = "Debug Tiles",
-- FilePath = "../../debugglobe/textures/test_tile.png",
-- },
--{
-- Name = "MARS_Viking",
-- FilePath = "map_service_configs/MARS_Viking_MDIM21.xml",
-- Enabled = true,
--},
{
Name = "MOLA Pseudo Color",
FilePath = "map_service_configs/Utah/MolaPseudoColor.xml",
-- Enabled = true,
},
--[[
{
Name = "Mars Viking Clr",
FilePath = "map_datasets/Viking/Mars_Viking_ClrMosaic_global_925m_longlat_full.vrt",
Enabled = true,
},
]]
},
GrayScaleLayers = {
},
GrayScaleColorOverlays = {
{
Name = "CTX Mosaic [AWS]",
FilePath = "map_service_configs/CTX.wms",
Enabled = true,
},
{
Name = "CTX Mosaic [Europe]",
FilePath = "map_service_configs/CTX_Mosaic.xml",
--Enabled = true,
BlendMode = "Color"
},
{
Name = "CTX Mosaic [Utah]",
FilePath = "map_service_configs/Utah/CTX_Mosaic.xml",
BlendMode = "Color"
},
{
Name = "West Candor Chasma",
FilePath = "map_datasets/CTX/West_Candor_Chasma_longlat_global.vrt",
--Enabled = true,
},
{
Name = "Layered Rock Outcrops in Southwest Candor Chasma",
FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Texture.vrt",
},
--[[{
Name = "Themis IR Day",
FilePath = "map_service_configs/Utah/ThemisIRDay.xml",
},
{
Name = "Themis IR Night",
FilePath = "map_service_configs/Utah/ThemisIRNight.xml",
},
{
Name = "MER_Meridianni_Endeavor_Basemap_25cm",
FilePath = "map_datasets/Basemap/MER_Meridianni_Endeavor_Basemap_25cm.vrt",
},
{
Name = "Part of Area Traversed by the Mars Exploration Rover",
FilePath = "map_datasets/HiRISE/Part_of_Area_Traversed_by_the_Mars_Exploration_Rover_Texture.vrt",
},
]]
},
NightLayers = { },
WaterMasks = { },
ColorOverlays = {
Overlays = {
{
Type = "TileIndex",
Type = "TileIndexTileLayer",
Name = "Indices",
},
{
Type = "SizeReference",
Type = "SizeReferenceTileLayer",
Name = "Size Reference",
Radii = marsEllipsoid,
BackgroundImagePath = "../arrows.png",
},
},
HeightLayers = {
@@ -131,50 +76,7 @@ return {
FilePath = "map_service_configs/Mola_Elevation.xml",
Enabled = true,
TilePixelSize = 90,
DoPreProcessing = true,
},
--[[
{
Name = "Mola Elevation [Utah]",
FilePath = "map_service_configs/Utah/Mola_Elevation.xml",
Enabled = false,
TilePixelSize = 90,
DoPreProcessing = true,
},
{
Name = "Mola Elevation CTX",
FilePath = "map_service_configs/Utah/MolaCTX_Elevation.xml",
-- Enabled = true,
TilePixelSize = 90,
DoPreProcessing = true,
},]]
{
Name = "West Candor Chasma",
FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt",
--Enabled = true,
TilePixelSize = 90,
DoPreProcessing = true,
},
{
Name = "Layered Rock Outcrops in Southwest Candor Chasma",
FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Heightmap.vrt",
TilePixelSize = 90,
DoPreProcessing = true,
},
--[[
{
Name = "West Candor Chasma",
FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt",
--Enabled = true,
TilePixelSize = 90,
DoPreProcessing = true,
},]]
--[[
{
Name = "Part of Area Traversed by the Mars Exploration Rover",
FilePath = "map_datasets/HiRISE/Part_of_Area_Traversed_by_the_Mars_Exploration_Rover_Heightmap.vrt",
},
]]
},
},
}

View File

@@ -25,6 +25,7 @@
<TileCountY>1</TileCountY>
<YOrigin>top</YOrigin>
</DataWindow>
<Timeout>5</Timeout>
<BlockSizeX>512</BlockSizeX>
<BlockSizeY>512</BlockSizeY>
</GDAL_WMS>

View File

@@ -0,0 +1,74 @@
return {
-- Barycenter module
{
Name = "MercuryBarycenter",
Parent = "SolarSystemBarycenter",
Transform = {
Translation = {
Type = "SpiceTranslation",
Body = "MERCURY",
Observer = "SUN",
Kernels = "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp"
},
},
},
-- RenderableGlobe module
{
Name = "Mercury",
Parent = "MercuryBarycenter",
Transform = {
Rotation = {
Type = "SpiceRotation",
SourceFrame = "IAU_MERCURY",
DestinationFrame = "GALACTIC",
},
Scale = {
Type = "StaticScale",
Scale = 1,
},
},
Renderable = {
Type = "RenderableGlobe",
Radii = {2439700, 2439700.0, 2439700.0},
Frame = "IAU_MERCURY",
Body = "MERCURY",
CameraMinHeight = 300,
InteractionDepthBelowEllipsoid = 0, -- Useful when having negative height map values
SegmentsPerPatch = 64,
Layers = {
ColorLayers = {
{
Name = "Simple Texture",
FilePath = "textures/mercury.jpg",
Enabled = true,
},
{
Name = "Messenger_Mosaic",
FilePath = "map_service_configs/Utah/MessengerMosaic.wms"
},
{
Name = "Messenger_MDIS",
FilePath = "map_service_configs/Utah/MessengerMDIS.wms"
}
},
},
},
},
-- Trail module
{
Name = "MercuryTrail",
Parent = "SolarSystemBarycenter",
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Body = "MERCURY",
Observer = "SUN",
},
Color = {0.6, 0.5, 0.5 },
Period = 87.968,
Resolution = 100
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -25,12 +25,6 @@ return {
InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values
Layers = {
ColorLayers = {
},
GrayScaleColorOverlays = {
},
GrayScaleLayers = {
{
Name = "OnMoonColorGrayscale",
FilePath = "map_service_configs/OnMoonColor.xml",
@@ -48,29 +42,14 @@ return {
Name = "WAC",
FilePath = "map_service_configs/Utah/Wac.wms"
}
},
NightLayers = {
},
WaterMasks = {
},
ColorOverlays = {
},
HeightLayers = {
{
Name = "OnMoonHeight",
FilePath = "map_service_configs/OnMoonHeight.xml",
Enabled = true,
DoPreProcessing = true,
TileSize = 64,
},
{
Name = "LolaDem",
FilePath = "map_service_configs/Utah/LolaDem.wms",
DoPreProcessing = true,
TileSize = 64,
Enabled = true,
TilePixelSize = 64,
Settings = { Multiplier = 0.5 },
}
},
},

View File

@@ -40,15 +40,8 @@ return {
Name = "Texture",
FilePath = "textures/neptune.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},

View File

@@ -40,15 +40,8 @@ return {
Name = "Saturn Texture",
FilePath = "textures/saturn.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},

View File

@@ -40,15 +40,8 @@ return {
Name = "Texture",
FilePath = "textures/uranus.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},

View File

@@ -45,15 +45,8 @@ return {
Name = "Venus Texture",
FilePath = "textures/venus.jpg",
Enabled = true,
TilePixelSize = 256,
},
},
GrayScaleLayers = { },
GrayScaleColorOverlays = { },
NightLayers = { },
WaterMasks = { },
ColorOverlays = { },
HeightLayers = { },
},
},
},

View File

@@ -25,6 +25,8 @@
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.h
${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.h
${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.inl
${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.h
@@ -79,12 +81,14 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroupid.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.h
@@ -102,8 +106,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileuvtransform.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h
@@ -123,6 +126,9 @@ set(HEADER_FILES
)
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globebrowsingmodule_lua.inl
${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cache/texturecontainer.cpp
@@ -159,12 +165,14 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuchunktilepile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpuheightlayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayeradjustment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gpulayerrendersettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputiledepthtransform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gpu/gputileuvtransform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layeradjustment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layergroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.cpp
@@ -178,8 +186,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/tile/tilemetadata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileselector.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileloadjob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/defaulttileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp

View File

@@ -70,6 +70,7 @@ public:
*/
Item popLRU();
size_t size() const;
size_t maximumCacheSize() const;
private:
void putWithoutCleaning(const KeyType& key, const ValueType& value);

View File

@@ -120,6 +120,11 @@ size_t LRUCache<KeyType, ValueType, HasherType>::size() const {
return _itemMap.size();
}
template<typename KeyType, typename ValueType, typename HasherType>
size_t LRUCache<KeyType, ValueType, HasherType>::maximumCacheSize() const {
return _maximumCacheSize;
}
template<typename KeyType, typename ValueType, typename HasherType>
void LRUCache<KeyType, ValueType, HasherType>::putWithoutCleaning(const KeyType& key,
const ValueType& value)

View File

@@ -117,7 +117,7 @@ void MemoryAwareTileCache::clear() {
void MemoryAwareTileCache::createDefaultTextureContainers() {
for (int id = 0; id < layergroupid::NUM_LAYER_GROUPS; id++) {
TileTextureInitData initData =
LayerManager::getTileTextureInitData(layergroupid::ID(id));
LayerManager::getTileTextureInitData(layergroupid::GroupID(id));
assureTextureContainerExists(initData);
}
}

View File

@@ -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;
}

View File

@@ -28,7 +28,7 @@
#include <modules/globebrowsing/globes/renderableglobe.h>
#include <modules/globebrowsing/other/distanceswitch.h>
#include <modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h>
#include <modules/globebrowsing/tile/tileprovider/cachingtileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/singleimageprovider.h>
#include <modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/temporaltileprovider.h>
@@ -37,10 +37,11 @@
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/tile/tileprovider/presentationslideprovider.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/templatefactory.h>
@@ -48,6 +49,8 @@
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
#include "globebrowsingmodule_lua.inl"
namespace openspace {
const std::string GlobeBrowsingModule::name = "GlobeBrowsing";
@@ -59,11 +62,10 @@ GlobeBrowsingModule::GlobeBrowsingModule()
void GlobeBrowsingModule::internalInitialize() {
using namespace globebrowsing;
// Initialize
OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Initialize, [&] {
_tileCache = std::make_unique<globebrowsing::cache::MemoryAwareTileCache>();
addPropertySubOwner(*_tileCache);
_tileCache = std::make_unique<globebrowsing::cache::MemoryAwareTileCache>();
addPropertySubOwner(*_tileCache);
#ifdef GLOBEBROWSING_USE_GDAL
// Convert from MB to Bytes
GdalWrapper::create(
@@ -73,37 +75,47 @@ void GlobeBrowsingModule::internalInitialize() {
#endif // GLOBEBROWSING_USE_GDAL
});
// Render
OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Render, [&]{
_tileCache->update();
});
// Deinitialize
OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Deinitialize, [&]{
#ifdef GLOBEBROWSING_USE_GDAL
GdalWrapper::ref().destroy();
#endif // GLOBEBROWSING_USE_GDAL
});
// Get factories
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "Renderable factory was not created");
// Create factory for TileProviders
auto fTileProvider =
std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
ghoul_assert(fTileProvider, "TileProvider factory was not created");
// Register renderable class
fRenderable->registerClass<globebrowsing::RenderableGlobe>("RenderableGlobe");
// add Tile Provider factory
auto fTileProvider = std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
fTileProvider->registerClass<tileprovider::CachingTileProvider>("LRUCaching");
fTileProvider->registerClass<tileprovider::SingleImageProvider>("SingleImage");
// Register TileProvider classes
fTileProvider->registerClass<tileprovider::DefaultTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::DefaultTileLayer)]);
fTileProvider->registerClass<tileprovider::SingleImageProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::SingleImageTileLayer)]);
#ifdef GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TemporalTileProvider>("Temporal");
fTileProvider->registerClass<tileprovider::TemporalTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::TemporalTileLayer)]);
#endif // GLOBEBROWSING_USE_GDAL
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>("TileIndex");
fTileProvider->registerClass<tileprovider::SizeReferenceTileProvider>("SizeReference");
// Combining Tile Providers
fTileProvider->registerClass<tileprovider::TileProviderByLevel>("ByLevel");
fTileProvider->registerClass<tileprovider::TileProviderByIndex>("ByIndex");
fTileProvider->registerClass<tileprovider::PresentationSlideProvider>("PresentationSlides");
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::TileIndexTileLayer)]);
fTileProvider->registerClass<tileprovider::SizeReferenceTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::SizeReferenceTileLayer)]);
fTileProvider->registerClass<tileprovider::TileProviderByLevel>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::ByLevelTileLayer)]);
fTileProvider->registerClass<tileprovider::TileProviderByIndex>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layergroupid::TypeID::ByIndexTileLayer)]);
FactoryManager::ref().addFactory(std::move(fTileProvider));
}
@@ -112,13 +124,62 @@ globebrowsing::cache::MemoryAwareTileCache* GlobeBrowsingModule::tileCache() {
}
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
std::string listLayerGroups = layerGroupNamesList();
return {
"globebrowsing",
{},
{
{
"addLayer",
&globebrowsing::luascriptfunctions::addLayer,
"string, string, table",
"Adds a layer to the specified globe. The first argument specifies the "
"name of the scene graph node of which to add the layer. The renderable "
"of the specified scene graph node needs to be a renderable globe. "
"The second argument is the layer group which can be any of "
+ listLayerGroups + ". The third argument is the dictionary defining the "
"layer."
},
{
"deleteLayer",
&globebrowsing::luascriptfunctions::deleteLayer,
"string, string",
"Removes a layer from the specified globe. The first argument specifies "
"the name of the scene graph node of which to remove the layer. "
"The renderable of the specified scene graph node needs to be a "
"renderable globe. The second argument is the layer group which can be "
"any of " + listLayerGroups + ". The third argument is the dictionary"
"defining the layer."
},
},
{
"${MODULE_GLOBEBROWSING}/scripts/layer_support.lua"
},
{
// Documentation
}
};
}
std::string GlobeBrowsingModule::layerGroupNamesList() {
std::string listLayerGroups("");
for (int i = 0; i < globebrowsing::layergroupid::NUM_LAYER_GROUPS - 1; ++i) {
listLayerGroups +=
globebrowsing::layergroupid::LAYER_GROUP_NAMES[i] + std::string(", ");
}
listLayerGroups +=
std::string(" and ") + globebrowsing::layergroupid::LAYER_GROUP_NAMES[
globebrowsing::layergroupid::NUM_LAYER_GROUPS - 1];
return listLayerGroups;
}
std::string GlobeBrowsingModule::layerTypeNamesList() {
std::string listLayerTypes("");
for (int i = 0; i < globebrowsing::layergroupid::NUM_LAYER_TYPES - 1; ++i) {
listLayerTypes += globebrowsing::layergroupid::LAYER_TYPE_NAMES[i] + ", ";
}
listLayerTypes +=
" and " + globebrowsing::layergroupid::LAYER_TYPE_NAMES[globebrowsing::layergroupid::NUM_LAYER_TYPES - 1];
return listLayerTypes;
}
} // namespace openspace

View File

@@ -46,11 +46,20 @@ public:
scripting::LuaLibrary luaLibrary() const override;
protected:
void internalInitialize() override;
private:
/**
\return a comma separated list of layer group names.
*/
static std::string layerGroupNamesList();
/**
\return a comma separated list of layer type names.
*/
static std::string layerTypeNamesList();
std::unique_ptr<globebrowsing::cache::MemoryAwareTileCache> _tileCache;
};

View File

@@ -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

View File

@@ -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();
}

View File

@@ -38,7 +38,20 @@ namespace globebrowsing {
PointGlobe::PointGlobe(const RenderableGlobe& owner)
: _owner(owner)
{}
, _intensityClamp(
"intensityClamp",
"Intensity clamp",
1, 0, 1
)
, _lightIntensity(
"lightIntensity",
"Light intensity",
1, 0, 50
)
{
addProperty(_intensityClamp);
addProperty(_lightIntensity);
}
PointGlobe::~PointGlobe() {
glDeleteBuffers(1, &_vertexBufferID);
@@ -56,21 +69,27 @@ bool PointGlobe::initialize() {
glBindVertexArray(_vaoID);
// Vertex data is only one point in the origin
glm::vec3 data = glm::vec3(0,0,0);
std::array<glm::vec2, 6> quadVertexData = {
glm::vec2(-1.0f, -1.0f),
glm::vec2(1.0f, -1.0f),
glm::vec2(-1.0f, 1.0f),
glm::vec2(-1.0f, 1.0f),
glm::vec2(1.0f, -1.0f),
glm::vec2(1.0f, 1.0f)
};
// Vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(glm::vec3),
&data,
sizeof(glm::vec2) * quadVertexData.size(),
quadVertexData.data(),
GL_STATIC_DRAW
);
// Position at location 0
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), 0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), 0);
glBindVertexArray(0);
@@ -91,32 +110,55 @@ void PointGlobe::render(const RenderData& data) {
// Calculate variables to be used as uniform variables in shader
glm::dvec3 bodyPosition = data.modelTransform.translation;
glm::dmat4 rotationTransform = glm::lookAt(
glm::dvec3(0.0f),
data.camera.positionVec3() - bodyPosition,
glm::normalize(glm::dvec3(1000000.0f) - bodyPosition));
glm::dvec3 camToBody = bodyPosition - data.camera.positionVec3();
float distanceToBody = glm::length(camToBody);
float avgRadius = _owner.ellipsoid().averageRadius();
float lightIntensity = _lightIntensity.value() * data.modelTransform.scale * avgRadius / distanceToBody;
float lightIntensityClamped = glm::min(lightIntensity, _intensityClamp.value());
float lightOverflow = glm::max(lightIntensity - lightIntensityClamped, 0.0f);
float billboardRadius = lightIntensityClamped * distanceToBody;
glm::dmat4 scaleTransform = glm::scale(glm::dmat4(1.0), glm::dvec3(billboardRadius));
setBoundingSphere(billboardRadius);
// Model transform and view transform needs to be in double precision
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), bodyPosition) * // Translation
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); // Scale
glm::inverse(rotationTransform) *
scaleTransform; // Scale
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
glm::vec3 directionToSun = glm::normalize(glm::vec3(0) - glm::vec3(bodyPosition));
glm::vec3 directionToSunViewSpace = glm::mat3(data.camera.combinedViewMatrix()) * directionToSun;
int windowWidth = OsEng.windowWrapper().currentWindowSize().x;
float avgRadius = _owner.ellipsoid().averageRadius();
_programObject->setUniform("windowWidth", windowWidth);
_programObject->setUniform("globeRadius", avgRadius);
_programObject->setUniform("directionToSunViewSpace", directionToSunViewSpace);
_programObject->setUniform("lightIntensityClamped", lightIntensityClamped);
//_programObject->setUniform("lightOverflow", lightOverflow);
//_programObject->setUniform("directionToSunViewSpace", directionToSunViewSpace);
_programObject->setUniform("modelViewTransform", glm::mat4(modelViewTransform));
_programObject->setUniform("projectionTransform", data.camera.sgctInternal.projectionMatrix());
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vertexBufferID);
glDrawArrays(GL_POINTS, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
_programObject->deactivate();
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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>

View File

@@ -32,7 +32,6 @@ namespace globebrowsing {
DistanceSwitch::~DistanceSwitch() {}
bool DistanceSwitch::initialize() {
_objectScale = 1.0;
for (unsigned int i = 0; i < _renderables.size(); ++i) {
_renderables[i]->initialize();
}
@@ -46,44 +45,32 @@ bool DistanceSwitch::deinitialize() {
return true;
}
void DistanceSwitch::render(const RenderData& data) {
if (_maxDistances.size() == 0) {
return;
}
double distanceToCamera = distance(data.camera.positionVec3(), data.modelTransform.translation);
if (distanceToCamera > _maxDistances.back() * _objectScale) {
return;
}
const double distanceToCamera =
distance(data.camera.positionVec3(), data.modelTransform.translation);
// This distance will be enough to render the globe as one pixel if the field of
// view is 'fov' radians and the screen resolution is 'res' pixels.
const double fov = 2 * glm::pi<double>() / 6; // 60 degrees
int res = 2880;
// linear search through nodes to find which Renderable to render
for (unsigned int i = 0; i < _renderables.size(); ++i) {
if (distanceToCamera < _maxDistances[i] * _objectScale) {
_renderables[i]->render(data);
return;
for (std::shared_ptr<Renderable> renderable : _renderables) {
const double distance = res * renderable->boundingSphere() / tan(fov / 2);
if (distanceToCamera < distance) {
renderable->render(data);
}
}
}
void DistanceSwitch::update(const UpdateData& data) {
_objectScale = data.modelTransform.scale;
for (unsigned int i = 0; i < _renderables.size(); ++i) {
_renderables[i]->update(data);
for (std::shared_ptr<Renderable> renderable : _renderables) {
renderable->update(data);
}
}
void DistanceSwitch::addSwitchValue(std::shared_ptr<Renderable> renderable,
double maxDistance)
{
ghoul_assert(maxDistance > 0, "Renderable must have a positive maxDistance");
if (_maxDistances.size() > 0) {
ghoul_assert(maxDistance > _maxDistances.back(),
"Renderables must be inserted in ascending order wrt distance");
}
void DistanceSwitch::addSwitchValue(std::shared_ptr<Renderable> renderable) {
_renderables.push_back(renderable);
_maxDistances.push_back(maxDistance);
}
} // namespace globebrowsing

View File

@@ -39,7 +39,7 @@ namespace globebrowsing {
/**
* Selects a specific Renderable to be used for rendering, based on distance to the
* camera
*/
*/
class DistanceSwitch {
public:
~DistanceSwitch();
@@ -50,20 +50,17 @@ public:
/**
* Picks the first Renderable with the associated maxDistance greater than the
* current distance to the camera
*/
*/
void render(const RenderData& data);
void update(const UpdateData& data);
/**
* Adds a new renderable (first argument) which may be rendered only if the distance
* to the camera is less than maxDistance (second argument)
*/
void addSwitchValue(std::shared_ptr<Renderable> renderable, double maxDistance);
* Adds a new renderable
*/
void addSwitchValue(std::shared_ptr<Renderable> renderable);
private:
std::vector<std::shared_ptr<Renderable>> _renderables;
std::vector<double> _maxDistances;
double _objectScale;
};
} // namespace globebrowsing

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -67,10 +67,17 @@ ThreadPool::ThreadPool(size_t numThreads)
}
}
ThreadPool::ThreadPool(const ThreadPool& toCopy)
: ThreadPool(toCopy.workers.size())
{ }
// the destructor joins all threads
ThreadPool::~ThreadPool() {
// stop all threads
stop = true;
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
// join them

View File

@@ -31,6 +31,7 @@
#include <queue>
#include <thread>
#include <vector>
#include <atomic>
// Implementatin based on http://progsch.net/wordpress/?p=81
@@ -50,6 +51,7 @@ private:
class ThreadPool {
public:
ThreadPool(size_t numThreads);
ThreadPool(const ThreadPool& toCopy);
~ThreadPool();
void enqueue(std::function<void()> f);

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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__

View File

@@ -30,60 +30,296 @@ namespace openspace {
namespace globebrowsing {
namespace {
const char* _loggerCat = "Layer";
const char* keyName = "Name";
const char* keyEnabled = "Enabled";
const char* keyLayerGroupID = "LayerGroupID";
const char* keySettings = "Settings";
const char* keyAdjustment = "Adjustment";
const char* KeyBlendMode = "BlendMode";
}
Layer::Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict)
Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict)
: properties::PropertyOwner(layerDict.value<std::string>(keyName))
, _typeOption(
"type",
"Type",
properties::OptionProperty::DisplayType::Dropdown
)
, _blendModeOption(
"blendMode",
"Blend Mode",
properties::OptionProperty::DisplayType::Dropdown
)
, _enabled(properties::BoolProperty("enabled", "Enabled", false))
, _reset("reset", "Reset")
{
// We add the id to the dictionary since it needs to be known by
// the tile provider
ghoul::Dictionary newLayerDict = layerDict;
newLayerDict.setValue(keyLayerGroupID, id);
_tileProvider = std::shared_ptr<tileprovider::TileProvider>(
tileprovider::TileProvider::createFromDictionary(newLayerDict));
// Something else went wrong and no exception was thrown
if (_tileProvider == nullptr) {
throw ghoul::RuntimeError("Unable to create TileProvider '" + name() + "'");
, _tileProvider(nullptr)
, _otherTypesProperties{
properties::Vec3Property (
"color",
"Color",
glm::vec4(1.f, 1.f, 1.f, 1.f),
glm::vec4(0.f),
glm::vec4(1.f))
}
, _layerGroupId(id)
{
layergroupid::TypeID typeID = parseTypeIdFromDictionary(layerDict);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type!");
}
initializeBasedOnType(typeID, layerDict);
bool enabled = false; // defaults to false if unspecified
layerDict.getValue(keyEnabled, enabled);
_enabled.setValue(enabled);
// Initialize settings
ghoul::Dictionary settingsDict;
if (layerDict.getValue(keySettings, settingsDict)) {
_renderSettings.setValuesFromDictionary(settingsDict);
}
if (id == layergroupid::ID::GrayScaleColorOverlays) {
_renderSettings.addProperty(_renderSettings.valueBlending);
_renderSettings.useValueBlending = true;
// Initiallize layer adjustment
ghoul::Dictionary adjustmentDict;
if (layerDict.getValue(keyAdjustment, adjustmentDict)) {
_layerAdjustment.setValuesFromDictionary(adjustmentDict);
}
_reset.onChange([&](){
_tileProvider->reset();
// Add options to option properties
for (int i = 0; i < layergroupid::NUM_LAYER_TYPES; ++i) {
_typeOption.addOption(i, layergroupid::LAYER_TYPE_NAMES[i]);
}
_typeOption.setValue(static_cast<int>(typeID));
_type = static_cast<layergroupid::TypeID>(_typeOption.value());
for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) {
_blendModeOption.addOption(i, layergroupid::BLEND_MODE_NAMES[i]);
}
// Initialize blend mode
std::string blendModeName;
if (layerDict.getValue(KeyBlendMode, blendModeName)) {
layergroupid::BlendModeID blendModeID =
layergroupid::getBlendModeIDFromName(blendModeName);
_blendModeOption.setValue(static_cast<int>(blendModeID));
}
else {
_blendModeOption.setValue(static_cast<int>(layergroupid::BlendModeID::Normal));
}
// On change callbacks definitions
_enabled.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_reset.onChange([&](){
if (_tileProvider) {
_tileProvider->reset();
}
});
_typeOption.onChange([&](){
removeVisibleProperties();
_type = static_cast<layergroupid::TypeID>(_typeOption.value());
ghoul::Dictionary dict;
initializeBasedOnType(type(), dict);
addVisibleProperties();
if (_onChangeCallback) {
_onChangeCallback();
}
});
_blendModeOption.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_layerAdjustment.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_typeOption.setReadOnly(true);
// Add the properties
addProperty(_typeOption);
addProperty(_blendModeOption);
addProperty(_enabled);
addProperty(_reset);
_otherTypesProperties.color.setViewOption(properties::Property::ViewOptions::Color);
addVisibleProperties();
addPropertySubOwner(_renderSettings);
addPropertySubOwner(*_tileProvider);
addPropertySubOwner(_layerAdjustment);
}
ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const {
return _tileProvider->getChunkTilePile(tileIndex, pileSize);
if (_tileProvider) {
return _tileProvider->getChunkTilePile(tileIndex, pileSize);
}
else {
ChunkTilePile chunkTilePile;
chunkTilePile.resize(pileSize);
for (int i = 0; i < pileSize; ++i) {
chunkTilePile[i].tile = Tile::TileUnavailable;
chunkTilePile[i].uvTransform.uvOffset = { 0, 0 };
chunkTilePile[i].uvTransform.uvScale = { 1, 1 };
}
return chunkTilePile;
}
}
Tile::Status Layer::getTileStatus(const TileIndex& index) const {
if (_tileProvider) {
return _tileProvider->getTileStatus(index);
}
else {
return Tile::Status::Unavailable;
}
}
layergroupid::TypeID Layer::type() const {
return _type;
};
layergroupid::BlendModeID Layer::blendMode() const {
return static_cast<layergroupid::BlendModeID>(_blendModeOption.value());
};
TileDepthTransform Layer::depthTransform() const {
if (_tileProvider) {
return _tileProvider->depthTransform();
}
else {
return {1.0f, 0.0f};
}
}
bool Layer::enabled() const {
return _enabled.value();
}
tileprovider::TileProvider* Layer::tileProvider() const {
return _tileProvider.get();
}
const Layer::OtherTypesProperties& Layer::otherTypesProperties() const {
return _otherTypesProperties;
}
const LayerRenderSettings& Layer::renderSettings() const {
return _renderSettings;
}
const LayerAdjustment& Layer::layerAdjustment() const {
return _layerAdjustment;
}
void Layer::onChange(std::function<void(void)> callback) {
_enabled.onChange(callback);
_onChangeCallback = callback;
}
void Layer::update() {
if (_tileProvider) {
_tileProvider->update();
}
}
layergroupid::TypeID Layer::parseTypeIdFromDictionary(
const ghoul::Dictionary& initDict) const
{
if (initDict.hasKeyAndValue<std::string>("Type")) {
const std::string typeString = initDict.value<std::string>("Type");
return layergroupid::getTypeIDFromTypeString(typeString);
}
else {
return layergroupid::TypeID::DefaultTileLayer;
}
}
void Layer::initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict) {
switch (typeId) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer: {
// We add the id to the dictionary since it needs to be known by
// the tile provider
ghoul::Dictionary tileProviderInitDict = initDict;
tileProviderInitDict.setValue(keyLayerGroupID, _layerGroupId);
if (tileProviderInitDict.hasKeyAndValue<std::string>(keyName)) {
std::string name;
tileProviderInitDict.getValue(keyName, name);
LDEBUG("Initializing tile provider for layer: '" + name + "'");
}
_tileProvider = std::shared_ptr<tileprovider::TileProvider>(
tileprovider::TileProvider::createFromDictionary(typeId, tileProviderInitDict)
);
break;
}
case layergroupid::TypeID::SolidColor:
break;
default:
throw ghoul::RuntimeError("Unable to create layer. Unknown type.");
break;
}
}
void Layer::addVisibleProperties() {
switch (type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer:
if (_tileProvider) {
addPropertySubOwner(*_tileProvider);
}
break;
case layergroupid::TypeID::SolidColor:
addProperty(_otherTypesProperties.color);
default:
break;
}
}
void Layer::removeVisibleProperties() {
switch (type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer:
if (_tileProvider) {
removePropertySubOwner(*_tileProvider);
}
break;
case layergroupid::TypeID::SolidColor:
removeProperty(_otherTypesProperties.color);
break;
default:
break;
}
}
} // namespace globebrowsing

View File

@@ -25,14 +25,17 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/tile/chunktile.h>
#include <modules/globebrowsing/rendering/layer/layeradjustment.h>
#include <modules/globebrowsing/rendering/layer/layergroupid.h>
#include <modules/globebrowsing/rendering/layer/layerrendersettings.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/properties/vectorproperty.h>
namespace openspace {
namespace globebrowsing {
@@ -41,29 +44,55 @@ namespace tileprovider {
class TileProvider;
}
/**
* Simple struct which is used to enable/disable <code>TileProvider</code>
* and associate is with a name. It also holds layer specific information
* which is used in rendering of layer.
*/
class Layer : public properties::PropertyOwner {
public:
Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict);
/**
* Properties used when the layer type is not a tile type layer. These properties
* can be added or removed depending on the layer type.
*/
struct OtherTypesProperties {
properties::Vec3Property color;
};
Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict);
ChunkTilePile getChunkTilePile(const TileIndex& tileIndex, int pileSize) const;
Tile::Status getTileStatus(const TileIndex& index) const;
bool enabled() const { return _enabled.value(); }
tileprovider::TileProvider* tileProvider() const { return _tileProvider.get(); }
const LayerRenderSettings& renderSettings() const { return _renderSettings; }
layergroupid::TypeID type() const;
layergroupid::BlendModeID blendMode() const;
TileDepthTransform depthTransform() const;
bool enabled() const;
tileprovider::TileProvider* tileProvider() const;
const OtherTypesProperties& otherTypesProperties() const;
const LayerRenderSettings& renderSettings() const;
const LayerAdjustment& layerAdjustment() const;
void onChange(std::function<void(void)> callback);
void update();
private:
layergroupid::TypeID parseTypeIdFromDictionary(const ghoul::Dictionary& initDict) const;
void initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict);
void addVisibleProperties();
void removeVisibleProperties();
properties::OptionProperty _typeOption;
properties::OptionProperty _blendModeOption;
properties::BoolProperty _enabled;
properties::TriggerProperty _reset;
layergroupid::TypeID _type;
std::shared_ptr<tileprovider::TileProvider> _tileProvider;
OtherTypesProperties _otherTypesProperties;
LayerRenderSettings _renderSettings;
};
LayerAdjustment _layerAdjustment;
const layergroupid::GroupID _layerGroupId;
std::function<void(void)> _onChangeCallback;
};
} // namespace globebrowsing
} // namespace openspace

View File

@@ -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

View File

@@ -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__

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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++) {

View File

@@ -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;
};

View File

@@ -8,6 +8,55 @@ openspace.globebrowsing.documentation = {
Name = "createHeightLayers",
Arguments = "table",
Documentation = "Creates a table used in the 'HeightLayers' of a RenderableGlobe."
},
{
Name = "createTemporalGibsGdalXml",
Arguments = "string, string, string, string, string, string",
Documentation =
"Creates an XML configuration for a temporal GIBS dataset." ..
"Arguments are: Name, Start date, end date, time resolution, time format," ..
"resolution, file format. For all specifications, see " ..
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
"Usage:" ..
"openspace.globebrowsing.addLayer(" ..
"\"Earth\"," ..
"\"ColorLayers\"," ..
"{" ..
"Type = \"TemporalTileLayer\"," ..
"Name = \"MODIS_Terra_Chlorophyll_A\"," ..
"FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(" ..
"\"MODIS_Terra_Chlorophyll_A\"," ..
"\"2013-07-02\"," ..
"\"Yesterday\"," ..
"\"1d\"," ..
"\"1km\"," ..
"\"png\"" ..
")" ..
"}" ..
")"
},
{
Name = "createGibsGdalXml",
Arguments = "string, string, string, string",
Documentation =
"Creates an XML configuration for a GIBS dataset." ..
"Arguments are: layerName, date, resolution, format." ..
"For all specifications, see " ..
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
"Usage:" ..
"openspace.globebrowsing.addLayer(" ..
"\"Earth\"," ..
"\"ColorLayers\"," ..
"{" ..
"Name = \"MODIS_Terra_Chlorophyll_A\"," ..
"FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(" ..
"\"MODIS_Terra_Chlorophyll_A\"," ..
"\"2013-07-02\"," ..
"\"1km\"," ..
"\"png\"" ..
")" ..
"}" ..
")"
}
}
@@ -31,7 +80,86 @@ end
openspace.globebrowsing.createHeightLayers = function (patches)
result = {}
for k,v in pairs(patches) do
table.insert(result, { Name = v["Name"], FilePath = v["Height"], TilePixelSize = 90, DoPreProcessing = true })
table.insert(result, { Name = v["Name"], FilePath = v["Height"], TilePixelSize = 90, PerformPreProcessing = true })
end
return result
end
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, startDate, endDate, timeResolution, resolution, format)
temporalTemplate =
"<OpenSpaceTemporalGDALDataset>" ..
"<OpenSpaceTimeStart>" .. startDate .. "</OpenSpaceTimeStart>" ..
"<OpenSpaceTimeEnd>" .. endDate .. "</OpenSpaceTimeEnd>" ..
"<OpenSpaceTimeResolution>" .. timeResolution .. "</OpenSpaceTimeResolution>" ..
"<OpenSpaceTimeIdFormat>YYYY-MM-DD</OpenSpaceTimeIdFormat>" ..
openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format) ..
"</OpenSpaceTemporalGDALDataset>"
return temporalTemplate
end
openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format)
tileLevel = 5
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
if resolution == "2km" then
tileLevel = 5
elseif resolution == "1km" then
tileLevel = 6
elseif resolution == "500m" then
tileLevel = 7
elseif resolution == "250m" then
tileLevel = 8
elseif resolution == "125m" then
tileLevel = 9
elseif resolution == "62.5m" then
tileLevel = 10
elseif resolution == "31.25m" then
tileLevel = 11
elseif resolution == "15.625m" then
tileLevel = 12
else
openspace.printError("Unknown resolution: " .. resolution)
return ""
end
rasterCount = 3
if format == "jpg" then
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
rasterCount = 1
else
rasterCount = 3
end
elseif format == "png" then
rasterCount = 4
else
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
return ""
end
gdalWmsTemplate =
"<GDAL_WMS>" ..
"<Service name=\"TMS\">" ..
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
layerName .. "/default/" .. date .. "/" .. resolution ..
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
"</Service>" ..
"<DataWindow>" ..
"<UpperLeftX>-180.0</UpperLeftX>" ..
"<UpperLeftY>90</UpperLeftY>" ..
"<LowerRightX>396.0</LowerRightX>" ..
"<LowerRightY>-198</LowerRightY>" ..
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
"<TileCountX>2</TileCountX>" ..
"<TileCountY>1</TileCountY>" ..
"<YOrigin>top</YOrigin>" ..
"</DataWindow>" ..
"<Projection>EPSG:4326</Projection>" ..
"<BlockSizeX>512</BlockSizeX>" ..
"<BlockSizeY>512</BlockSizeY>" ..
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
"<UnsafeSSL>true</UnsafeSSL>" ..
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
"</GDAL_WMS>"
return gdalWmsTemplate
end

View File

@@ -25,7 +25,7 @@
#ifndef BLENDING_HGLSL
#define BLENDING_HGLSL
vec4 blendOver(vec4 oldColor, vec4 newColor)
vec4 blendNormal(vec4 oldColor, vec4 newColor)
{
vec4 toReturn;
toReturn.rgb =

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -116,10 +116,19 @@ struct LayerSettings {
float valueBlending;
};
struct LayerAdjustment {
vec3 chromaKeyColor;
float chromaKeyTolerance;
};
struct Layer {
ChunkTilePile pile;
TileDepthTransform depthTransform;
LayerSettings settings;
LayerAdjustment adjustment;
// Other layer type properties stuff
vec3 color;
};
struct LevelWeights {

View File

@@ -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

View File

@@ -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");

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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&

View File

@@ -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;
}

View File

@@ -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);
/**

View File

@@ -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();

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