Merged master in

This commit is contained in:
Gene Payne
2022-01-25 13:10:58 -07:00
parent 3cf15920d0
commit d165c8508b
79 changed files with 3196 additions and 2567 deletions

View File

@@ -865,11 +865,11 @@ void setSgctDelegateFunctions() {
currentWindow->viewports().front()->nonLinearProjection()
) != nullptr;
};
sgctDelegate.takeScreenshot = [](bool applyWarping) {
sgctDelegate.takeScreenshot = [](bool applyWarping, std::vector<int> windowIds) {
ZoneScoped
Settings::instance().setCaptureFromBackBuffer(applyWarping);
Engine::instance().takeScreenshot();
Engine::instance().takeScreenshot(std::move(windowIds));
return Engine::instance().screenShotNumber();
};
sgctDelegate.swapBuffer = []() {

View File

@@ -7,28 +7,46 @@ local path = asset.syncedResource({
Version = 1
})
local layer = {
Identifier = "ERA5_Land_HighRes_Monthly_2M_Temperature_Temporal",
Name = "ERA5 Land HighRes Monthly 2M Temperature (Temporal)",
local layer_prototype = {
Identifier = "ERA5_Land_HighRes_Monthly_2M_Temperature_Temporal_prototype",
Name = "ERA5 Land HighRes Monthly 2M Temperature (Temporal) [Prototype]",
Type = "TemporalTileLayer",
FilePath =
"<OpenSpaceTemporalGDALDataset>" ..
"<OpenSpaceTimeStart>1981-01-01</OpenSpaceTimeStart>" ..
"<OpenSpaceTimeEnd>1990-10-01</OpenSpaceTimeEnd>" ..
"<OpenSpaceTimeResolution>1M</OpenSpaceTimeResolution>" ..
"<OpenSpaceTimeIdFormat>YYYY-MM-DD</OpenSpaceTimeIdFormat>" ..
"<OpenSpaceTransferFunction>" .. path .. "rainbow.png</OpenSpaceTransferFunction>" ..
"<OpenSpaceTimeInterpolation>linear</OpenSpaceTimeInterpolation>" ..
"<FilePath>" .. path .. "${OpenSpaceTimeId}-land.png</FilePath>" ..
"</OpenSpaceTemporalGDALDataset>",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "1981-01-01",
End = "1990-10-01"
},
TemporalResolution = "1M",
TimeFormat = "YYYY-MM-DD",
Prototype = path .. "${OpenSpaceTimeId}-land.png"
},
Interpolation = true,
Colormap = path .. "rainbow.png",
Description = [[ Temporal coverage: 01 Jan 1981 - 31 Dec 2020.]]
}
local layer_folder = {
Identifier = "ERA5_Land_HighRes_Monthly_2M_Temperature_Temporal_folder",
Name = "ERA5 Land HighRes Monthly 2M Temperature (Temporal) [Folder]",
Type = "TemporalTileLayer",
Mode = "Folder",
Folder = {
Folder = "C:/Development/sync/http/earth_textures_climate/1",
Format = "%Y-%m-%d-land.png"
},
Interpolation = true,
Colormap = path .. "rainbow.png",
Description = [[ Temporal coverage: 01 Jan 1981 - 31 Dec 2020.]]
}
asset.onInitialize(function ()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer_prototype)
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer_folder)
end)
asset.export("layer", layer)
asset.export("layer", layer_prototype)
asset.meta = {
Name = "Climate Earth Layers",
Version = "1.0",

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "AMSR2_GCOM_W1_Sea_Ice_Concentration_Temporal",
Name = "AMSR2 GCOM W1 Sea Ice Concentration (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"AMSRU2_Sea_Ice_Concentration_12km",
"2012-05-08",
"Yesterday",
"1d",
"2km",
"png"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2012-05-08",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"AMSRU2_Sea_Ice_Concentration_12km",
"2km",
"png"
)
},
Description = [[ Temporal coverage: 02 July 2012 - Present. The Advanced Microwave
Scanning Radiometer-E/Advanced Microwave Scanning Radiometer-2 (AMSR-E/AMSR2)
unified "Sea Ice Concentration (12 km)" layer displays the percent of sea ice

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "Aqua_Modis_Temporal",
Name = "Aqua Modis (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Aqua_CorrectedReflectance_TrueColor",
"2002-07-04",
"Yesterday",
"1d",
"250m",
"jpg"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2002-07-04",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Aqua_CorrectedReflectance_TrueColor",
"250m",
"jpg"
)
},
Description = [[ Temporal coverage: 03 July 2002 - Present. True Color: Red = Band 1,
Green = Band 4, Blue = Band 3. These images are called true-color or natural color
because this combination of wavelengths is similar to what the human eye would see.

View File

@@ -13,14 +13,20 @@ local layer = {
Identifier = "Temporal_VIIRS_SNPP",
Name = "Temporal VIIRS SNPP",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_CorrectedReflectance_TrueColor",
"2015-11-24",
"Today",
"1d",
"250m",
"jpg"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2015-11-24",
End = "Today"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_CorrectedReflectance_TrueColor",
"250m",
"jpg"
)
},
PadTiles = false
}
},

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "GHRSST_L4_G1SST_Sea_Surface_Temperature_Temporal",
Name = "GHRSST L4 G1SST Sea Surface Temperature (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"GHRSST_L4_G1SST_Sea_Surface_Temperature",
"2010-06-21",
"2019-12-08",
"1d",
"1km",
"png"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2010-06-21",
End = "2019-12-08"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"GHRSST_L4_G1SST_Sea_Surface_Temperature",
"1km",
"png"
)
},
Description = [[ Temporal coverage: 21 June 2010 - 08 December 2019. The imagery
resolution is 1 km, and the temporal resolution is daily.]],
Author = "NASA EOSDIS Global Imagery Browse Services"

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "GHRSST_L4_MUR_Sea_Surface_Temperature_Temporal",
Name = "GHRSST L4 MUR Sea Surface Temperature (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"GHRSST_L4_MUR_Sea_Surface_Temperature",
"2002-06-01",
"Yesterday",
"1d",
"1km",
"png"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2002-06-01",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"GHRSST_L4_MUR_Sea_Surface_Temperature",
"1km",
"png"
)
},
Description = [[ Temporal coverage: 01 June 2002 - Present. The imagery resolution
is 1 km, and the temporal resolution is daily.]]
}

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "MODIS_Terra_Chlorophyll_A_Temporal",
Name = "MODIS Terra Chlorophyll A (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2013-07-02",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Terra_Chlorophyll_A",
"2013-07-02",
"Yesterday",
"1d",
"1km",
"png"
),
)
},
Description = [[ Temporal coverage: 02 July 2013 - Present. The imagery resolution
is 1 km, and the temporal resolution is daily.]]
}

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "Terra_Modis_Temporal",
Name = "Terra Modis (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Terra_CorrectedReflectance_TrueColor",
"2000-02-24",
"Yesterday",
"1d",
"250m",
"jpg"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2000-02-24",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"MODIS_Terra_CorrectedReflectance_TrueColor",
"250m",
"jpg"
)
},
Description = [[ Temporal coverage: 02 July 2013 - Present. The imagery resolution
is 1 km, and the temporal resolution is daily.]]
}

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "VIIRS_SNPP_Temporal",
Name = "VIIRS SNPP (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_CorrectedReflectance_TrueColor",
"2015-11-24",
"Yesterday",
"1d",
"250m",
"jpg"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2015-11-24",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_CorrectedReflectance_TrueColor",
"250m",
"jpg"
)
},
Description = [[ Temporal coverage: 11 November 2015 - Present. The imagery resolution
is 0.25 km, and the temporal resolution is daily.]]
}

View File

@@ -4,14 +4,20 @@ local layer = {
Identifier = "Earth_at_Night_Temporal",
Name = "Earth at Night (Temporal)",
Type = "TemporalTileLayer",
FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_DayNightBand_ENCC",
"2012-05-08",
"Yesterday",
"1d",
"500m",
"png"
),
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2012-05-08",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_DayNightBand_ENCC",
"500m",
"png"
)
},
Description = [[ The VIIRS Nighttime Imagery (Day/Night Band, Enhanced Near Constant
Contrast) layer shows the Earth's surface and atmosphere using a sensor designed
to capture low-light emission sources, under varying illumination conditions. It

View File

@@ -20,7 +20,7 @@ asset.require("./layers/colorlayers/hirisels")
-- Height layers
asset.require("./layers/heightlayers/mola_sweden")
asset.require("./layers/heightlayers/mola_utah")
local heightLayer = asset.require("./layers/heightlayers/mdem200m")
local heightLayer = asset.require("./layers/heightlayers/MDEM200M")
asset.require("./layers/heightlayers/hirisels")
-- Overlays

View File

@@ -3,7 +3,7 @@ asset.require("./static_server")
local guiCustomization = asset.require("customization/gui")
-- Select which commit hashes to use for the frontend and backend
local frontendHash = "4fe18eea379c8493dbcb2cea6798d09a85819912"
local frontendHash = "7e513ba86b0bb989b72f22712ebf0bb5a626ba06"
local dataProvider = "data.openspaceproject.com/files/webgui"
local frontend = asset.syncedResource({

View File

@@ -76,7 +76,8 @@ struct WindowDelegate {
bool (*isFisheyeRendering)() = []() { return false; };
unsigned int (*takeScreenshot)(bool applyWarping) = [](bool) { return 0u; };
unsigned int (*takeScreenshot)(bool applyWarping, std::vector<int> windowIds) =
[](bool, std::vector<int>) { return 0u; };
void (*swapBuffer)() = []() {};

View File

@@ -148,6 +148,7 @@ private:
// Reset camera direction to the aim node.
properties::TriggerProperty _retargetAim;
properties::BoolProperty _followAnchorNodeRotation;
properties::FloatProperty _followAnchorNodeRotationDistance;
properties::FloatProperty _minimumAllowedDistance;

View File

@@ -81,6 +81,8 @@ public:
static scripting::LuaLibrary luaLibrary();
private:
void handlePathEnd();
/**
* Populate list of nodes that are relevant for collision checks, etc
*/
@@ -90,6 +92,7 @@ private:
std::unique_ptr<Path> _currentPath = nullptr;
bool _isPlaying = false;
bool _startSimulationTimeOnFinish = false;
properties::OptionProperty _defaultPathType;
properties::BoolProperty _includeRoll;

View File

@@ -28,6 +28,7 @@
#include <openspace/properties/propertyowner.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/list/intlistproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
@@ -177,6 +178,7 @@ private:
properties::BoolProperty _showVersionInfo;
properties::BoolProperty _showCameraInfo;
properties::IntListProperty _screenshotWindowIds;
properties::BoolProperty _applyWarping;
properties::BoolProperty _screenshotUseDate;
properties::BoolProperty _showFrameInformation;

View File

@@ -27,6 +27,7 @@
#include <ghoul/glm.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace openspace {

View File

@@ -27,6 +27,7 @@
#include <modules/galaxy/rendering/renderablegalaxy.h>
#include <modules/galaxy/tasks/milkywayconversiontask.h>
#include <modules/galaxy/tasks/milkywaypointsconversiontask.h>
#include <openspace/documentation/documentation.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/assert.h>
@@ -47,4 +48,10 @@ void GalaxyModule::internalInitialize(const ghoul::Dictionary&) {
fTask->registerClass<MilkywayPointsConversionTask>("MilkywayPointsConversionTask");
}
std::vector<documentation::Documentation> GalaxyModule::documentations() const {
return {
RenderableGalaxy::Documentation()
};
}
} // namespace openspace

View File

@@ -35,6 +35,8 @@ public:
GalaxyModule();
std::vector<documentation::Documentation> documentations() const override;
private:
void internalInitialize(const ghoul::Dictionary&) override;
};

View File

@@ -55,7 +55,7 @@
namespace {
constexpr int8_t CurrentCacheVersion = 1;
constexpr const char* _loggerCat = "Renderable Galaxy";
constexpr const char* _loggerCat = "RenderableGalaxy";
enum StarRenderingMethod {
Points,
@@ -125,8 +125,7 @@ namespace {
{
"Downscale",
"Downscale Factor Volume Rendering",
"This value set the downscaling factor"
" when rendering the current volume."
"This value sets the downscaling factor when rendering the current volume."
};
constexpr openspace::properties::Property::PropertyInfo NumberOfRayCastingStepsInfo =
@@ -229,6 +228,10 @@ namespace {
namespace openspace {
documentation::Documentation RenderableGalaxy::Documentation() {
return codegen::doc<Parameters>("galaxy_renderablegalaxy");
}
RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _volumeRenderingEnabled(VolumeRenderingEnabledInfo, true)

View File

@@ -54,6 +54,8 @@ public:
void render(const RenderData& data, RendererTasks& tasks) override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
private:
void renderPoints(const RenderData& data);
void renderBillboards(const RenderData& data);

View File

@@ -57,9 +57,18 @@ set(HEADER_FILES
src/skirtedgrid.h
src/tileindex.h
src/tileloadjob.h
src/tileprovider.h
src/tiletextureinitdata.h
src/timequantizer.h
src/tileprovider/defaulttileprovider.h
src/tileprovider/imagesequencetileprovider.h
src/tileprovider/singleimagetileprovider.h
src/tileprovider/sizereferencetileprovider.h
src/tileprovider/temporaltileprovider.h
src/tileprovider/texttileprovider.h
src/tileprovider/tileindextileprovider.h
src/tileprovider/tileprovider.h
src/tileprovider/tileproviderbyindex.h
src/tileprovider/tileproviderbylevel.h
)
set(SOURCE_FILES
@@ -87,9 +96,18 @@ set(SOURCE_FILES
src/skirtedgrid.cpp
src/tileindex.cpp
src/tileloadjob.cpp
src/tileprovider.cpp
src/tiletextureinitdata.cpp
src/timequantizer.cpp
src/tileprovider/defaulttileprovider.cpp
src/tileprovider/imagesequencetileprovider.cpp
src/tileprovider/singleimagetileprovider.cpp
src/tileprovider/sizereferencetileprovider.cpp
src/tileprovider/temporaltileprovider.cpp
src/tileprovider/texttileprovider.cpp
src/tileprovider/tileindextileprovider.cpp
src/tileprovider/tileprovider.cpp
src/tileprovider/tileproviderbyindex.cpp
src/tileprovider/tileproviderbylevel.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -35,7 +35,15 @@
#include <modules/globebrowsing/src/layeradjustment.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/navigation/navigationhandler.h>
@@ -236,7 +244,7 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
_tileCache = std::make_unique<cache::MemoryAwareTileCache>(_tileCacheSizeMB);
addPropertySubOwner(_tileCache.get());
tileprovider::initializeDefaultTile();
TileProvider::initializeDefaultTile();
// Convert from MB to Bytes
GdalWrapper::create(
@@ -249,10 +257,9 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
global::callback::deinitializeGL->emplace_back([]() {
ZoneScopedN("GlobeBrowsingModule")
tileprovider::deinitializeDefaultTile();
TileProvider::deinitializeDefaultTile();
});
// Render
global::callback::render->emplace_back([&]() {
ZoneScopedN("GlobeBrowsingModule")
@@ -279,46 +286,45 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
ghoul_assert(fRotation, "Rotation factory was not created");
fRotation->registerClass<globebrowsing::GlobeRotation>("GlobeRotation");
auto fTileProvider =
std::make_unique<ghoul::TemplateFactory<tileprovider::TileProvider>>();
auto fTileProvider = std::make_unique<ghoul::TemplateFactory<TileProvider>>();
ghoul_assert(fTileProvider, "TileProvider factory was not created");
fTileProvider->registerClass<tileprovider::DefaultTileProvider>(
fTileProvider->registerClass<DefaultTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::DefaultTileLayer
)]
);
fTileProvider->registerClass<tileprovider::SingleImageProvider>(
fTileProvider->registerClass<SingleImageProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::SingleImageTileLayer
)]
);
fTileProvider->registerClass<tileprovider::ImageSequenceTileProvider>(
fTileProvider->registerClass<ImageSequenceTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::ImageSequenceTileLayer
)]
);
fTileProvider->registerClass<tileprovider::TemporalTileProvider>(
fTileProvider->registerClass<TemporalTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::TemporalTileLayer
)]
);
fTileProvider->registerClass<tileprovider::TileIndexTileProvider>(
fTileProvider->registerClass<TileIndexTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::TileIndexTileLayer
)]
);
fTileProvider->registerClass<tileprovider::SizeReferenceTileProvider>(
fTileProvider->registerClass<SizeReferenceTileProvider>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::SizeReferenceTileLayer
)]
);
fTileProvider->registerClass<tileprovider::TileProviderByLevel>(
fTileProvider->registerClass<TileProviderByLevel>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::ByLevelTileLayer
)]
);
fTileProvider->registerClass<tileprovider::TileProviderByIndex>(
fTileProvider->registerClass<TileProviderByIndex>(
layergroupid::LAYER_TYPE_NAMES[static_cast<int>(
layergroupid::TypeID::ByIndexTileLayer
)]
@@ -376,12 +382,14 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
"moveLayer",
&globebrowsing::luascriptfunctions::moveLayer,
"string, string, number, number",
"Rearranges the order of a single layer in a scene graph node. The first "
"parameter specifies the scene graph node, the second parameter specifies "
"Rearranges the order of a single layer on a globe. The first parameter"
"is the identifier of the globe, the second parameter specifies "
"the name of the layer group, the third parameter is the original position "
"of the layer that should be moved and the last parameter is the new "
"position. The new position may be -1 to place the layer at the top or any "
"large number bigger than the number of layers to place it at the bottom."
"position in the list. The first position in the list has index 0, and the "
"last position is given by the number of layers minus one. The new position "
"may be -1 to place the layer at the top or any number bigger than the "
"number of layers to place it at the bottom."
},
{
"goToChunk",

View File

@@ -169,7 +169,7 @@ int moveLayer(lua_State* L) {
}
globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
lg.moveLayers(oldPosition, newPosition);
lg.moveLayer(oldPosition, newPosition);
return 0;
}

View File

@@ -1,30 +1,11 @@
openspace.globebrowsing.documentation = {
{
Name = "createTemporalGibsGdalXml",
Arguments = "string, 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. The last parameter is the temporal format and " ..
"defaults to YYYY-MM-DD. 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\"" ..
")" ..
"}" ..
")"
Arguments = "string, string, string",
Documentation = [[
Creates an XML configuration for a temporal GIBS dataset to be used in
a TemporalTileprovider
]]
},
{
Name = "createGibsGdalXml",
@@ -40,7 +21,7 @@ openspace.globebrowsing.documentation = {
"\"ColorLayers\"," ..
"{" ..
"Name = \"MODIS_Terra_Chlorophyll_A\"," ..
"FilePath = openspace.globebrowsing.createTemporalGibsGdalXml(" ..
"FilePath = openspace.globebrowsing.createGibsGdalXml(" ..
"\"MODIS_Terra_Chlorophyll_A\"," ..
"\"2013-07-02\"," ..
"\"1km\"," ..
@@ -111,21 +92,27 @@ openspace.globebrowsing.addGibsLayer = function(layer, resolution, format, start
if endDate == 'Present' then
endDate = ''
end
local xml = openspace.globebrowsing.createTemporalGibsGdalXml(layer, startDate, endDate, '1d', resolution, format)
openspace.globebrowsing.addLayer('Earth', 'ColorLayers', { Identifier = layer, Type = "TemporalTileLayer", FilePath = xml })
end
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, startDate, endDate, timeResolution, resolution, format, temporalFormat)
temporalFormat = temporalFormat or 'YYYY-MM-DD'
local temporalTemplate =
"<OpenSpaceTemporalGDALDataset>" ..
"<OpenSpaceTimeStart>" .. startDate .. "</OpenSpaceTimeStart>" ..
"<OpenSpaceTimeEnd>" .. endDate .. "</OpenSpaceTimeEnd>" ..
"<OpenSpaceTimeResolution>" .. timeResolution .. "</OpenSpaceTimeResolution>" ..
"<OpenSpaceTimeIdFormat>" .. temporalFormat .. "</OpenSpaceTimeIdFormat>" ..
openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format) ..
"</OpenSpaceTemporalGDALDataset>"
return temporalTemplate
local layer = {
Identifier = layerName,
Type = "TemporalTileLayer",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = startDate,
End = endDate
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
}
}
openspace.globebrowsing.addLayer(
'Earth',
'ColorLayers',
layer
)
end
openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format)
@@ -196,6 +183,10 @@ openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolutio
return gdalWmsTemplate
end
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, resolution, format)
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
end
openspace.globebrowsing.parseInfoFile = function (file)
-- We are loading these values from an external info file and since we are switching
-- to a strict Lua, we need to predefine these global variables

View File

@@ -26,25 +26,23 @@
uniform sampler2D prevTexture;
uniform sampler2D nextTexture;
uniform sampler2D colormapTexture;
uniform sampler1D colormapTexture;
uniform float blendFactor;
in vec2 texCoord;
Fragment getFragment() {
vec4 texel0 = texture2D(prevTexture, texCoord);
vec4 texel1 = texture2D(nextTexture, texCoord);
vec4 texel0 = texture(prevTexture, texCoord);
vec4 texel1 = texture(nextTexture, texCoord);
vec4 mixedTexture = mix(texel0, texel1, blendFactor);
Fragment frag;
if (mixedTexture.r > 0.999) {
vec2 position = vec2(mixedTexture.r - 0.01, 0.5);
frag.color = texture2D(colormapTexture, position);
frag.color = texture(colormapTexture, mixedTexture.r - 0.01);
}
else {
vec2 position = vec2(mixedTexture.r , 0.5);
frag.color = texture2D(colormapTexture, position);
frag.color = texture(colormapTexture, mixedTexture.r);
}
frag.color.a = mixedTexture.a;

View File

@@ -50,8 +50,6 @@ AsyncTileDataProvider::AsyncTileDataProvider(std::string name,
performReset(ResetRawTileDataReader::No);
}
AsyncTileDataProvider::~AsyncTileDataProvider() {} // NOLINT
const RawTileDataReader& AsyncTileDataProvider::rawTileDataReader() const {
return *_rawTileDataReader;
}

View File

@@ -50,8 +50,6 @@ public:
AsyncTileDataProvider(std::string name,
std::unique_ptr<RawTileDataReader> rawTileDataReader);
~AsyncTileDataProvider();
/**
* Creates a job which asynchronously loads a raw tile. This job is enqueued.
*/

View File

@@ -115,9 +115,8 @@ struct TileMetaData {
class Tile {
public:
/**
* Describe if this Tile is good for usage (OK) or otherwise
* the reason why it is not.
*/
* Describe if this Tile is good for usage (OK) or otherwise the reason why it is not.
*/
enum class Status {
/**
* E.g when texture data is not currently in memory.
@@ -168,7 +167,6 @@ struct ChunkTile {
//using ChunkTilePile = std::vector<ChunkTile>;
// The ChunkTilePile either contains 1 or 3 ChunkTile, depending on if layer-blending is
// enabled. If it is enabled, we need the two adjacent levels, if it is not enabled, only
// the current layer is needed

View File

@@ -286,13 +286,13 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
_reset.onChange([&]() {
if (_tileProvider) {
tileprovider::reset(*_tileProvider);
_tileProvider->reset();
}
});
_remove.onChange([&]() {
if (_tileProvider) {
tileprovider::reset(*_tileProvider);
_tileProvider->reset();
_parent.deleteLayer(identifier());
}
});
@@ -360,13 +360,13 @@ void Layer::initialize() {
ZoneScoped
if (_tileProvider) {
tileprovider::initialize(*_tileProvider);
_tileProvider->initialize();
}
}
void Layer::deinitialize() {
if (_tileProvider) {
tileprovider::deinitialize(*_tileProvider);
_tileProvider->deinitialize();
}
}
@@ -374,7 +374,7 @@ ChunkTilePile Layer::chunkTilePile(const TileIndex& tileIndex, int pileSize) con
ZoneScoped
if (_tileProvider) {
return tileprovider::chunkTilePile(*_tileProvider, tileIndex, pileSize);
return _tileProvider->chunkTilePile(tileIndex, pileSize);
}
else {
ChunkTilePile chunkTilePile;
@@ -390,7 +390,7 @@ ChunkTilePile Layer::chunkTilePile(const TileIndex& tileIndex, int pileSize) con
Tile::Status Layer::tileStatus(const TileIndex& index) const {
return _tileProvider ?
tileprovider::tileStatus(*_tileProvider, index) :
_tileProvider->tileStatus(index) :
Tile::Status::Unavailable;
}
@@ -404,7 +404,7 @@ layergroupid::BlendModeID Layer::blendMode() const {
TileDepthTransform Layer::depthTransform() const {
return _tileProvider ?
tileprovider::depthTransform(*_tileProvider) :
_tileProvider->depthTransform() :
TileDepthTransform{ 1.f, 0.f };
}
@@ -416,7 +416,7 @@ bool Layer::enabled() const {
return _enabled;
}
tileprovider::TileProvider* Layer::tileProvider() const {
TileProvider* Layer::tileProvider() const {
return _tileProvider.get();
}
@@ -440,7 +440,7 @@ void Layer::update() {
ZoneScoped
if (_tileProvider) {
tileprovider::update(*_tileProvider);
_tileProvider->update();
}
}
@@ -483,7 +483,7 @@ void Layer::initializeBasedOnType(layergroupid::TypeID id, ghoul::Dictionary ini
std::string name = initDict.value<std::string>(KeyName);
LDEBUG("Initializing tile provider for layer: '" + name + "'");
}
_tileProvider = tileprovider::createFromDictionary(id, std::move(initDict));
_tileProvider = TileProvider::createFromDictionary(id, std::move(initDict));
break;
}
case layergroupid::TypeID::SolidColor: {

View File

@@ -30,7 +30,7 @@
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/layeradjustment.h>
#include <modules/globebrowsing/src/layerrendersettings.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
@@ -40,8 +40,7 @@ namespace openspace::globebrowsing {
struct LayerGroup;
struct TileIndex;
namespace tileprovider { struct TileProvider; }
struct TileProvider;
class Layer : public properties::PropertyOwner {
public:
@@ -59,7 +58,7 @@ public:
TileDepthTransform depthTransform() const;
void setEnabled(bool enabled);
bool enabled() const;
tileprovider::TileProvider* tileProvider() const;
TileProvider* tileProvider() const;
glm::vec3 solidColor() const;
const LayerRenderSettings& renderSettings() const;
const LayerAdjustment& layerAdjustment() const;
@@ -89,7 +88,7 @@ private:
properties::StringProperty _guiDescription;
layergroupid::TypeID _type;
std::unique_ptr<tileprovider::TileProvider> _tileProvider;
std::unique_ptr<TileProvider> _tileProvider;
properties::Vec3Property _solidColor;
LayerRenderSettings _renderSettings;
LayerAdjustment _layerAdjustment;

View File

@@ -74,7 +74,7 @@ documentation::Documentation LayerAdjustment::Documentation() {
}
LayerAdjustment::LayerAdjustment()
: properties::PropertyOwner({ "adjustment" })
: properties::PropertyOwner({ "Adjustment" })
, _chromaKeyColor(ChromaKeyColorInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f))
, _chromaKeyTolerance(ChromaKeyToleranceInfo, 0.f, 0.f, 1.f)
, _typeOption(TypeInfo, properties::OptionProperty::DisplayType::Dropdown)

View File

@@ -36,8 +36,6 @@ namespace openspace::documentation { struct Documentation; }
namespace openspace::globebrowsing {
namespace tileprovider { struct TileProvider; }
class LayerAdjustment : public properties::PropertyOwner {
public:
LayerAdjustment();

View File

@@ -212,16 +212,9 @@ void LayerGroup::deleteLayer(const std::string& layerName) {
LERROR("Could not find layer " + layerName);
}
void LayerGroup::moveLayers(int oldPosition, int newPosition) {
void LayerGroup::moveLayer(int oldPosition, int newPosition) {
oldPosition = std::max(0, oldPosition);
newPosition = std::min(newPosition, static_cast<int>(_layers.size()));
// We need to adjust the new position as we first delete the old position, if this
// position is before the new position we have reduced the size of the vector by 1 and
// need to adapt where we want to put the value in
if (oldPosition < newPosition) {
newPosition -= 1;
}
newPosition = std::min(newPosition, static_cast<int>(_layers.size() - 1));
// There are two synchronous vectors that we have to update here. The _layers vector
// is used to determine the order while rendering, the _subowners is the order in

View File

@@ -33,8 +33,7 @@
namespace openspace::globebrowsing {
class Layer;
namespace tileprovider { struct TileProvider; }
struct TileProvider;
/**
* Convenience class for dealing with multiple <code>Layer</code>s.
@@ -52,7 +51,7 @@ struct LayerGroup : public properties::PropertyOwner {
Layer* addLayer(const ghoul::Dictionary& layerDict);
void deleteLayer(const std::string& layerName);
void moveLayers(int oldPosition, int newPosition);
void moveLayer(int oldPosition, int newPosition);
/// @returns const vector of all layers
std::vector<Layer*> layers() const;

View File

@@ -26,7 +26,7 @@
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
@@ -155,7 +155,7 @@ void LayerManager::reset(bool includeDisabled) {
for (std::unique_ptr<LayerGroup>& layerGroup : _layerGroups) {
for (Layer* layer : layerGroup->layers()) {
if ((layer->enabled() || includeDisabled) && layer->tileProvider()) {
tileprovider::reset(*layer->tileProvider());
layer->tileProvider()->reset();
}
}
}

View File

@@ -30,7 +30,7 @@
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <modules/globebrowsing/src/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
@@ -322,7 +322,7 @@ ChunkTileVector tilesAndSettingsUnsorted(const LayerGroup& layerGroup,
for (Layer* layer : layerGroup.activeLayers()) {
if (layer->tileProvider()) {
tilesAndSettings.emplace_back(
tileprovider::chunkTile(*layer->tileProvider(), tileIndex),
layer->tileProvider()->chunkTile(tileIndex),
&layer->renderSettings()
);
}
@@ -403,7 +403,7 @@ bool colorAvailableForChunk(const Chunk& chunk, const LayerManager& lm) {
for (Layer* lyr : colorLayers.activeLayers()) {
if (lyr->tileProvider()) {
ChunkTile t = tileprovider::chunkTile(*lyr->tileProvider(), chunk.tileIndex);
ChunkTile t = lyr->tileProvider()->chunkTile(chunk.tileIndex);
if (t.tile.status == Tile::Status::Unavailable) {
return false;
}
@@ -1886,16 +1886,15 @@ float RenderableGlobe::getHeight(const glm::dvec3& position) const {
_layerManager.layerGroup(layergroupid::GroupID::HeightLayers).activeLayers();
for (Layer* layer : heightMapLayers) {
tileprovider::TileProvider* tileProvider = layer->tileProvider();
TileProvider* tileProvider = layer->tileProvider();
if (!tileProvider) {
continue;
}
// Transform the uv coordinates to the current tile texture
const ChunkTile chunkTile = tileprovider::chunkTile(*tileProvider, tileIndex);
const ChunkTile chunkTile = tileProvider->chunkTile(tileIndex);
const Tile& tile = chunkTile.tile;
const TileUvTransform& uvTransform = chunkTile.uvTransform;
const TileDepthTransform& depthTransform =
tileprovider::depthTransform(*tileProvider);
const TileDepthTransform& depthTransform = tileProvider->depthTransform();
if (tile.status != Tile::Status::OK) {
return 0;
}
@@ -1953,10 +1952,10 @@ float RenderableGlobe::getHeight(const glm::dvec3& position) const {
std::isnan(sample11);
const bool anySampleIsNoData =
sample00 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample01 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample10 == tileprovider::noDataValueAsFloat(*tileProvider) ||
sample11 == tileprovider::noDataValueAsFloat(*tileProvider);
sample00 == tileProvider->noDataValueAsFloat() ||
sample01 == tileProvider->noDataValueAsFloat() ||
sample10 == tileProvider->noDataValueAsFloat() ||
sample11 == tileProvider->noDataValueAsFloat();
if (anySampleIsNaN || anySampleIsNoData) {
continue;

File diff suppressed because it is too large Load Diff

View File

@@ -1,292 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILE_PROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_PROVIDER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/ellipsoid.h>
#include <modules/globebrowsing/src/layergroupid.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <modules/globebrowsing/src/timequantizer.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <unordered_map>
#include <ghoul/opengl/programobject.h>
struct CPLXMLNode;
namespace ghoul::fontrendering {
class Font;
class FontRenderer;
} // namespace ghoul::fontrendering
namespace openspace { class PixelBuffer; }
namespace openspace::globebrowsing {
class AsyncTileDataProvider;
struct RawTile;
struct TileIndex;
namespace cache { class MemoryAwareTileCache; }
} // namespace openspace::globebrowsing
namespace openspace::globebrowsing::tileprovider {
enum class Type {
DefaultTileProvider = 0,
SingleImageTileProvider,
ImageSequenceTileProvider,
SizeReferenceTileProvider,
TemporalTileProvider,
TileIndexTileProvider,
ByIndexTileProvider,
ByLevelTileProvider,
InterpolateTileProvider
};
struct TileProvider : public properties::PropertyOwner {
static unsigned int NumTileProviders;
Type type;
TileProvider();
virtual ~TileProvider() = default;
std::string name;
uint16_t uniqueIdentifier = 0;
bool isInitialized = false;
};
struct DefaultTileProvider : public TileProvider {
DefaultTileProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<AsyncTileDataProvider> asyncTextureDataProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
properties::StringProperty filePath;
properties::IntProperty tilePixelSize;
layergroupid::GroupID layerGroupID = layergroupid::GroupID::Unknown;
bool performPreProcessing = false;
bool padTiles = true;
};
struct SingleImageProvider : public TileProvider {
SingleImageProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<ghoul::opengl::Texture> tileTexture;
Tile tile;
properties::StringProperty filePath;
};
struct InterpolateTileProvider : public TileProvider {
InterpolateTileProvider(const ghoul::Dictionary&);
virtual ~InterpolateTileProvider();
Tile calculateTile(const TileIndex&);
TileProvider* before = nullptr;
TileProvider* t1 = nullptr;
TileProvider* t2 = nullptr;
TileProvider* future = nullptr;
float factor = 1.f;
GLuint vaoQuad = 0;
GLuint vboQuad = 0;
GLuint fbo = 0;
std::string colormap;
std::unique_ptr<ghoul::opengl::ProgramObject> shaderProgram;
std::unique_ptr<SingleImageProvider> singleImageProvider;
cache::MemoryAwareTileCache* tileCache = nullptr;
};
struct TextTileProvider : public TileProvider {
TextTileProvider(TileTextureInitData initData, size_t fontSize = 48);
const TileTextureInitData initData;
std::unique_ptr<ghoul::fontrendering::FontRenderer> fontRenderer;
std::shared_ptr<ghoul::fontrendering::Font> font;
size_t fontSize = 0;
std::string text;
glm::vec2 textPosition = glm::vec2(0.f);
glm::vec4 textColor = glm::vec4(0.f);
GLuint fbo = 0;
cache::MemoryAwareTileCache* tileCache;
};
struct SizeReferenceTileProvider : public TextTileProvider {
SizeReferenceTileProvider(const ghoul::Dictionary& dictionary);
Ellipsoid ellipsoid;
};
struct TileIndexTileProvider : public TextTileProvider {
TileIndexTileProvider(const ghoul::Dictionary& dictionary);
};
struct TileProviderByIndex : public TileProvider {
TileProviderByIndex(const ghoul::Dictionary& dictionary);
std::unordered_map<
TileIndex::TileHashKey, std::unique_ptr<TileProvider>
> tileProviderMap;
std::unique_ptr<TileProvider> defaultTileProvider;
};
struct TileProviderByLevel : public TileProvider {
TileProviderByLevel(const ghoul::Dictionary& dictionary);
std::vector<int> providerIndices;
std::vector<std::unique_ptr<TileProvider>> levelTileProviders;
};
struct ImageSequenceTileProvider : public TileProvider {
ImageSequenceTileProvider(const ghoul::Dictionary& dictionary);
std::unique_ptr<DefaultTileProvider> currentTileProvider = nullptr;
properties::IntProperty index;
properties::StringProperty currentImage;
properties::StringProperty folderPath;
ghoul::Dictionary initDict;
bool isImageDirty = true;
std::vector<std::filesystem::path> imagePaths;
};
/**
* Provide <code>Tile</code>s from web map services that have temporal resolution.
*
* TemporalTileProviders are instantiated using a ghoul::Dictionary,
* and must define a filepath to a Openspace Temporal dataset description file.
* This is an xml-file that defines the same meta data as the GDAL wms description
* (http://www.gdal.org/frmt_wms.html), but augmented with some
* extra tags describing the temporal properties of the dataset. See
* <code>TemporalTileProvider::TemporalXMLTags</code>
*
*/
struct TemporalTileProvider : public TileProvider {
enum class TimeFormatType {
YYYY_MM_DD = 0,
YYYYMMDD_hhmmss,
YYYYMMDD_hhmm,
YYYY_MM_DDThhColonmmColonssZ,
YYYY_MM_DDThh_mm_ssZ
};
using TimeKey = std::string;
TemporalTileProvider(const ghoul::Dictionary& dictionary);
ghoul::Dictionary initDict;
properties::StringProperty filePath;
properties::BoolProperty useFixedTime;
properties::StringProperty fixedTime;
std::string gdalXmlTemplate;
std::unordered_map<TimeKey, std::unique_ptr<TileProvider>> tileProviderMap;
bool interpolation = false;
TileProvider* currentTileProvider = nullptr;
double startTimeJ2000;
double endTimeJ2000;
TimeFormatType timeFormat;
TimeQuantizer timeQuantizer;
std::string colormap;
std::string myResolution;
std::unique_ptr<InterpolateTileProvider> interpolateTileProvider;
};
void initializeDefaultTile();
void deinitializeDefaultTile();
std::unique_ptr<TileProvider> createFromDictionary(layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary);
bool initialize(TileProvider& tp);
bool deinitialize(TileProvider& tp);
Tile tile(TileProvider& tp, const TileIndex& tileIndex);
ChunkTile chunkTile(TileProvider& tp, TileIndex tileIndex, int parents = 0,
int maxParents = 1337);
ChunkTilePile chunkTilePile(TileProvider& tp, TileIndex tileIndex, int pileSize);
/**
* Returns the status of a <code>Tile</code>. The <code>Tile::Status</code>
* corresponds the <code>Tile</code> that would be returned
* if the function <code>tile</code> would be invoked with the same
* <code>TileIndex</code> argument at this point in time.
*/
Tile::Status tileStatus(TileProvider& tp, const TileIndex& index);
/**
* Get the associated depth transform for this TileProvider.
* This is necessary for TileProviders serving height map
* data, in order to correcly map pixel values to meters.
*/
TileDepthTransform depthTransform(TileProvider& tp);
/**
* This method should be called once per frame. Here, TileProviders
* are given the opportunity to update their internal state.
*/
void update(TileProvider& tp);
/**
* Provides a uniform way of all TileProviders to reload or
* restore all of its internal state. This is mainly useful
* for debugging purposes.
*/
void reset(TileProvider& tp);
/**
* \returns The maximum level as defined by <code>TileIndex</code>
* that this TileProvider is able provide.
*/
int maxLevel(TileProvider& tp);
/**
* \returns the no data value for the dataset. Default is the minimum float avalue.
*/
float noDataValueAsFloat(TileProvider& tp);
} // namespace openspace::globebrowsing::tileprovider
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE_PROVIDER___H__

View File

@@ -0,0 +1,204 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <optional>
namespace {
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"The path of the GDAL file or the image file that is to be used in this tile "
"provider."
};
constexpr openspace::properties::Property::PropertyInfo TilePixelSizeInfo = {
"TilePixelSize",
"Tile Pixel Size",
"This value is the preferred size (in pixels) for each tile. Choosing the right "
"value is a tradeoff between more efficiency (larger images) and better quality "
"(smaller images). The tile pixel size has to be smaller than the size of the "
"complete image if a single image is used."
};
struct [[codegen::Dictionary(DefaultTileProvider)]] Parameters {
// User-facing name of this tile provider
std::optional<std::string> name;
// The path to the file that is loaded by GDAL to produce tiles. Since GDAL
// supports it, this can also be the textual representation of the contents of a
// loading file
std::string filePath;
// The layer into which this tile provider is loaded
int layerGroupID;
// [[codegen::verbatim(TilePixelSizeInfo.description)]]
std::optional<int> tilePixelSize;
// Determines whether the tiles should have a padding zone around it, making the
// interpolation between tiles more pleasant
std::optional<bool> padTiles;
// Determines if the tiles should be preprocessed before uploading to the GPU
std::optional<bool> performPreProcessing;
};
#include "defaulttileprovider_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary)
: _filePath(FilePathInfo, "")
, _tilePixelSize(TilePixelSizeInfo, 32, 32, 2048)
{
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
name = p.name.value_or("Name unspecified");
std::string _loggerCat = "DefaultTileProvider (" + name + ")";
// 1. Get required Keys
_filePath = p.filePath;
_layerGroupID = layergroupid::GroupID(p.layerGroupID);
// 2. Initialize default values for any optional Keys
// getValue does not work for integers
int pixelSize = p.tilePixelSize.value_or(0);
_padTiles = p.padTiles.value_or(_padTiles);
// Only preprocess height layers by default
switch (_layerGroupID) {
case layergroupid::GroupID::HeightLayers: _performPreProcessing = true; break;
default: _performPreProcessing = false; break;
}
_performPreProcessing = p.performPreProcessing.value_or(_performPreProcessing);
TileTextureInitData initData(
tileTextureInitData(_layerGroupID, _padTiles, pixelSize)
);
_tilePixelSize = initData.dimensions.x;
initAsyncTileDataReader(initData);
addProperty(_filePath);
addProperty(_tilePixelSize);
}
void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData) {
ZoneScoped
_asyncTextureDataProvider = std::make_unique<AsyncTileDataProvider>(
name,
std::make_unique<RawTileDataReader>(
_filePath,
initData,
RawTileDataReader::PerformPreprocessing(_performPreProcessing)
)
);
}
Tile DefaultTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
ghoul_assert(_asyncTextureDataProvider, "No data provider");
if (tileIndex.level > maxLevel()) {
return Tile{ nullptr, std::nullopt, Tile::Status::OutOfRange };
}
const cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
cache::MemoryAwareTileCache* tileCache =
global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
Tile tile = tileCache->get(key);
if (!tile.texture) {
_asyncTextureDataProvider->enqueueTileIO(tileIndex);
}
return tile;
}
Tile::Status DefaultTileProvider::tileStatus(const TileIndex& index) {
ghoul_assert(_asyncTextureDataProvider, "No data provider");
const RawTileDataReader& reader = _asyncTextureDataProvider->rawTileDataReader();
if (index.level > reader.maxChunkLevel()) {
return Tile::Status::OutOfRange;
}
const cache::ProviderTileKey key = { index, uniqueIdentifier };
cache::MemoryAwareTileCache* tileCache =
global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
return tileCache->get(key).status;
}
TileDepthTransform DefaultTileProvider::depthTransform() {
ghoul_assert(_asyncTextureDataProvider, "No data provider");
return _asyncTextureDataProvider->rawTileDataReader().depthTransform();
}
void DefaultTileProvider::update() {
ghoul_assert(_asyncTextureDataProvider, "No data provider");
_asyncTextureDataProvider->update();
std::optional<RawTile> tile = _asyncTextureDataProvider->popFinishedRawTile();
if (tile) {
const cache::ProviderTileKey key = { tile->tileIndex, uniqueIdentifier };
cache::MemoryAwareTileCache* tileCache =
global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
ghoul_assert(!tileCache->exist(key), "Tile must not be existing in cache");
tileCache->createTileAndPut(key, std::move(*tile));
}
if (_asyncTextureDataProvider->shouldBeDeleted()) {
initAsyncTileDataReader(
tileTextureInitData(_layerGroupID, _padTiles, _tilePixelSize)
);
}
}
void DefaultTileProvider::reset() {
global::moduleEngine->module<GlobeBrowsingModule>()->tileCache()->clear();
ghoul_assert(_asyncTextureDataProvider, "No data provider");
_asyncTextureDataProvider->prepareToBeDeleted();
}
int DefaultTileProvider::maxLevel() {
ghoul_assert(_asyncTextureDataProvider, "No data provider");
return _asyncTextureDataProvider->rawTileDataReader().maxChunkLevel();
}
float DefaultTileProvider::noDataValueAsFloat() {
ghoul_assert(_asyncTextureDataProvider, "No data provider");
return _asyncTextureDataProvider->noDataValueAsFloat();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,61 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/asynctiledataprovider.h>
#include <memory>
namespace openspace::globebrowsing {
class DefaultTileProvider : public TileProvider {
public:
DefaultTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
void initAsyncTileDataReader(TileTextureInitData initData);
properties::StringProperty _filePath;
properties::IntProperty _tilePixelSize;
std::unique_ptr<AsyncTileDataProvider> _asyncTextureDataProvider;
layergroupid::GroupID _layerGroupID = layergroupid::GroupID::Unknown;
bool _performPreProcessing = false;
bool _padTiles = true;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__

View File

@@ -0,0 +1,158 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <openspace/documentation/documentation.h>
#include <optional>
namespace {
constexpr openspace::properties::Property::PropertyInfo IndexInfo = {
"Index",
"Index",
"The index into the list of images that is used to pick the currently displayed "
"image"
};
constexpr openspace::properties::Property::PropertyInfo CurrentImageInfo = {
"CurrentImage",
"Current Image",
"The read-only value of the currently selected image"
};
constexpr openspace::properties::Property::PropertyInfo FolderPathInfo = {
"FolderPath",
"Folder Path",
"The path that is used to look for images for this image provider. The path must "
"point to an existing folder that contains images"
};
struct [[codegen::Dictionary(ImageSequenceTileProvider)]] Parameters {
// [[codegen::verbatim(IndexInfo.description)]]
std::optional<int> index;
// [[codegen::verbatim(FolderPathInfo.description)]]
std::filesystem::path folderPath [[codegen::directory()]];
};
#include "imagesequencetileprovider_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
ImageSequenceTileProvider::ImageSequenceTileProvider(const ghoul::Dictionary& dictionary)
: _index(IndexInfo, 0)
, _currentImage(CurrentImageInfo)
, _folderPath(FolderPathInfo)
, _initDict(dictionary)
{
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
_index = p.index.value_or(_index);
_index.setMinValue(0);
_index.onChange([this]() { _isImageDirty = true; });
addProperty(_index);
_currentImage.setReadOnly(true);
addProperty(_currentImage);
_folderPath = p.folderPath.string();
addProperty(_folderPath);
reset();
}
Tile ImageSequenceTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
return _currentTileProvider ? _currentTileProvider->tile(tileIndex) : Tile();
}
Tile::Status ImageSequenceTileProvider::tileStatus(const TileIndex& index) {
return _currentTileProvider ?
_currentTileProvider->tileStatus(index) :
Tile::Status::Unavailable;
}
TileDepthTransform ImageSequenceTileProvider::depthTransform() {
if (_currentTileProvider) {
return _currentTileProvider->depthTransform();
}
else {
return { 1.f, 0.f };
}
}
void ImageSequenceTileProvider::update() {
if (_isImageDirty && !_imagePaths.empty() &&
_index >= 0 && _index < _imagePaths.size())
{
if (_currentTileProvider) {
_currentTileProvider->deinitialize();
}
std::string p = _imagePaths[_index].string();
_currentImage = p;
_initDict.setValue("FilePath", p);
_currentTileProvider = std::make_unique<DefaultTileProvider>(_initDict);
_currentTileProvider->initialize();
_isImageDirty = false;
}
if (_currentTileProvider) {
_currentTileProvider->update();
}
}
void ImageSequenceTileProvider::reset() {
namespace fs = std::filesystem;
std::string path = _folderPath;
_imagePaths.clear();
for (const fs::directory_entry& p : fs::directory_iterator(path)) {
if (p.is_regular_file()) {
_imagePaths.push_back(p.path());
}
}
_index = 0;
_index.setMaxValue(static_cast<int>(_imagePaths.size() - 1));
if (_currentTileProvider) {
_currentTileProvider->reset();
}
}
int ImageSequenceTileProvider::maxLevel() {
return _currentTileProvider ? _currentTileProvider->maxLevel() : 0;
}
float ImageSequenceTileProvider::noDataValueAsFloat() {
return _currentTileProvider ?
_currentTileProvider->noDataValueAsFloat() :
std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,60 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
namespace openspace::globebrowsing {
class ImageSequenceTileProvider : public TileProvider {
public:
ImageSequenceTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
std::unique_ptr<DefaultTileProvider> _currentTileProvider = nullptr;
properties::IntProperty _index;
properties::StringProperty _currentImage;
properties::StringProperty _folderPath;
ghoul::Dictionary _initDict;
bool _isImageDirty = true;
std::vector<std::filesystem::path> _imagePaths;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__IMAGESEQUENCETILEPROVIDER___H__

View File

@@ -0,0 +1,100 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/singleimagetileprovider.h>
#include <openspace/documentation/documentation.h>
#include <ghoul/io/texture/texturereader.h>
namespace {
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"The file path that is used for this image provider. The file must point to an "
"image that is then loaded and used for all tiles."
};
struct [[codegen::Dictionary(SingleImageProvider)]] Parameters {
// [[codegen::verbatim(FilePathInfo.description)]]
std::string filePath;
};
#include "singleimagetileprovider_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary)
: _filePath(FilePathInfo)
{
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
_filePath = p.filePath;
addProperty(_filePath);
reset();
}
Tile SingleImageProvider::tile(const TileIndex&) {
ZoneScoped
return _tile;
}
Tile::Status SingleImageProvider::tileStatus(const TileIndex&) {
return _tile.status;
}
TileDepthTransform SingleImageProvider::depthTransform() {
return { 0.f, 1.f };
}
void SingleImageProvider::update() {}
void SingleImageProvider::reset() {
if (_filePath.value().empty()) {
return;
}
_tileTexture = ghoul::io::TextureReader::ref().loadTexture(_filePath, 2);
if (!_tileTexture) {
throw ghoul::RuntimeError(
fmt::format("Unable to load texture '{}'", _filePath.value())
);
}
_tileTexture->uploadTexture();
_tileTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
_tile = Tile{ _tileTexture.get(), std::nullopt, Tile::Status::OK };
}
int SingleImageProvider::maxLevel() {
return 1337; // unlimited
}
float SingleImageProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,53 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
class SingleImageProvider : public TileProvider {
public:
SingleImageProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
properties::StringProperty _filePath;
std::unique_ptr<ghoul::opengl::Texture> _tileTexture;
Tile _tile;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SINGLEIMAGETILEPROVIDER___H__

View File

@@ -0,0 +1,121 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <ghoul/font/fontmanager.h>
#include <optional>
#include <variant>
namespace {
struct [[codegen::Dictionary(SizeReferenceTileProvider)]] Parameters {
std::optional<std::variant<glm::dvec3, double>> radii;
};
#include "sizereferencetileprovider_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary)
: TextTileProvider(tileTextureInitData(layergroupid::GroupID::ColorLayers, false))
{
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
font = global::fontManager->font("Mono", static_cast<float>(fontSize));
if (p.radii.has_value()) {
if (std::holds_alternative<glm::dvec3>(*p.radii)) {
_ellipsoid = std::get<glm::dvec3>(*p.radii);
}
else {
const double r = std::get<double>(*p.radii);
_ellipsoid = glm::dvec3(r, r, r);
}
}
}
Tile SizeReferenceTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
const GeodeticPatch patch(tileIndex);
const bool aboveEquator = patch.isNorthern();
const double lat = aboveEquator ? patch.minLat() : patch.maxLat();
const double lon1 = patch.minLon();
const double lon2 = patch.maxLon();
int l = static_cast<int>(_ellipsoid.longitudalDistance(lat, lon1, lon2));
const bool useKm = l > 9999;
if (useKm) {
l /= 1000;
}
l = static_cast<int>(std::round(l));
if (useKm) {
l *= 1000;
}
double tileLongitudalLength = l;
const char* unit;
if (tileLongitudalLength > 9999) {
tileLongitudalLength *= 0.001;
unit = "km";
}
else {
unit = "m";
}
std::string text = fmt::format(" {:.0f} {:s}", tileLongitudalLength, unit);
glm::vec2 textPosition = {
0.f,
aboveEquator ?
fontSize / 2.f :
initData.dimensions.y - 3.f * fontSize / 2.f
};
return TextTileProvider::renderTile(tileIndex, text, textPosition, glm::vec4(1.f));
}
Tile::Status SizeReferenceTileProvider::tileStatus(const TileIndex& index) {
return Tile::Status::OK;
}
TileDepthTransform SizeReferenceTileProvider::depthTransform() {
return { 0.f, 1.f };
}
void SizeReferenceTileProvider::update() {}
int SizeReferenceTileProvider::maxLevel() {
return 1337; // unlimited
}
float SizeReferenceTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/texttileprovider.h>
namespace openspace::globebrowsing {
class SizeReferenceTileProvider : public TextTileProvider {
public:
SizeReferenceTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
Ellipsoid _ellipsoid;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__SIZEREFERENCETILEPROVIDER___H__

View File

@@ -0,0 +1,822 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/memorymanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/textureunit.h>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
namespace {
constexpr const char* KeyBasePath = "BasePath";
constexpr const char* TimePlaceholder = "${OpenSpaceTimeId}";
constexpr openspace::properties::Property::PropertyInfo FilePathInfo = {
"FilePath",
"File Path",
"This is the path to the XML configuration file that describes the temporal tile "
"information."
};
constexpr openspace::properties::Property::PropertyInfo UseFixedTimeInfo = {
"UseFixedTime",
"Use Fixed Time",
"If this value is enabled, the time-varying timevarying dataset will always use "
"the time that is specified in the 'FixedTime' property, rather than using the "
"actual time from OpenSpace"
};
constexpr openspace::properties::Property::PropertyInfo FixedTimeInfo = {
"FixedTime",
"Fixed Time",
"If the 'UseFixedTime' is enabled, this time will be used instead of the actual "
"time taken from OpenSpace for the displayed tiles."
};
struct [[codegen::Dictionary(TemporalTileProvider)]] Parameters {
// [[codegen::verbatim(UseFixedTimeInfo.description)]]
std::optional<bool> useFixedTime;
// [[codegen::verbatim(FixedTimeInfo.description)]]
std::optional<std::string> fixedTime;
enum class Mode {
Prototyped,
Folder
};
// The mode that his temporal tile provider operates in. In the `Prototyped` mode,
// a given start and end time, temporal resolution, and perscriptive time format
// is used to generate the information used by GDAL to access the data. In the
// `folder` method, a folder and a time format is provided and each file in the
// folder is scanned using the time format instead
Mode mode;
struct Prototyped {
struct Time {
// The (inclusive) starting time of the temporal image range
std::string start;
// The (inclusive) ending time of the temporal image range
std::string end;
};
// The starting and ending times for the range of values
Time time;
// The temporal resolution between each image
std::string temporalResolution;
// The specification of the date format that is used in the tile provider. The
// time format must be specified in a manner appropriate for the SPICE
// function `timout_c`.
// https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html
std::string timeFormat;
// The text that will be used as the prototype to generate the data to load
// the image layer. Any occurance of `${OpenSpaceTimeId}` in this prototype
// is replaced with the current date according to the remaining information
// such as the resolution and the format and the resulting text is used to
// load the corresponding images
std::string prototype;
};
std::optional<Prototyped> prototyped;
struct Folder {
// The folder that is parsed for files. Every file in the provided directory
// is checked against the provided format and added if it adheres to said
// format
std::filesystem::path folder [[codegen::directory()]];
// The format of files that is pared in the provided folder. The format string
// has to be compatible to the C++ function get_time.
// https://en.cppreference.com/w/cpp/io/manip/get_time
std::string format;
};
std::optional<Folder> folder;
// Determines whether this tile provider should interpolate between two adjacent
// layers
std::optional<bool> interpolation;
// If provided, the tile provider will use this color map to convert a greyscale
// image to color
std::optional<std::string> colormap;
};
#include "temporaltileprovider_codegen.cpp"
std::string_view timeStringify(const std::string& format, const openspace::Time& t) {
ZoneScoped
constexpr const int BufferSize = 64;
ghoul_assert(format.size() < BufferSize, "Format string too long");
using namespace openspace;
char FormatBuf[BufferSize];
std::memset(FormatBuf, '\0', BufferSize);
std::memcpy(FormatBuf, format.c_str(), format.size());
char* OutBuf = reinterpret_cast<char*>(
global::memoryManager->TemporaryMemory.allocate(BufferSize)
);
std::memset(OutBuf, '\0', BufferSize);
const double time = t.j2000Seconds();
SpiceManager::ref().dateFromEphemerisTime(time, OutBuf, BufferSize, FormatBuf);
return std::string_view(OutBuf, format.size());
}
} // namespace
namespace openspace::globebrowsing {
TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
: _initDict(dictionary)
, _useFixedTime(UseFixedTimeInfo, false)
, _fixedTime(FixedTimeInfo)
{
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
// Make sure that the user provided the data that they requested. The mode parameter
// is a required one and these two if statements tie the table requirement to the mode
if (p.mode == Parameters::Mode::Folder && !p.folder.has_value()) {
throw ghoul::RuntimeError(
"When selecting the `Folder` mode, a `Folder` table must be specified"
);
}
if (p.mode == Parameters::Mode::Prototyped && !p.prototyped.has_value()) {
throw ghoul::RuntimeError(
"When selecting the `Prototyped` mode, a `Prototyped` table must be specified"
);
}
_useFixedTime = p.useFixedTime.value_or(_useFixedTime);
_useFixedTime.onChange([this]() { _fixedTimeDirty = true; });
addProperty(_useFixedTime);
_fixedTime = p.fixedTime.value_or(_fixedTime);
_fixedTime.onChange([this]() { _fixedTimeDirty = true; });
addProperty(_fixedTime);
_colormap = p.colormap.value_or(_colormap);
if (p.prototyped.has_value()) {
_mode = Mode::Prototype;
Time start = Time(p.prototyped->time.start);
Time end = Time::now();
_prototyped.startTimeJ2000 = start.j2000Seconds();
_prototyped.endTimeJ2000 = Time(p.prototyped->time.end).j2000Seconds();
if (p.prototyped->time.end == "Yesterday") {
end.advanceTime(-60.0 * 60.0 * 24.0); // Go back one day
}
else if (p.prototyped->time.end != "Today") {
end.setTime(p.prototyped->time.end);
}
try {
_prototyped.timeQuantizer.setStartEndRange(
std::string(start.ISO8601()),
std::string(end.ISO8601())
);
_prototyped.timeQuantizer.setResolution(p.prototyped->temporalResolution);
_prototyped.temporalResolution = p.prototyped->temporalResolution;
}
catch (const ghoul::RuntimeError& e) {
throw ghoul::RuntimeError(fmt::format(
"Could not create time quantizer for Temporal GDAL dataset. {}", e.message
));
}
if (p.prototyped->timeFormat.size() >= 64) {
throw ghoul::RuntimeError(fmt::format(
"Time format string '{}' too large. Maximum length of 64 is allowed",
p.prototyped->timeFormat
));
}
_prototyped.timeFormat = p.prototyped->timeFormat;
_prototyped.prototype = p.prototyped->prototype;
}
if (p.folder.has_value()) {
_mode = Mode::Folder;
_folder.folder = p.folder->folder;
_folder.format = p.folder->format;
namespace fs = std::filesystem;
for (const fs::directory_entry& path : fs::directory_iterator(_folder.folder)) {
if (!path.is_regular_file()) {
continue;
}
std::string file = path.path().filename().string();
std::istringstream ss(file);
std::tm tm = {};
ss >> std::get_time(&tm, p.folder->format.c_str());
if (!ss.fail()) {
std::string date = fmt::format(
"{}-{}-{} {}:{}:{}",
tm.tm_year + 1900,
tm.tm_mon + 1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec
);
double et = SpiceManager::ref().ephemerisTimeFromDate(date);
_folder.files.push_back({ et, path.path().string() });
}
}
using K = double;
using V = std::string;
std::sort(
_folder.files.begin(),
_folder.files.end(),
[](const std::pair<K, V>& lhs, const std::pair<K, V>& rhs) {
return lhs.first < rhs.first;
}
);
}
_isInterpolating = p.interpolation.value_or(_isInterpolating);
if (_isInterpolating) {
_interpolateTileProvider = std::make_unique<InterpolateTileProvider>(dictionary);
_interpolateTileProvider->initialize();
_interpolateTileProvider->colormap =
ghoul::io::TextureReader::ref().loadTexture(_colormap, 1);
_interpolateTileProvider->colormap->uploadTexture();
_interpolateTileProvider->colormap->setFilter(
ghoul::opengl::Texture::FilterMode::AnisotropicMipMap
);
}
}
Tile TemporalTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
if (!_currentTileProvider) {
update();
}
return _currentTileProvider->tile(tileIndex);
}
Tile::Status TemporalTileProvider::tileStatus(const TileIndex& index) {
if (!_currentTileProvider) {
update();
}
return _currentTileProvider->tileStatus(index);
}
TileDepthTransform TemporalTileProvider::depthTransform() {
if (!_currentTileProvider) {
update();
}
return _currentTileProvider->depthTransform();
}
void TemporalTileProvider::update() {
TileProvider* newCurr = nullptr;
try {
if (_useFixedTime && !_fixedTime.value().empty()) {
if (_fixedTimeDirty) {
std::string fixedTime = _fixedTime.value();
double et = SpiceManager::ref().ephemerisTimeFromDate(fixedTime);
newCurr = retrieveTileProvider(Time(et));
_fixedTimeDirty = false;
}
}
else {
newCurr = tileProvider(global::timeManager->time());
}
}
catch (const ghoul::RuntimeError& e) {
LERRORC("TemporalTileProvider", e.message);
}
if (newCurr) {
_currentTileProvider = newCurr;
}
if (_currentTileProvider) {
_currentTileProvider->update();
}
}
void TemporalTileProvider::reset() {
for (std::pair<const double, DefaultTileProvider>& it : _tileProviderMap) {
it.second.reset();
}
}
int TemporalTileProvider::maxLevel() {
if (!_currentTileProvider) {
update();
}
return _currentTileProvider->maxLevel();
}
float TemporalTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
DefaultTileProvider TemporalTileProvider::createTileProvider(
std::string_view timekey) const
{
ZoneScoped
std::string value;
switch (_mode) {
case Mode::Prototype: {
static const std::vector<std::string> IgnoredTokens = {
// From: http://www.gdal.org/frmt_wms.html
"${x}", "${y}", "${z}", "${version}" "${format}", "${layer}"
};
value = _prototyped.prototype;
while (true) {
const size_t pos = value.find(TimePlaceholder);
if (pos == std::string::npos) {
break;
}
const size_t numChars = std::string_view(TimePlaceholder).size();
value = value.replace(pos, numChars, timekey);
}
value = FileSys.expandPathTokens(std::move(value), IgnoredTokens).string();
break;
}
case Mode::Folder: {
value = std::string(timekey);
break;
}
}
ghoul::Dictionary dict = _initDict;
dict.setValue("FilePath", value);
return DefaultTileProvider(dict);
}
DefaultTileProvider* TemporalTileProvider::retrieveTileProvider(const Time& t) {
ZoneScoped
const double time = t.j2000Seconds();
if (const auto it = _tileProviderMap.find(time); it != _tileProviderMap.end()) {
return &it->second;
}
std::string_view timeStr = [this, time]() {
switch (_mode) {
case Mode::Prototype:
return timeStringify(_prototyped.timeFormat, Time(time));
case Mode::Folder: {
// Yes this will have to be done twice since we do the check previously
// but it is only happening when the images change, so I think that should
// be fine
auto it = std::lower_bound(
_folder.files.cbegin(),
_folder.files.cend(),
time,
[](const std::pair<double, std::string>& p, double time) {
return p.first < time;
}
);
return std::string_view(it->second);
}
default: throw ghoul::MissingCaseException();
};
}();
DefaultTileProvider tileProvider = createTileProvider(timeStr);
tileProvider.initialize();
auto it = _tileProviderMap.insert({ time, std::move(tileProvider) });
return &it.first->second;
}
template <>
TileProvider*
TemporalTileProvider::tileProvider<TemporalTileProvider::Mode::Folder, false>(
const Time& time)
{
// Find the most current image that matches the current time. We can't pass the `time`
// variable into the retrieveTileProvider function as it would generate a new
// non-existing TileProvider for every new frame
using It = std::vector<std::pair<double, std::string>>::const_iterator;
It it = std::lower_bound(
_folder.files.begin(),
_folder.files.end(),
time.j2000Seconds(),
[](const std::pair<double, std::string>& p, double t) {
return p.first < t;
}
);
if (it != _folder.files.begin()) {
it -= 1;
}
double t = it->first;
return retrieveTileProvider(Time(t));
}
template <>
TileProvider*
TemporalTileProvider::tileProvider<TemporalTileProvider::Mode::Folder, true>(
const Time& time)
{
using It = std::vector<std::pair<double, std::string>>::const_iterator;
It next = std::lower_bound(
_folder.files.begin(),
_folder.files.end(),
time.j2000Seconds(),
[](const std::pair<double, std::string>& p, double t) {
return p.first < t;
}
);
It curr = next != _folder.files.begin() ? next - 1 : next;
It nextNext = next != _folder.files.end() ? next + 1 : curr;
It prev = curr != _folder.files.begin() ? curr - 1 : curr;
_interpolateTileProvider->t1 = retrieveTileProvider(Time(curr->first));
_interpolateTileProvider->t2 = retrieveTileProvider(Time(next->first));
_interpolateTileProvider->future = retrieveTileProvider(Time(nextNext->first));
_interpolateTileProvider->before = retrieveTileProvider(Time(prev->first));
_interpolateTileProvider->factor = static_cast<float>(
(time.j2000Seconds() - curr->first) /
(next->first - curr->first)
);
if (_interpolateTileProvider->factor > 1.f) {
_interpolateTileProvider->factor = 1.f;
}
return _interpolateTileProvider.get();
}
template <>
TileProvider*
TemporalTileProvider::tileProvider<TemporalTileProvider::Mode::Prototype, false>(
const Time& time)
{
Time tCopy(time);
if (_prototyped.timeQuantizer.quantize(tCopy, true)) {
return retrieveTileProvider(tCopy);
}
else {
return nullptr;
}
}
template <>
TileProvider*
TemporalTileProvider::tileProvider<TemporalTileProvider::Mode::Prototype, true>(
const Time& time)
{
Time tCopy(time);
if (!_prototyped.timeQuantizer.quantize(tCopy, true)) {
return nullptr;
}
Time nextTile = tCopy;
Time nextNextTile = tCopy;
Time prevTile = tCopy;
Time secondToLast = Time(_prototyped.endTimeJ2000);
Time secondToFirst = Time(_prototyped.startTimeJ2000);
_interpolateTileProvider->t1 = retrieveTileProvider(tCopy);
// if the images are for each hour
if (_prototyped.temporalResolution == "1h") {
constexpr const int Hour = 60 * 60;
// the second tile to interpolate between
nextTile.advanceTime(Hour);
// the tile after the second tile
nextNextTile.advanceTime(2 * Hour);
// the tile before the first tile
prevTile.advanceTime(-Hour + 1);
// to make sure that an image outside the dataset is not searched for both
// ends of the dataset are calculated
secondToLast.advanceTime(-Hour);
secondToFirst.advanceTime(Hour);
}
// if the images are for each month
if (_prototyped.temporalResolution == "1M") {
constexpr const int Day = 24 * 60 * 60;
// the second tile to interpolate between
nextTile.advanceTime(32 * Day);
// the tile after the second tile
nextNextTile.advanceTime(64 * Day);
// the tile before the first tile
prevTile.advanceTime(-2 * Day);
// to make sure that an image outside the dataset is not searched for both
// ends of the dataset are calculated
secondToLast.advanceTime(-2 * Day);
secondToFirst.advanceTime(32 * Day);
// since months vary in length the time is set to the first of each month
auto setToFirstOfMonth = [](Time& t) {
std::string timeString = std::string(t.ISO8601());
timeString[8] = '0';
timeString[9] = '1';
t.setTime(timeString);
};
setToFirstOfMonth(nextTile);
setToFirstOfMonth(nextNextTile);
setToFirstOfMonth(prevTile);
setToFirstOfMonth(secondToLast);
setToFirstOfMonth(secondToFirst);
}
// the necessary tile providers are loaded if they exist within the timespan
if (secondToLast.j2000Seconds() > time.j2000Seconds() &&
secondToFirst.j2000Seconds() < time.j2000Seconds())
{
_interpolateTileProvider->t2 = retrieveTileProvider(nextTile);
_interpolateTileProvider->future = retrieveTileProvider(nextNextTile);
_interpolateTileProvider->before = retrieveTileProvider(prevTile);
}
else if (secondToLast.j2000Seconds() < time.j2000Seconds() &&
_prototyped.endTimeJ2000 > time.j2000Seconds())
{
_interpolateTileProvider->t2 = retrieveTileProvider(nextTile);
_interpolateTileProvider->future = retrieveTileProvider(tCopy);
_interpolateTileProvider->before = retrieveTileProvider(prevTile);
}
else if (secondToFirst.j2000Seconds() > time.j2000Seconds() &&
_prototyped.startTimeJ2000 < time.j2000Seconds())
{
_interpolateTileProvider->t2 = retrieveTileProvider(nextTile);
_interpolateTileProvider->future = retrieveTileProvider(nextNextTile);
_interpolateTileProvider->before = retrieveTileProvider(tCopy);
}
else {
_interpolateTileProvider->t2 = retrieveTileProvider(tCopy);
_interpolateTileProvider->future = retrieveTileProvider(tCopy);
_interpolateTileProvider->before = retrieveTileProvider(tCopy);
}
_interpolateTileProvider->factor = static_cast<float>(
(time.j2000Seconds() - tCopy.j2000Seconds()) /
(nextTile.j2000Seconds() - tCopy.j2000Seconds())
);
if (_interpolateTileProvider->factor > 1.f) {
_interpolateTileProvider->factor = 1.f;
}
return _interpolateTileProvider.get();
}
TileProvider* TemporalTileProvider::tileProvider(const Time& time) {
if (_isInterpolating) {
switch (_mode) {
case Mode::Folder:
return tileProvider<Mode::Folder, true>(time);
case Mode::Prototype:
return tileProvider<Mode::Prototype, true>(time);
default: throw ghoul::MissingCaseException();
}
}
else {
switch (_mode) {
case Mode::Folder:
return tileProvider<Mode::Folder, false>(time);
case Mode::Prototype:
return tileProvider<Mode::Prototype, false>(time);
default: throw ghoul::MissingCaseException();
}
}
}
TemporalTileProvider::InterpolateTileProvider::InterpolateTileProvider(
const ghoul::Dictionary&)
{
ZoneScoped
glGenFramebuffers(1, &fbo);
glGenVertexArrays(1, &vaoQuad);
glGenBuffers(1, &vboQuad);
glBindVertexArray(vaoQuad);
glBindBuffer(GL_ARRAY_BUFFER, vboQuad);
// Quad for fullscreen with vertex (xy) and texture coordinates (uv)
const GLfloat vertexData[] = {
// x y u v
-1.f, -1.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f,
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// vertex coordinates at location 0
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(0);
// texture coords at location 1
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
4 * sizeof(GLfloat),
reinterpret_cast<void*>(2 * sizeof(GLfloat))
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
shaderProgram = global::renderEngine->buildRenderProgram(
"InterpolatingProgram",
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_vs.glsl"),
absPath("${MODULE_GLOBEBROWSING}/shaders/interpolate_fs.glsl")
);
}
TemporalTileProvider::InterpolateTileProvider::~InterpolateTileProvider() {
glDeleteFramebuffers(1, &fbo);
glDeleteBuffers(1, &vboQuad);
glDeleteVertexArrays(1, &vaoQuad);
}
Tile TemporalTileProvider::InterpolateTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
TracyGpuZone("tile");
// prev and next are the two tiles to interpolate between
Tile prev = t1->tile(tileIndex);
Tile next = t2->tile(tileIndex);
// the tile before and the tile after the interpolation interval are loaded so the
// interpolation goes smoother
Tile prevprev = before->tile(tileIndex);
Tile nextnext = future->tile(tileIndex);
cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
if (!prev.texture || !next.texture) {
return Tile{ nullptr, std::nullopt, Tile::Status::Unavailable };
}
// The data for initializing the texture
TileTextureInitData initData(
prev.texture->dimensions().x,
prev.texture->dimensions().y,
prev.texture->dataType(),
prev.texture->format(),
TileTextureInitData::PadTiles::No,
TileTextureInitData::ShouldAllocateDataOnCPU::No
);
// Check if a tile exists for the given key in the tileCache
// Initializing the tile that will contian the interpolated texture
Tile ourTile;
// The texture that will contain the interpolated image
ghoul::opengl::Texture* writeTexture;
cache::MemoryAwareTileCache* tileCache =
global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
if (tileCache->exist(key)) {
ourTile = tileCache->get(key);
writeTexture = ourTile.texture;
}
else {
// Create a texture with the initialization data
writeTexture = tileCache->texture(initData);
ourTile = Tile{ writeTexture, std::nullopt, Tile::Status::OK };
tileCache->put(key, initData.hashKey, ourTile);
}
// Saves current state
GLint currentFBO;
GLint viewport[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFBO);
global::renderEngine->openglStateCache().viewport(viewport);
// Bind render texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *writeTexture, 0);
glDisable(GL_BLEND);
GLenum textureBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, textureBuffers);
// Setup our own viewport settings
GLsizei w = static_cast<GLsizei>(writeTexture->width());
GLsizei h = static_cast<GLsizei>(writeTexture->height());
glViewport(0, 0, w, h);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
GLint id;
glGetIntegerv(GL_CURRENT_PROGRAM, &id);
// Activate shader and bind uniforms
shaderProgram->activate();
shaderProgram->setUniform("blendFactor", factor);
// The texture that will give the color for the interpolated texture
ghoul::opengl::TextureUnit colormapUnit;
colormapUnit.activate();
colormap->bind();
shaderProgram->setUniform("colormapTexture", colormapUnit);
ghoul::opengl::TextureUnit prevUnit;
prevUnit.activate();
prev.texture->bind();
shaderProgram->setUniform("prevTexture", prevUnit);
ghoul::opengl::TextureUnit nextUnit;
nextUnit.activate();
next.texture->bind();
shaderProgram->setUniform("nextTexture", nextUnit);
// Render to the texture
glBindVertexArray(vaoQuad);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2 triangles
// Deactivate shader program (when rendering is completed)
shaderProgram->deactivate();
glUseProgram(id);
// Restores system state
glBindFramebuffer(GL_FRAMEBUFFER, currentFBO);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Restores OpenGL Rendering State
global::renderEngine->openglStateCache().resetColorState();
global::renderEngine->openglStateCache().resetBlendState();
global::renderEngine->openglStateCache().resetDepthState();
global::renderEngine->openglStateCache().resetPolygonAndClippingState();
global::renderEngine->openglStateCache().resetViewportState();
return ourTile;
}
Tile::Status TemporalTileProvider::InterpolateTileProvider::tileStatus(
const TileIndex& index)
{
return std::min(t1->tileStatus(index), t2->tileStatus(index));
}
TileDepthTransform TemporalTileProvider::InterpolateTileProvider::depthTransform() {
return t1->depthTransform();
}
void TemporalTileProvider::InterpolateTileProvider::update() {
t1->update();
t2->update();
before->update();
future->update();
}
void TemporalTileProvider::InterpolateTileProvider::reset() {
t1->reset();
t2->reset();
before->reset();
future->reset();
}
int TemporalTileProvider::InterpolateTileProvider::maxLevel() {
return glm::min(t1->maxLevel(), t2->maxLevel());
}
float TemporalTileProvider::InterpolateTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,130 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__TEMPORALTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEMPORALTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
namespace openspace::globebrowsing {
/**
* Provide <code>Tile</code>s from web map services that have temporal resolution.
*
* TemporalTileProviders are instantiated using a ghoul::Dictionary, and must define a
* filepath to a Openspace Temporal dataset description file. This is an xml-file that
* defines the same meta data as the GDAL wms description
* (http://www.gdal.org/frmt_wms.html), but augmented with some extra tags describing the
* temporal properties of the dataset. See
* <code>TemporalTileProvider::TemporalXMLTags</code>
*/
class TemporalTileProvider : public TileProvider {
public:
TemporalTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
enum class Mode {
Prototype,
Folder
};
struct InterpolateTileProvider : public TileProvider {
InterpolateTileProvider(const ghoul::Dictionary&);
virtual ~InterpolateTileProvider();
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
TileProvider* before = nullptr;
TileProvider* t1 = nullptr;
TileProvider* t2 = nullptr;
TileProvider* future = nullptr;
float factor = 1.f;
GLuint vaoQuad = 0;
GLuint vboQuad = 0;
GLuint fbo = 0;
std::unique_ptr<ghoul::opengl::ProgramObject> shaderProgram;
std::unique_ptr<ghoul::opengl::Texture> colormap;
};
DefaultTileProvider createTileProvider(std::string_view timekey) const;
DefaultTileProvider* retrieveTileProvider(const Time& t);
template <Mode mode, bool interpolation>
TileProvider* tileProvider(const Time& time);
TileProvider* tileProvider(const Time& time);
Mode _mode;
struct {
double startTimeJ2000 = 0.0;
double endTimeJ2000 = 0.0;
std::string temporalResolution;
std::string timeFormat;
TimeQuantizer timeQuantizer;
std::string prototype;
} _prototyped;
struct {
std::filesystem::path folder;
std::string format;
std::vector<std::pair<double, std::string>> files;
} _folder;
ghoul::Dictionary _initDict;
properties::BoolProperty _useFixedTime;
properties::StringProperty _fixedTime;
bool _fixedTimeDirty = true;
TileProvider* _currentTileProvider = nullptr;
std::unordered_map<double, DefaultTileProvider> _tileProviderMap;
bool _isInterpolating = false;
std::string _colormap;
std::unique_ptr<InterpolateTileProvider> _interpolateTileProvider;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEMPORALTILEPROVIDER___H__

View File

@@ -0,0 +1,109 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/texttileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/opengl/openglstatecache.h>
namespace openspace::globebrowsing {
TextTileProvider::TextTileProvider(TileTextureInitData initData_, size_t fontSize_)
: initData(std::move(initData_))
, fontSize(fontSize_)
{
ZoneScoped
tileCache = global::moduleEngine->module<GlobeBrowsingModule>()->tileCache();
}
TextTileProvider::~TextTileProvider() {}
void TextTileProvider::internalInitialize() {
ZoneScoped
font = global::fontManager->font("Mono", static_cast<float>(fontSize));
fontRenderer = ghoul::fontrendering::FontRenderer::createDefault();
fontRenderer->setFramebufferSize(glm::vec2(initData.dimensions));
glGenFramebuffers(1, &fbo);
}
void TextTileProvider::internalDeinitialize() {
glDeleteFramebuffers(1, &fbo);
}
Tile TextTileProvider::renderTile(const TileIndex& tileIndex, const std::string& text,
const glm::vec2& position, const glm::vec4& color)
{
ZoneScoped
TracyGpuZone("tile")
cache::ProviderTileKey key = { tileIndex, uniqueIdentifier };
Tile tile = tileCache->get(key);
if (!tile.texture) {
ghoul::opengl::Texture* texture = tileCache->texture(initData);
// Keep track of defaultFBO and viewport to be able to reset state when done
GLint defaultFBO = global::renderEngine->openglStateCache().defaultFramebuffer();
// Render to texture
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
*texture,
0
);
GLsizei w = static_cast<GLsizei>(texture->width());
GLsizei h = static_cast<GLsizei>(texture->height());
glViewport(0, 0, w, h);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
fontRenderer->render(*font, position, text, color);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
global::renderEngine->openglStateCache().resetViewportState();
tile = Tile{ texture, std::nullopt, Tile::Status::OK };
tileCache->put(key, initData.hashKey, tile);
}
return tile;
}
void TextTileProvider::reset() {
ZoneScoped
tileCache->clear();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,60 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__TEXTTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEXTTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
class TextTileProvider : public TileProvider {
public:
TextTileProvider(TileTextureInitData initData, size_t fontSize = 48);
virtual ~TextTileProvider();
void reset() override;
protected:
Tile renderTile(const TileIndex& tileIndex, const std::string& text,
const glm::vec2& position, const glm::vec4& color);
const TileTextureInitData initData;
std::unique_ptr<ghoul::fontrendering::FontRenderer> fontRenderer;
std::shared_ptr<ghoul::fontrendering::Font> font;
size_t fontSize = 0;
GLuint fbo = 0;
cache::MemoryAwareTileCache* tileCache;
private:
void internalInitialize() override final;
void internalDeinitialize() override final;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TEXTTILEPROVIDER___H__

View File

@@ -0,0 +1,65 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/tileindextileprovider.h>
namespace openspace::globebrowsing {
TileIndexTileProvider::TileIndexTileProvider(const ghoul::Dictionary&)
: TextTileProvider(tileTextureInitData(layergroupid::GroupID::ColorLayers, false))
{}
Tile TileIndexTileProvider::tile(const TileIndex& tileIndex) {
ZoneScoped
std::string text = fmt::format(
"level: {}\nx: {}\ny: {}", tileIndex.level, tileIndex.x, tileIndex.y
);
glm::vec2 textPosition = glm::vec2(
initData.dimensions.x / 4 -
(initData.dimensions.x / 32) * log10(1 << tileIndex.level),
initData.dimensions.y / 2 + fontSize
);
return TextTileProvider::renderTile(tileIndex, text, textPosition, glm::vec4(1.f));
}
Tile::Status TileIndexTileProvider::tileStatus(const TileIndex&) {
return Tile::Status::OK;
}
TileDepthTransform TileIndexTileProvider::depthTransform() {
return { 0.f, 1.f };
}
void TileIndexTileProvider::update() {}
int TileIndexTileProvider::maxLevel() {
return 1337; // unlimited
}
float TileIndexTileProvider::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -22,14 +22,25 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "catch2/catch.hpp"
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__
#include <modules/globebrowsing/src/tileprovider.h>
#include <openspace/util/time.h>
#include <glm/glm.hpp>
#include <modules/globebrowsing/src/tileprovider/texttileprovider.h>
namespace {
constexpr const char* fileName = "data/scene/debugglobe/map_service_configs/"
"VIIRS_SNPP_CorrectedReflectance_TrueColor_temporal.xml";
} // namespace
namespace openspace::globebrowsing {
class TileIndexTileProvider : public TextTileProvider {
public:
TileIndexTileProvider(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEINDEXTILEPROVIDER___H__

View File

@@ -0,0 +1,238 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/asynctiledataprovider.h>
#include <modules/globebrowsing/src/geodeticpatch.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/rawtiledatareader.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/sizereferencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/memorymanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/textureunit.h>
#include <filesystem>
#include <fstream>
#include "cpl_minixml.h"
namespace openspace::globebrowsing {
namespace {
std::unique_ptr<ghoul::opengl::Texture> DefaultTileTexture;
Tile DefaultTile = Tile { nullptr, std::nullopt, Tile::Status::Unavailable };
constexpr const char* KeyFilePath = "FilePath";
} // namespace
unsigned int TileProvider::NumTileProviders = 0;
std::unique_ptr<TileProvider> TileProvider::createFromDictionary(
layergroupid::TypeID layerTypeID,
const ghoul::Dictionary& dictionary)
{
ZoneScoped
const char* type = layergroupid::LAYER_TYPE_NAMES[static_cast<int>(layerTypeID)];
auto factory = FactoryManager::ref().factory<TileProvider>();
TileProvider* result = factory->create(type, dictionary);
return std::unique_ptr<TileProvider>(result);
}
void TileProvider::initializeDefaultTile() {
ZoneScoped
ghoul_assert(!DefaultTile.texture, "Default tile should not have been created");
using namespace ghoul::opengl;
// Create pixel data
TileTextureInitData initData(
8,
8,
GL_UNSIGNED_BYTE,
Texture::Format::RGBA,
TileTextureInitData::PadTiles::No,
TileTextureInitData::ShouldAllocateDataOnCPU::Yes
);
char* pixels = new char[initData.totalNumBytes];
memset(pixels, 0, initData.totalNumBytes * sizeof(char));
// Create ghoul texture
DefaultTileTexture = std::make_unique<Texture>(initData.dimensions, GL_TEXTURE_2D);
DefaultTileTexture->setDataOwnership(Texture::TakeOwnership::Yes);
DefaultTileTexture->setPixelData(pixels);
DefaultTileTexture->uploadTexture();
DefaultTileTexture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
// Create tile
DefaultTile = Tile{ DefaultTileTexture.get(), std::nullopt, Tile::Status::OK };
}
void TileProvider::deinitializeDefaultTile() {
DefaultTileTexture = nullptr;
}
TileProvider::TileProvider() : properties::PropertyOwner({ "TileProvider" }) {}
void TileProvider::initialize() {
ZoneScoped
ghoul_assert(!isInitialized, "TileProvider can only be initialized once.");
if (TileProvider::NumTileProviders >
static_cast<unsigned int>(std::numeric_limits<uint16_t>::max()) - 1)
{
LERRORC(
"TileProvider",
"Number of tile providers exceeds 65535. Something will break soon"
);
TileProvider::NumTileProviders = 0;
}
uniqueIdentifier = static_cast<uint16_t>(TileProvider::NumTileProviders++);
if (TileProvider::NumTileProviders == std::numeric_limits<unsigned int>::max()) {
--TileProvider::NumTileProviders;
return;
}
internalInitialize();
isInitialized = true;
}
void TileProvider::deinitialize() {
ZoneScoped
internalDeinitialize();
}
void TileProvider::internalInitialize() {}
void TileProvider::internalDeinitialize() {}
ChunkTile TileProvider::chunkTile(TileIndex tileIndex, int parents, int maxParents) {
ZoneScoped
ghoul_assert(isInitialized, "TileProvider was not initialized.");
auto ascendToParent = [](TileIndex& ti, TileUvTransform& uv) {
uv.uvOffset *= 0.5;
uv.uvScale *= 0.5;
uv.uvOffset += ti.positionRelativeParent();
ti.x /= 2;
ti.y /= 2;
ti.level--;
};
TileUvTransform uvTransform = { glm::vec2(0.f, 0.f), glm::vec2(1.f, 1.f) };
// Step 1. Traverse 0 or more parents up the chunkTree as requested by the caller
for (int i = 0; i < parents && tileIndex.level > 1; i++) {
ascendToParent(tileIndex, uvTransform);
}
maxParents -= parents;
// Step 2. Traverse 0 or more parents up the chunkTree to make sure we're inside
// the range of defined data.
int maximumLevel = maxLevel();
while (tileIndex.level > maximumLevel) {
ascendToParent(tileIndex, uvTransform);
maxParents--;
}
if (maxParents < 0) {
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
// Step 3. Traverse 0 or more parents up the chunkTree until we find a chunk that
// has a loaded tile ready to use.
while (tileIndex.level > 1) {
Tile t = tile(tileIndex);
if (t.status != Tile::Status::OK) {
if (--maxParents < 0) {
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
ascendToParent(tileIndex, uvTransform);
}
else {
return ChunkTile { std::move(t), uvTransform, TileDepthTransform() };
}
}
return ChunkTile { Tile(), uvTransform, TileDepthTransform() };
}
ChunkTilePile TileProvider::chunkTilePile(TileIndex tileIndex, int pileSize) {
ZoneScoped
ghoul_assert(isInitialized, "TileProvider was not initialized.");
ghoul_assert(pileSize >= 0, "pileSize must be positive");
ChunkTilePile chunkTilePile;
std::fill(chunkTilePile.begin(), chunkTilePile.end(), std::nullopt);
for (int i = 0; i < pileSize; ++i) {
chunkTilePile[i] = chunkTile(tileIndex, i);
if (chunkTilePile[i]->tile.status == Tile::Status::Unavailable) {
if (i == 0) {
// First iteration
chunkTilePile[i]->tile = DefaultTile;
chunkTilePile[i]->uvTransform.uvOffset = { 0.f, 0.f };
chunkTilePile[i]->uvTransform.uvScale = { 1.f, 1.f };
}
else {
// We are iterating through the array one-by-one, so we are guaranteed
// that for tile 'i', tile 'i-1' already was initializated
chunkTilePile[i]->tile = chunkTilePile[i - 1]->tile;
chunkTilePile[i]->uvTransform.uvOffset =
chunkTilePile[i - 1]->uvTransform.uvOffset;
chunkTilePile[i]->uvTransform.uvScale =
chunkTilePile[i - 1]->uvTransform.uvScale;
}
}
}
return chunkTilePile;
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,145 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__TILEPROVIDER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDER___H__
#include <openspace/properties/propertyowner.h>
#include <modules/globebrowsing/src/basictypes.h>
#include <modules/globebrowsing/src/ellipsoid.h>
#include <modules/globebrowsing/src/layergroupid.h>
#include <modules/globebrowsing/src/tileindex.h>
#include <modules/globebrowsing/src/tiletextureinitdata.h>
#include <modules/globebrowsing/src/timequantizer.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/intproperty.h>
#include <unordered_map>
#include <ghoul/opengl/programobject.h>
struct CPLXMLNode;
namespace ghoul::fontrendering {
class Font;
class FontRenderer;
} // namespace ghoul::fontrendering
namespace openspace { class PixelBuffer; }
namespace openspace::globebrowsing {
class AsyncTileDataProvider;
struct RawTile;
struct TileIndex;
namespace cache { class MemoryAwareTileCache; }
} // namespace openspace::globebrowsing
namespace openspace::globebrowsing {
enum class Type {
DefaultTileProvider = 0,
SingleImageTileProvider,
ImageSequenceTileProvider,
SizeReferenceTileProvider,
TemporalTileProvider,
TileIndexTileProvider,
ByIndexTileProvider,
ByLevelTileProvider,
InterpolateTileProvider
};
struct TileProvider : public properties::PropertyOwner {
static unsigned int NumTileProviders;
static std::unique_ptr<TileProvider> createFromDictionary(
layergroupid::TypeID layerTypeID, const ghoul::Dictionary& dictionary);
static void initializeDefaultTile();
static void deinitializeDefaultTile();
TileProvider();
virtual ~TileProvider() = default;
void initialize();
void deinitialize();
virtual Tile tile(const TileIndex& tileIndex) = 0;
/**
* Returns the status of a <code>Tile</code>. The <code>Tile::Status</code>
* corresponds the <code>Tile</code> that would be returned if the function
* <code>tile</code> would be invoked with the same <code>TileIndex</code> argument at
* this point in time.
*/
virtual Tile::Status tileStatus(const TileIndex& index) = 0;
/**
* Get the associated depth transform for this TileProvider. This is necessary for
* TileProviders serving height map data, in order to correcly map pixel values to
* meters.
*/
virtual TileDepthTransform depthTransform() = 0;
/**
* This method should be called once per frame. Here, TileProviders are given the
* opportunity to update their internal state.
*/
virtual void update() = 0;
/**
* Provides a uniform way of all TileProviders to reload or restore all of its
* internal state. This is mainly useful for debugging purposes.
*/
virtual void reset() = 0;
/**
* \return The maximum level as defined by <code>TileIndex</code> that this
* TileProvider is able provide.
*/
virtual int maxLevel() = 0;
/**
* \return the no data value for the dataset. Default is the minimum float value.
*/
virtual float noDataValueAsFloat() = 0;
ChunkTile chunkTile(TileIndex tileIndex, int parents = 0, int maxParents = 1337);
ChunkTilePile chunkTilePile(TileIndex tileIndex, int pileSize);
std::string name;
uint16_t uniqueIdentifier = 0;
bool isInitialized = false;
private:
virtual void internalInitialize();
virtual void internalDeinitialize();
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDER___H__

View File

@@ -0,0 +1,140 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/tileproviderbyindex.h>
#include <openspace/documentation/documentation.h>
namespace {
constexpr const char* KeyDefaultProvider = "DefaultProvider";
constexpr const char* KeyProviders = "IndexTileProviders";
constexpr const char* KeyTileIndex = "TileIndex";
constexpr const char* KeyTileProvider = "TileProvider";
struct [[codegen::Dictionary(TileProviderByIndex)]] Parameters {
ghoul::Dictionary defaultProvider;
struct IndexProvider {
struct Index {
int x [[codegen::greaterequal(0)]];
int y [[codegen::greaterequal(0)]];
int level [[codegen::inrange(0, 255)]];
};
Index tileIndex;
ghoul::Dictionary tileProvider;
};
std::vector<IndexProvider> indexTileProviders;
};
#include "tileproviderbyindex_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
TileProviderByIndex::TileProviderByIndex(const ghoul::Dictionary& dictionary) {
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
layergroupid::TypeID typeID = layergroupid::TypeID::DefaultTileLayer;
if (p.defaultProvider.hasValue<std::string>("Type")) {
std::string type = p.defaultProvider.value<std::string>("Type");
typeID = ghoul::from_string<layergroupid::TypeID>(type);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + type);
}
}
_defaultTileProvider = createFromDictionary(typeID, p.defaultProvider);
for (const Parameters::IndexProvider& ip : p.indexTileProviders) {
const TileIndex tileIndex(
ip.tileIndex.x,
ip.tileIndex.y,
static_cast<uint8_t>(ip.tileIndex.level)
);
layergroupid::TypeID providerTypeID = layergroupid::TypeID::DefaultTileLayer;
if (ip.tileProvider.hasValue<std::string>("Type")) {
std::string type = ip.tileProvider.value<std::string>("Type");
providerTypeID = ghoul::from_string<layergroupid::TypeID>(type);
if (providerTypeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + type);
}
}
std::unique_ptr<TileProvider> stp = createFromDictionary(
providerTypeID,
ip.tileProvider
);
TileIndex::TileHashKey key = tileIndex.hashKey();
_providers.insert(std::make_pair(key, std::move(stp)));
}
}
Tile TileProviderByIndex::tile(const TileIndex& tileIndex) {
ZoneScoped
const auto it = _providers.find(tileIndex.hashKey());
const bool hasProvider = it != _providers.end();
return hasProvider ? it->second->tile(tileIndex) : Tile();
}
Tile::Status TileProviderByIndex::tileStatus(const TileIndex& index) {
const auto it = _providers.find(index.hashKey());
const bool hasProvider = it != _providers.end();
return hasProvider ? it->second->tileStatus(index) : Tile::Status::Unavailable;
}
TileDepthTransform TileProviderByIndex::depthTransform() {
return _defaultTileProvider->depthTransform();
}
void TileProviderByIndex::update() {
using K = TileIndex::TileHashKey;
using V = std::unique_ptr<TileProvider>;
for (std::pair<const K, V>& it : _providers) {
it.second->update();
}
_defaultTileProvider->update();
}
void TileProviderByIndex::reset() {
using K = TileIndex::TileHashKey;
using V = std::unique_ptr<TileProvider>;
for (std::pair<const K, V>& it : _providers) {
it.second->reset();
}
_defaultTileProvider->reset();
}
int TileProviderByIndex::maxLevel() {
return _defaultTileProvider->maxLevel();
}
float TileProviderByIndex::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,51 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__TILEPROVIDERBYINDEX___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYINDEX___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
class TileProviderByIndex : public TileProvider {
public:
TileProviderByIndex(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
std::unordered_map<TileIndex::TileHashKey, std::unique_ptr<TileProvider>> _providers;
std::unique_ptr<TileProvider> _defaultTileProvider;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYINDEX___H__

View File

@@ -0,0 +1,161 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/src/tileprovider/tileproviderbylevel.h>
#include <openspace/documentation/documentation.h>
namespace {
struct [[codegen::Dictionary(TileProviderByLevel)]] Parameters {
int layerGroupID;
struct Providers {
int maxLevel [[codegen::greaterequal(0)]];
ghoul::Dictionary tileProvider;
};
std::vector<Providers> levelTileProviders;
};
#include "tileproviderbylevel_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
TileProviderByLevel::TileProviderByLevel(const ghoul::Dictionary& dictionary) {
ZoneScoped
const Parameters p = codegen::bake<Parameters>(dictionary);
layergroupid::GroupID layerGroup = static_cast<layergroupid::GroupID>(p.layerGroupID);
for (Parameters::Providers p : p.levelTileProviders) {
p.tileProvider.setValue("LayerGroupID", static_cast<int>(layerGroup));
layergroupid::TypeID typeID = layergroupid::TypeID::DefaultTileLayer;
if (p.tileProvider.hasValue<std::string>("Type")) {
std::string type = p.tileProvider.value<std::string>("Type");
typeID = ghoul::from_string<layergroupid::TypeID>(type);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type: " + type);
}
}
std::unique_ptr<TileProvider> tp = createFromDictionary(typeID, p.tileProvider);
std::string provId = p.tileProvider.value<std::string>("Identifier");
tp->setIdentifier(provId);
std::string providerName = p.tileProvider.value<std::string>("Name");
tp->setGuiName(providerName);
addPropertySubOwner(tp.get());
_levelTileProviders.push_back(std::move(tp));
// Ensure we can represent the max level
if (static_cast<int>(_providerIndices.size()) < p.maxLevel) {
_providerIndices.resize(p.maxLevel + 1, -1);
}
// map this level to the tile provider index
_providerIndices[p.maxLevel] = static_cast<int>(_levelTileProviders.size()) - 1;
}
// Fill in the gaps (value -1 ) in provider indices, from back to end
for (int i = static_cast<int>(_providerIndices.size()) - 2; i >= 0; --i) {
if (_providerIndices[i] == -1) {
_providerIndices[i] = _providerIndices[i + 1];
}
}
}
void TileProviderByLevel::internalInitialize() {
for (const std::unique_ptr<TileProvider>& prov : _levelTileProviders) {
prov->initialize();
}
}
void TileProviderByLevel::internalDeinitialize() {
for (const std::unique_ptr<TileProvider>& prov : _levelTileProviders) {
prov->deinitialize();
}
}
Tile TileProviderByLevel::tile(const TileIndex& tileIndex) {
ZoneScoped
TileProvider* provider = levelProvider(tileIndex.level);
if (provider) {
return provider->tile(tileIndex);
}
else {
return Tile();
}
}
Tile::Status TileProviderByLevel::tileStatus(const TileIndex& index) {
TileProvider* provider = levelProvider(index.level);
return provider ? provider->tileStatus(index) : Tile::Status::Unavailable;
}
TileProvider* TileProviderByLevel::levelProvider(int level) const {
ZoneScoped
if (!_levelTileProviders.empty()) {
int clampedLevel = glm::clamp(
level,
0,
static_cast<int>(_providerIndices.size() - 1)
);
int idx = _providerIndices[clampedLevel];
return _levelTileProviders[idx].get();
}
else {
return nullptr;
}
}
TileDepthTransform TileProviderByLevel::depthTransform() {
return { 0.f, 1.f };
}
void TileProviderByLevel::update() {
for (const std::unique_ptr<TileProvider>& provider : _levelTileProviders) {
provider->update();
}
}
void TileProviderByLevel::reset() {
for (const std::unique_ptr<TileProvider>& provider : _levelTileProviders) {
provider->reset();
}
}
int TileProviderByLevel::maxLevel() {
return static_cast<int>(_providerIndices.size() - 1);
}
float TileProviderByLevel::noDataValueAsFloat() {
return std::numeric_limits<float>::min();
}
} // namespace openspace::globebrowsing

View File

@@ -0,0 +1,55 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
namespace openspace::globebrowsing {
class TileProviderByLevel : public TileProvider {
public:
TileProviderByLevel(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
private:
std::vector<int> _providerIndices;
std::vector<std::unique_ptr<TileProvider>> _levelTileProviders;
void internalInitialize() override final;
void internalDeinitialize() override final;
TileProvider* levelProvider(int level) const;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYLEVEL___H__

View File

@@ -73,7 +73,7 @@ namespace {
namespace openspace {
documentation::Documentation RenderableCrawlingLine::Documentation() {
return codegen::doc<Parameters>("newhorizons_renderable_crawlingline");
return codegen::doc<Parameters>("spacecraftinstruments_renderablecrawlingline");
}
RenderableCrawlingLine::RenderableCrawlingLine(const ghoul::Dictionary& dictionary)

View File

@@ -196,7 +196,7 @@ namespace {
namespace openspace {
documentation::Documentation RenderableFov::Documentation() {
return codegen::doc<Parameters>("newhorizons_renderable_fieldofview");
return codegen::doc<Parameters>("spacecraftinstruments_renderablefieldofview");
}
RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary)

View File

@@ -90,7 +90,7 @@ namespace {
namespace openspace {
documentation::Documentation RenderableModelProjection::Documentation() {
return codegen::doc<Parameters>("newhorizons_renderable_modelprojection");
return codegen::doc<Parameters>("spacecraftinstruments_renderablemodelprojection");
}
RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& dictionary)

View File

@@ -45,6 +45,7 @@ namespace {
constexpr const char* _loggerCat = "RenderablePlaneProjection";
constexpr const char* GalacticFrame = "GALACTIC";
// @TODO (emmbr 2022-01-20) Add documentation
struct [[codegen::Dictionary(RenderablePlaneProjection)]] Parameters {
std::optional<std::string> spacecraft;
std::optional<std::string> instrument;
@@ -58,6 +59,10 @@ namespace {
namespace openspace {
documentation::Documentation RenderablePlaneProjection::Documentation() {
return codegen::doc<Parameters>("spacecraftinstruments_renderableorbitdisc");
}
RenderablePlaneProjection::RenderablePlaneProjection(const ghoul::Dictionary& dict)
: Renderable(dict)
{

View File

@@ -56,6 +56,8 @@ public:
void render(const RenderData& data, RendererTasks& rendererTask) override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
private:
void loadTexture();
void updatePlane(const Image& img, double currentTime);

View File

@@ -162,7 +162,7 @@ namespace {
namespace openspace {
documentation::Documentation RenderablePlanetProjection::Documentation() {
return codegen::doc<Parameters>("newhorizons_renderable_planetprojection");
return codegen::doc<Parameters>("spacecraftinstruments_renderableplanetprojection");
}
RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& dict)

View File

@@ -143,7 +143,7 @@ namespace {
namespace openspace {
documentation::Documentation RenderableShadowCylinder::Documentation() {
return codegen::doc<Parameters>("newhorizons_renderable_shadowcylinder");
return codegen::doc<Parameters>("spacecraftinstruments_renderableshadowcylinder");
}
RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dictionary)

View File

@@ -61,12 +61,12 @@ void SpacecraftInstrumentsModule::internalInitialize(const ghoul::Dictionary&) {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
fRenderable->registerClass<RenderableShadowCylinder>("RenderableShadowCylinder");
fRenderable->registerClass<RenderableCrawlingLine>("RenderableCrawlingLine");
fRenderable->registerClass<RenderableFov>("RenderableFov");
fRenderable->registerClass<RenderableModelProjection>("RenderableModelProjection");
fRenderable->registerClass<RenderablePlaneProjection>("RenderablePlaneProjection");
fRenderable->registerClass<RenderablePlanetProjection>("RenderablePlanetProjection");
fRenderable->registerClass<RenderableModelProjection>("RenderableModelProjection");
fRenderable->registerClass<RenderableShadowCylinder>("RenderableShadowCylinder");
auto fDecoder = FactoryManager::ref().factory<Decoder>();
fDecoder->registerClass<InstrumentDecoder>("Instrument");
@@ -85,9 +85,12 @@ std::vector<documentation::Documentation>
SpacecraftInstrumentsModule::documentations() const
{
return {
RenderableCrawlingLine::Documentation(),
RenderableFov::Documentation(),
RenderableModelProjection::Documentation(),
RenderablePlaneProjection::Documentation(),
RenderablePlanetProjection::Documentation(),
RenderableShadowCylinder::Documentation(),
ProjectionComponent::Documentation()
};
}

View File

@@ -162,7 +162,7 @@ namespace {
namespace openspace {
documentation::Documentation ProjectionComponent::Documentation() {
return codegen::doc<Parameters>("newhorizons_projectioncomponent");
return codegen::doc<Parameters>("spacecraftinstruments_projectioncomponent");
}
ProjectionComponent::ProjectionComponent()

View File

@@ -32,7 +32,7 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "Renderable ToyVolume";
constexpr const char* _loggerCat = "RenderableToyVolume";
constexpr openspace::properties::Property::PropertyInfo SizeInfo = {
"Size",
"Size",

View File

@@ -134,24 +134,33 @@ namespace {
};
constexpr openspace::properties::Property::PropertyInfo FollowAnchorNodeInfo = {
"FollowAnchorNodeRotation",
"Follow Anchor Node Rotation",
"If true, the camera will rotate with the current achor node if within a "
"certain distance from it. When this happens, the object will appear fixed in "
"relation to the camera. The distance at which the change happens is controlled "
"through another property."
};
constexpr openspace::properties::Property::PropertyInfo
FollowAnchorNodeDistanceInfo = {
"FollowAnchorNodeRotationDistance",
"Follow anchor node rotation distance",
"Follow Anchor Node Rotation Distance",
"A factor used to determine the distance at which the camera starts rotating "
"with the anchor node. When this happends, a the object will appear fixed in "
"relation to the camera. The actual distance will be computed by multiplying "
"with the anchor node. The actual distance will be computed by multiplying "
"this factor with the approximate radius of the node."
};
constexpr openspace::properties::Property::PropertyInfo MinimumDistanceInfo = {
"MinimumAllowedDistance",
"Minimum allowed distance",
"Minimum Allowed Distance",
"Limits how close the camera can get to an object. The distance is given in "
"meters above the surface."
};
constexpr openspace::properties::Property::PropertyInfo VelocityZoomControlInfo = {
"VelocityZoomControl",
"Velocity zoom control",
"Velocity Zoom Control",
"Controls the velocity of the camera motion when zooming in to the focus node "
"on a linear flight. The higher the value the faster the camera will move "
"towards the focus."
@@ -180,7 +189,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo
StereoInterpolationTimeInfo = {
"StereoInterpolationTime",
"Stereo interpolation time",
"Stereo Interpolation Time",
"The time to interpolate to a new stereoscopic depth "
"when the anchor node is changed, in seconds."
};
@@ -188,7 +197,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo
RetargetInterpolationTimeInfo = {
"RetargetAnchorInterpolationTime",
"Retarget interpolation time",
"Retarget Interpolation Time",
"The time to interpolate the camera rotation "
"when the anchor or aim node is changed, in seconds."
};
@@ -196,13 +205,13 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo
FollowRotationInterpTimeInfo = {
"FollowRotationInterpolationTime",
"Follow rotation interpolation time",
"Follow Rotation Interpolation Time",
"The interpolation time when toggling following focus node rotation."
};
constexpr openspace::properties::Property::PropertyInfo InvertMouseButtons = {
"InvertMouseButtons",
"Invert left and right mouse buttons",
"Invert Left and Right Mouse Buttons",
"If this value is 'false', the left mouse button causes the camera to rotate "
"around the object and the right mouse button causes the zooming motion. If this "
"value is 'true', these two functionalities are reversed."
@@ -229,7 +238,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo
StereoscopicDepthOfFocusSurfaceInfo = {
"StereoscopicDepthOfFocusSurface",
"Stereoscopic depth of the surface in focus",
"Stereoscopic Depth of the Surface in Focus",
"Set the stereoscopically perceived distance (in meters) to the closest "
"point out of the surface of the anchor and the center of the aim node. "
"Only used if UseAdaptiveStereoscopicDepthInfo is set to true."
@@ -331,7 +340,8 @@ OrbitalNavigator::OrbitalNavigator()
, _aim(AimInfo)
, _retargetAnchor(RetargetAnchorInfo)
, _retargetAim(RetargetAimInfo)
, _followAnchorNodeRotationDistance(FollowAnchorNodeInfo, 5.f, 0.f, 20.f)
, _followAnchorNodeRotation(FollowAnchorNodeInfo, true)
, _followAnchorNodeRotationDistance(FollowAnchorNodeDistanceInfo, 5.f, 0.f, 20.f)
, _minimumAllowedDistance(MinimumDistanceInfo, 10.0f, 0.0f, 10000.f)
, _mouseSensitivity(MouseSensitivityInfo, 15.f, 1.f, 50.f)
, _joystickSensitivity(JoystickSensitivityInfo, 10.f, 1.0f, 50.f)
@@ -491,6 +501,7 @@ OrbitalNavigator::OrbitalNavigator()
addProperty(_aim);
addProperty(_retargetAnchor);
addProperty(_retargetAim);
addProperty(_followAnchorNodeRotation);
addProperty(_followAnchorNodeRotationDistance);
addProperty(_minimumAllowedDistance);
@@ -954,7 +965,7 @@ void OrbitalNavigator::setRetargetInterpolationTime(float durationInSeconds) {
bool OrbitalNavigator::shouldFollowAnchorRotation(const glm::dvec3& cameraPosition) const
{
if (!_anchorNode) {
if (!_anchorNode || !_followAnchorNodeRotation) {
return false;
}

View File

@@ -466,7 +466,6 @@ Path createPathFromDictionary(const ghoul::Dictionary& dictionary, Path::Type ty
break;
}
default: {
LERROR(fmt::format("Uknown camera path target type: {}", p.targetType));
throw ghoul::MissingCaseException();
}
}

View File

@@ -200,7 +200,7 @@ void PathNavigator::updateCamera(double deltaTime) {
if (_currentPath->hasReachedEnd()) {
LINFO("Reached end of path");
_isPlaying = false;
handlePathEnd();
if (_applyIdleBehaviorOnFinish) {
constexpr const char* ApplyIdleBehaviorScript =
@@ -263,10 +263,16 @@ void PathNavigator::startPath() {
return;
}
//OBS! Until we can handle simulation time: early out if not paused
// Always pause the simulation time when flying, to aovid problem with objects
// moving. However, keep track of whether the time was running before the path
// was started, so we can reset it on finish
if (!global::timeManager->isPaused()) {
LERROR("Simulation time must be paused to run a camera path");
return;
global::timeManager->setPause(true);
_startSimulationTimeOnFinish = true;
LINFO(
"Pausing time simulation during path traversal. "
"Will unpause once the camera path is finished"
);
}
LINFO("Starting path");
@@ -280,9 +286,7 @@ void PathNavigator::abortPath() {
LWARNING("No camera path is playing");
return;
}
_isPlaying = false;
clearPath(); // TODO: instead of clearing this could be handled better
handlePathEnd();
LINFO("Aborted camera path");
}
@@ -329,6 +333,16 @@ const std::vector<SceneGraphNode*>& PathNavigator::relevantNodes() {
return _relevantNodes;
}
void PathNavigator::handlePathEnd() {
_isPlaying = false;
if (_startSimulationTimeOnFinish) {
global::timeManager->setPause(false);
}
_startSimulationTimeOnFinish = false;
clearPath();
}
void PathNavigator::findRelevantNodes() {
const std::vector<SceneGraphNode*>& allNodes =
global::renderEngine->scene()->allSceneGraphNodes();
@@ -413,8 +427,8 @@ scripting::LuaLibrary PathNavigator::luaLibrary() {
"Stops a path, if one is being played"
},
{
"goTo",
&luascriptfunctions::goTo,
"flyTo",
&luascriptfunctions::flyTo,
"string [, bool, double]",
"Move the camera to the node with the specified identifier. The optional "
"double specifies the duration of the motion. If the optional bool is "
@@ -422,8 +436,8 @@ scripting::LuaLibrary PathNavigator::luaLibrary() {
"node. Either of the optional parameters can be left out."
},
{
"goToHeight",
&luascriptfunctions::goToHeight,
"flyToHeight",
&luascriptfunctions::flyToHeight,
"string, double [, bool, double]",
"Move the camera to the node with the specified identifier. The second "
"argument is the desired target height above the target node's bounding "
@@ -433,8 +447,8 @@ scripting::LuaLibrary PathNavigator::luaLibrary() {
"parameters can be left out."
},
{
"goToNavigationState",
&luascriptfunctions::goToNavigationState,
"flyToNavigationState",
&luascriptfunctions::flyToNavigationState,
"table, [double]",
"Create a path to the navigation state described by the input table. "
"The optional double specifies the target duration of the motion. Note "
@@ -445,7 +459,7 @@ scripting::LuaLibrary PathNavigator::luaLibrary() {
"createPath",
&luascriptfunctions::createPath,
"table",
"Create the path as described by the lua table input argument"
"Create a camera path as described by the lua table input argument"
},
}
};

View File

@@ -68,8 +68,8 @@ int stopPath(lua_State* L) {
return 0;
}
int goTo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::goTo");
int flyTo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::flyTo");
auto [nodeIdentifier, useUpFromTargetOrDuration, duration] = ghoul::lua::values<
std::string, std::optional<std::variant<bool, double>>, std::optional<double>
>(L);
@@ -120,8 +120,8 @@ int goTo(lua_State* L) {
return 0;
}
int goToHeight(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToHeight");
int flyToHeight(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::flyToHeight");
auto [nodeIdentifier, height, useUpFromTargetOrDuration, duration] =
ghoul::lua::values<
std::string, double, std::optional<std::variant<bool, double>>,
@@ -169,8 +169,8 @@ int goToHeight(lua_State* L) {
return 0;
}
int goToNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::goToNavigationState");
int flyToNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::flyToNavigationState");
auto [navigationState, duration] =
ghoul::lua::values<ghoul::Dictionary, std::optional<double>>(L);
@@ -182,7 +182,7 @@ int goToNavigationState(lua_State* L) {
);
}
catch (documentation::SpecificationError& e) {
LERRORC("goToNavigationState", ghoul::to_string(e.result));
LERRORC("flyToNavigationState", ghoul::to_string(e.result));
return ghoul::lua::luaError(
L, fmt::format("Unable to create a path: {}", e.what())
);

View File

@@ -130,6 +130,14 @@ namespace {
"shown on the screen"
};
constexpr openspace::properties::Property::PropertyInfo ScreenshotWindowIdsInfo = {
"ScreenshotWindowId",
"Screenshow Window Ids",
"The list of window identifiers whose screenshot will be taken the next time "
"anyone triggers a screenshot. If this list is empty (the default), all windows "
"will have their screenshot taken. Id's that do not exist are silently ignored."
};
constexpr openspace::properties::Property::PropertyInfo ApplyWarpingInfo = {
"ApplyWarpingScreenshot",
"Apply Warping to Screenshots",
@@ -277,6 +285,7 @@ RenderEngine::RenderEngine()
, _verticalLogOffset(VerticalLogOffsetInfo, 0.f, 0.f, 1.f)
, _showVersionInfo(ShowVersionInfo, true)
, _showCameraInfo(ShowCameraInfo, true)
, _screenshotWindowIds(ScreenshotWindowIdsInfo)
, _applyWarping(ApplyWarpingInfo, false)
, _screenshotUseDate(ScreenshotUseDateInfo, false)
, _showFrameInformation(ShowFrameNumberInfo, false)
@@ -342,6 +351,7 @@ RenderEngine::RenderEngine()
addProperty(_value);
addProperty(_globalBlackOutFactor);
addProperty(_screenshotWindowIds);
addProperty(_applyWarping);
_screenshotUseDate.onChange([this]() {
@@ -1046,7 +1056,10 @@ void RenderEngine::takeScreenshot() {
std::filesystem::create_directories(absPath("${SCREENSHOTS}"));
}
_latestScreenshotNumber = global::windowDelegate->takeScreenshot(_applyWarping);
_latestScreenshotNumber = global::windowDelegate->takeScreenshot(
_applyWarping,
_screenshotWindowIds
);
}
unsigned int RenderEngine::latestScreenshotNumber() const {

View File

@@ -40,7 +40,6 @@ add_executable(
test_rawvolumeio.cpp
test_scriptscheduler.cpp
test_spicemanager.cpp
test_temporaltileprovider.cpp
test_timequantizer.cpp
test_timeline.cpp