mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
Merge branch 'master' into feature/model-opacity
* Solve conflicts in renderablemodel.cpp and renderabletrail.cpp
This commit is contained in:
@@ -92,7 +92,6 @@ RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
@@ -135,7 +135,6 @@ RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
@@ -117,7 +117,6 @@ RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
@@ -94,7 +94,6 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_color = p.color.value_or(_color);
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
|
||||
@@ -238,7 +238,7 @@ documentation::Documentation RenderableLabel::Documentation() {
|
||||
}
|
||||
|
||||
RenderableLabel::RenderableLabel(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
: Renderable(dictionary, { .automaticallyUpdateRenderBin = false })
|
||||
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _color(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _fontSize(FontSizeInfo, 50.f, 1.f, 100.f)
|
||||
@@ -260,11 +260,10 @@ RenderableLabel::RenderableLabel(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_blendMode.addOptions({
|
||||
{ BlendMode::Normal, "Normal" },
|
||||
{ BlendMode::Additive, "Additive"}
|
||||
{ BlendMode::Additive, "Additive" }
|
||||
});
|
||||
_blendMode.onChange([&]() {
|
||||
switch (_blendMode) {
|
||||
|
||||
@@ -297,7 +297,6 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
if (p.forceRenderInvisible.has_value()) {
|
||||
_forceRenderInvisible = *p.forceRenderInvisible;
|
||||
@@ -634,7 +633,7 @@ void RenderableModel::initializeGL() {
|
||||
setBoundingSphere(_geometry->boundingRadius() * _modelScale);
|
||||
|
||||
// Set Interaction sphere size to be 10% of the bounding sphere
|
||||
setInteractionSphere(_boundingSphere * 0.1);
|
||||
setInteractionSphere(boundingSphere() * 0.1);
|
||||
}
|
||||
|
||||
void RenderableModel::deinitializeGL() {
|
||||
|
||||
@@ -181,7 +181,7 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
"Trying to use relative offsets for start node '{}' that has no "
|
||||
"bounding sphere. This will result in no offset. Use direct "
|
||||
"values by setting UseRelativeOffsets to false",
|
||||
_parent->identifier(), _start
|
||||
parent()->identifier(), _start
|
||||
));
|
||||
}
|
||||
});
|
||||
@@ -199,7 +199,7 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
"Trying to use relative offsets for end node '{}' that has no "
|
||||
"bounding sphere. This will result in no offset. Use direct "
|
||||
"values by setting UseRelativeOffsets to false",
|
||||
_parent->identifier(), _end
|
||||
parent()->identifier(), _end
|
||||
));
|
||||
}
|
||||
});
|
||||
@@ -212,7 +212,7 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
if (!startNode) {
|
||||
LERROR(fmt::format(
|
||||
"Error when recomputing node line offsets for scene graph node '{}'. "
|
||||
"Could not find start node '{}'", _parent->identifier(), _start.value()
|
||||
"Could not find start node '{}'", parent()->identifier(), _start.value()
|
||||
));
|
||||
return;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
if (!endNode) {
|
||||
LERROR(fmt::format(
|
||||
"Error when recomputing node line offsets for scene graph node '{}'. "
|
||||
"Could not find end node '{}'", _parent->identifier(), _end.value()
|
||||
"Could not find end node '{}'", parent()->identifier(), _end.value()
|
||||
));
|
||||
return;
|
||||
}
|
||||
@@ -229,8 +229,10 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary)
|
||||
// Recompute previous offsets to relative values
|
||||
double startBs = startNode->boundingSphere();
|
||||
double endBs = endNode->boundingSphere();
|
||||
_startOffset = startBs > 0.0 ? _startOffset / startBs : 0.0;
|
||||
_endOffset = endBs > 0.0 ? _endOffset / startBs : 0.0;
|
||||
_startOffset =
|
||||
static_cast<float>(startBs > 0.0 ? _startOffset / startBs : 0.0);
|
||||
_endOffset =
|
||||
static_cast<float>(endBs > 0.0 ? _endOffset / startBs : 0.0);
|
||||
}
|
||||
else {
|
||||
// Recompute relative values to meters
|
||||
|
||||
@@ -113,7 +113,7 @@ documentation::Documentation RenderablePlane::Documentation() {
|
||||
}
|
||||
|
||||
RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
: Renderable(dictionary, { .automaticallyUpdateRenderBin = false })
|
||||
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
|
||||
, _billboard(BillboardInfo, false)
|
||||
, _mirrorBackside(MirrorBacksideInfo, false)
|
||||
@@ -123,7 +123,6 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
|
||||
Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_size = p.size;
|
||||
_billboard = p.billboard.value_or(_billboard);
|
||||
|
||||
@@ -162,7 +162,6 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_size = p.size;
|
||||
_segments = p.segments;
|
||||
@@ -208,7 +207,6 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_disableFadeInDistance);
|
||||
|
||||
setBoundingSphere(_size);
|
||||
setRenderBinFromOpacity();
|
||||
}
|
||||
|
||||
bool RenderableSphere::isReady() const {
|
||||
|
||||
@@ -164,7 +164,6 @@ RenderableTimeVaryingSphere::RenderableTimeVaryingSphere(
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_size = p.size;
|
||||
_segments = p.segments;
|
||||
@@ -208,7 +207,6 @@ RenderableTimeVaryingSphere::RenderableTimeVaryingSphere(
|
||||
}
|
||||
|
||||
setBoundingSphere(_size);
|
||||
setRenderBinFromOpacity();
|
||||
}
|
||||
|
||||
bool RenderableTimeVaryingSphere::isReady() const {
|
||||
|
||||
@@ -433,7 +433,7 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) {
|
||||
);
|
||||
const double distance = glm::distance(trailPosWorld, data.camera.eyePositionVec3());
|
||||
|
||||
if (distance > _boundingSphere * DISTANCE_CULLING_RADII) {
|
||||
if (distance > boundingSphere() * DISTANCE_CULLING_RADII) {
|
||||
// Reset
|
||||
global::renderEngine->openglStateCache().resetBlendState();
|
||||
global::renderEngine->openglStateCache().resetDepthState();
|
||||
|
||||
@@ -189,7 +189,6 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_speckFile = absPath(p.file).string();
|
||||
_hasSpeckFile = true;
|
||||
|
||||
@@ -130,7 +130,6 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_speckFile = absPath(p.file);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ set(HEADER_FILES
|
||||
src/tileindex.h
|
||||
src/tileloadjob.h
|
||||
src/tiletextureinitdata.h
|
||||
src/tilecacheproperties.h
|
||||
src/timequantizer.h
|
||||
src/tileprovider/defaulttileprovider.h
|
||||
src/tileprovider/imagesequencetileprovider.h
|
||||
|
||||
@@ -91,43 +91,24 @@
|
||||
namespace {
|
||||
constexpr std::string_view _loggerCat = "GlobeBrowsingModule";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo WMSCacheEnabledInfo = {
|
||||
"WMSCacheEnabled",
|
||||
"WMS Cache Enabled",
|
||||
"Determines whether automatic caching of WMS servers is enabled. Changing the "
|
||||
"value of this property will not affect already created WMS datasets"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo OfflineModeInfo = {
|
||||
"OfflineMode",
|
||||
"Offline Mode",
|
||||
"Determines whether loaded WMS servers should be used in offline mode, that is "
|
||||
"not even try to retrieve images through an internet connection. Please note "
|
||||
"that this setting is only reasonable, if the caching is enabled and there is "
|
||||
"available cached data. Changing the value of this property will not affect "
|
||||
"already created WMS datasets"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo WMSCacheLocationInfo = {
|
||||
"WMSCacheLocation",
|
||||
"WMS Cache Location",
|
||||
"The location of the cache folder for WMS servers. Changing the value of this "
|
||||
"property will not affect already created WMS datasets"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo WMSCacheSizeInfo = {
|
||||
"WMSCacheSize",
|
||||
"WMS Cache Size",
|
||||
"The maximum size of the cache for each WMS server. Changing the value of this "
|
||||
"property will not affect already created WMS datasets"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TileCacheSizeInfo = {
|
||||
"TileCacheSize",
|
||||
"Tile Cache Size",
|
||||
"The maximum size of the MemoryAwareTileCache, on the CPU and GPU"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo MRFCacheEnabledInfo = {
|
||||
"MRFCacheEnabled",
|
||||
"MRF Cache Enabled",
|
||||
"Determines whether automatic caching of globe browsing data is enabled."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo MRFCacheLocationInfo = {
|
||||
"MRFCacheLocation",
|
||||
"MRF Cache Location",
|
||||
"The location of the root folder for the MRF cache of globe browsing data."
|
||||
};
|
||||
|
||||
openspace::GlobeBrowsingModule::Capabilities
|
||||
parseSubDatasets(char** subDatasets, int nSubdatasets)
|
||||
{
|
||||
@@ -185,25 +166,15 @@ namespace {
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(GlobeBrowsingModule)]] Parameters {
|
||||
// [[codegen::verbatim(WMSCacheEnabledInfo.description)]]
|
||||
std::optional<bool> cacheEnabled [[codegen::key("WMSCacheEnabled")]];
|
||||
|
||||
// [[codegen::verbatim(OfflineModeInfo.description)]]
|
||||
std::optional<bool> offlineMode;
|
||||
|
||||
// [[codegen::verbatim(WMSCacheLocationInfo.description)]]
|
||||
std::optional<std::string> cacheLocation [[codegen::key("WMSCacheLocation")]];
|
||||
|
||||
// [[codegen::verbatim(WMSCacheSizeInfo.description)]]
|
||||
std::optional<int> wmsCacheSize [[codegen::key("WMSCacheSize")]];
|
||||
|
||||
// [[codegen::verbatim(TileCacheSizeInfo.description)]]
|
||||
std::optional<int> tileCacheSize;
|
||||
|
||||
// If you know what you are doing and you have WMS caching *disabled* but offline
|
||||
// mode *enabled*, you can set this value to 'true' to silence a warning that you
|
||||
// would otherwise get at startup
|
||||
std::optional<bool> noWarning;
|
||||
// [[codegen::verbatim(MRFCacheEnabledInfo.description)]]
|
||||
std::optional<bool> mrfCacheEnabled [[codegen::key("MRFCacheEnabled")]];
|
||||
|
||||
// [[codegen::verbatim(MRFCacheLocationInfo.description)]]
|
||||
std::optional<std::string> mrfCacheLocation [[codegen::key("MRFCacheLocation")]];
|
||||
};
|
||||
#include "globebrowsingmodule_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -212,40 +183,22 @@ namespace openspace {
|
||||
|
||||
GlobeBrowsingModule::GlobeBrowsingModule()
|
||||
: OpenSpaceModule(Name)
|
||||
, _wmsCacheEnabled(WMSCacheEnabledInfo, false)
|
||||
, _offlineMode(OfflineModeInfo, false)
|
||||
, _wmsCacheLocation(WMSCacheLocationInfo, "${BASE}/cache_gdal")
|
||||
, _wmsCacheSizeMB(WMSCacheSizeInfo, 1024)
|
||||
, _tileCacheSizeMB(TileCacheSizeInfo, 1024)
|
||||
, _mrfCacheEnabled(MRFCacheEnabledInfo, false)
|
||||
, _mrfCacheLocation(MRFCacheLocationInfo, "${BASE}/cache_mrf")
|
||||
{
|
||||
addProperty(_wmsCacheEnabled);
|
||||
addProperty(_offlineMode);
|
||||
addProperty(_wmsCacheLocation);
|
||||
addProperty(_wmsCacheSizeMB);
|
||||
addProperty(_tileCacheSizeMB);
|
||||
addProperty(_mrfCacheEnabled);
|
||||
addProperty(_mrfCacheLocation);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
using namespace globebrowsing;
|
||||
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
_wmsCacheEnabled = p.cacheEnabled.value_or(_wmsCacheEnabled);
|
||||
_offlineMode = p.offlineMode.value_or(_offlineMode);
|
||||
_wmsCacheLocation = p.cacheLocation.value_or(_wmsCacheLocation);
|
||||
_wmsCacheSizeMB = p.wmsCacheSize.value_or(_wmsCacheSizeMB);
|
||||
_tileCacheSizeMB = p.tileCacheSize.value_or(_tileCacheSizeMB);
|
||||
const bool noWarning = p.noWarning.value_or(false);
|
||||
|
||||
if (!_wmsCacheEnabled && _offlineMode && !noWarning) {
|
||||
LWARNINGC(
|
||||
"GlobeBrowsingModule",
|
||||
"WMS caching is disabled, but offline mode is enabled. Unless you know "
|
||||
"what you are doing, this will probably cause many servers to stop working. "
|
||||
"If you want to silence this warning, set the 'NoWarning' parameter to "
|
||||
"'true'"
|
||||
);
|
||||
}
|
||||
|
||||
_mrfCacheEnabled = p.mrfCacheEnabled.value_or(_mrfCacheEnabled);
|
||||
_mrfCacheLocation = p.mrfCacheLocation.value_or(_mrfCacheLocation);
|
||||
|
||||
// Initialize
|
||||
global::callback::initializeGL->emplace_back([&]() {
|
||||
@@ -670,21 +623,12 @@ bool GlobeBrowsingModule::hasUrlInfo(const std::string& globe) const {
|
||||
return _urlList.find(globe) != _urlList.end();
|
||||
}
|
||||
|
||||
bool GlobeBrowsingModule::isWMSCachingEnabled() const {
|
||||
return _wmsCacheEnabled;
|
||||
bool GlobeBrowsingModule::isMRFCachingEnabled() const {
|
||||
return _mrfCacheEnabled;
|
||||
}
|
||||
|
||||
bool GlobeBrowsingModule::isInOfflineMode() const {
|
||||
return _offlineMode;
|
||||
}
|
||||
|
||||
std::string GlobeBrowsingModule::wmsCacheLocation() const {
|
||||
return _wmsCacheLocation;
|
||||
}
|
||||
|
||||
uint64_t GlobeBrowsingModule::wmsCacheSize() const {
|
||||
uint64_t size = _wmsCacheSizeMB;
|
||||
return size * 1024 * 1024;
|
||||
const std::string GlobeBrowsingModule::mrfCacheLocation() const {
|
||||
return _mrfCacheLocation;
|
||||
}
|
||||
|
||||
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
|
||||
@@ -92,10 +92,8 @@ public:
|
||||
|
||||
void removeWMSServer(const std::string& name);
|
||||
|
||||
bool isWMSCachingEnabled() const;
|
||||
bool isInOfflineMode() const;
|
||||
std::string wmsCacheLocation() const;
|
||||
uint64_t wmsCacheSize() const; // bytes
|
||||
bool isMRFCachingEnabled() const;
|
||||
const std::string mrfCacheLocation() const;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
@@ -113,12 +111,11 @@ private:
|
||||
glm::dquat lookDownCameraRotation(const globebrowsing::RenderableGlobe& globe,
|
||||
glm::dvec3 cameraPositionModelSpace, globebrowsing::Geodetic2 geo2);
|
||||
|
||||
properties::BoolProperty _wmsCacheEnabled;
|
||||
properties::BoolProperty _offlineMode;
|
||||
properties::StringProperty _wmsCacheLocation;
|
||||
properties::UIntProperty _wmsCacheSizeMB;
|
||||
properties::UIntProperty _tileCacheSizeMB;
|
||||
|
||||
properties::BoolProperty _mrfCacheEnabled;
|
||||
properties::StringProperty _mrfCacheLocation;
|
||||
|
||||
std::unique_ptr<globebrowsing::cache::MemoryAwareTileCache> _tileCache;
|
||||
|
||||
// name -> capabilities
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace {
|
||||
throw ghoul::lua::LuaError("Unknown layer group: " + layerGroupName);
|
||||
}
|
||||
|
||||
// Add the name of the enclosing globe to layer dict, it is used to identify a cache
|
||||
layer.setValue("GlobeName", globeName);
|
||||
|
||||
// Get the dictionary defining the layer
|
||||
Layer* l = globe->layerManager().addLayer(groupID, layer);
|
||||
if (l) {
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/exception.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
@@ -54,11 +53,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <system_error>
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::string_view _loggerCat = "RawTileDataReader";
|
||||
// These are some locations in memory taken from ESRI's No Data Available tile so that we
|
||||
// can spotcheck these tiles and not present them
|
||||
// The pair is <byte index, expected value>
|
||||
@@ -421,9 +422,11 @@ RawTile::ReadError postProcessErrorCheck(const RawTile& rawTile,
|
||||
|
||||
RawTileDataReader::RawTileDataReader(std::string filePath,
|
||||
TileTextureInitData initData,
|
||||
TileCacheProperties cacheProperties,
|
||||
PerformPreprocessing preprocess)
|
||||
: _datasetFilePath(std::move(filePath))
|
||||
, _initData(std::move(initData))
|
||||
, _cacheProperties(std::move(cacheProperties))
|
||||
, _preprocess(preprocess)
|
||||
{
|
||||
ZoneScoped;
|
||||
@@ -439,83 +442,115 @@ RawTileDataReader::~RawTileDataReader() {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> RawTileDataReader::mrfCache() {
|
||||
// We don't support these formats as they will typically lack
|
||||
// crucial imformation such as GeoTags. It also makes little sense to
|
||||
// cache them as they are already local files.
|
||||
// If it is crucial to cache a dataset of this type, convert it to geotiff.
|
||||
constexpr std::array<std::string_view, 11> Unsupported = {
|
||||
"jpeg", "jpg",
|
||||
"png",
|
||||
"bmp",
|
||||
"psd",
|
||||
"tga",
|
||||
"gif",
|
||||
"hdr",
|
||||
"pic",
|
||||
"ppm", "pgm"
|
||||
};
|
||||
|
||||
for (std::string_view fmt : Unsupported) {
|
||||
if (_datasetFilePath.ends_with(fmt)) {
|
||||
LWARNING(fmt::format(
|
||||
"Unsupported file format for MRF caching: {}, Dataset: {}",
|
||||
fmt, _datasetFilePath
|
||||
));
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
GlobeBrowsingModule& module = *global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
|
||||
std::string datasetIdentifier =
|
||||
std::to_string(std::hash<std::string>{}(_datasetFilePath));
|
||||
std::string path = fmt::format("{}/{}/{}/",
|
||||
module.mrfCacheLocation(), _cacheProperties.path, datasetIdentifier);
|
||||
std::string root = absPath(path).string();
|
||||
std::string mrf = root + datasetIdentifier + ".mrf";
|
||||
std::string cache = root + datasetIdentifier + ".mrfcache";
|
||||
|
||||
if (!std::filesystem::exists(mrf)) {
|
||||
std::error_code ec;
|
||||
if (!std::filesystem::create_directories(root, ec)) {
|
||||
// Already existing directories causes a 'failure' but no error
|
||||
if (ec) {
|
||||
LWARNING(fmt::format(
|
||||
"Failed to create directories for cache at: {}. Error Code: {}, message: {}",
|
||||
root, std::to_string(ec.value()), ec.message()
|
||||
));
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("MRF");
|
||||
if (driver != nullptr) {
|
||||
GDALDataset* src = static_cast<GDALDataset*>(GDALOpen(_datasetFilePath.c_str(), GA_ReadOnly));
|
||||
if (!src) {
|
||||
LWARNING(fmt::format(
|
||||
"Failed to load dataset: {}. GDAL Error: {}",
|
||||
_datasetFilePath, CPLGetLastErrorMsg()
|
||||
));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
defer{ GDALClose(src); };
|
||||
|
||||
char** createOpts = nullptr;
|
||||
createOpts = CSLSetNameValue(createOpts, "CACHEDSOURCE", _datasetFilePath.c_str());
|
||||
createOpts = CSLSetNameValue(createOpts, "NOCOPY", "true");
|
||||
createOpts = CSLSetNameValue(createOpts, "uniform_scale", "2");
|
||||
createOpts = CSLSetNameValue(createOpts, "compress", _cacheProperties.compression.c_str());
|
||||
createOpts = CSLSetNameValue(createOpts, "quality", std::to_string(_cacheProperties.quality).c_str());
|
||||
createOpts = CSLSetNameValue(createOpts, "blocksize", std::to_string(_cacheProperties.blockSize).c_str());
|
||||
createOpts = CSLSetNameValue(createOpts, "indexname", cache.c_str());
|
||||
createOpts = CSLSetNameValue(createOpts, "DATANAME", cache.c_str());
|
||||
|
||||
GDALDataset* dst = static_cast<GDALDataset*>(driver->CreateCopy(mrf.c_str(), src, false, createOpts, nullptr, nullptr));
|
||||
if (!dst) {
|
||||
LWARNING(fmt::format(
|
||||
"Failed to create MRF Caching dataset dataset: {}. GDAL Error: {}",
|
||||
mrf, CPLGetLastErrorMsg()
|
||||
));
|
||||
return std::nullopt;
|
||||
}
|
||||
GDALClose(dst);
|
||||
|
||||
return mrf;
|
||||
}
|
||||
else {
|
||||
LWARNING("Failed to create MRF driver");
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return mrf;
|
||||
}
|
||||
}
|
||||
|
||||
void RawTileDataReader::initialize() {
|
||||
ZoneScoped;
|
||||
|
||||
if (_datasetFilePath.empty()) {
|
||||
throw ghoul::RuntimeError("File path must not be empty");
|
||||
}
|
||||
|
||||
GlobeBrowsingModule& module = *global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
|
||||
std::string content = _datasetFilePath;
|
||||
if (module.isWMSCachingEnabled()) {
|
||||
ZoneScopedN("WMS Caching");
|
||||
std::string c;
|
||||
if (std::filesystem::is_regular_file(_datasetFilePath)) {
|
||||
// Only replace the 'content' if the dataset is an XML file and we want to do
|
||||
// caching
|
||||
std::ifstream t(_datasetFilePath);
|
||||
c.append(
|
||||
(std::istreambuf_iterator<char>(t)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
}
|
||||
else {
|
||||
//GDAL input case for configuration string (e.g. temporal data)
|
||||
c = _datasetFilePath;
|
||||
}
|
||||
|
||||
if (c.size() > 10 && c.substr(0, 10) == "<GDAL_WMS>") {
|
||||
// We know that _datasetFilePath is an XML file, so now we add a Cache line
|
||||
// into it iff there isn't already one in the XML and if the configuration
|
||||
// says we should
|
||||
if (_cacheProperties.enabled) {
|
||||
ZoneScopedN("MRF Caching");
|
||||
|
||||
// 1. Parse XML
|
||||
// 2. Inject Cache tag if it isn't already there
|
||||
// 3. Serialize XML to pass into GDAL
|
||||
|
||||
LDEBUGC(_datasetFilePath, "Inserting caching tag");
|
||||
|
||||
bool shouldSerializeXml = false;
|
||||
|
||||
CPLXMLNode* root = CPLParseXMLString(c.c_str());
|
||||
CPLXMLNode* cache = CPLSearchXMLNode(root, "Cache");
|
||||
if (!cache) {
|
||||
// If there already is a cache, we don't want to modify it
|
||||
cache = CPLCreateXMLNode(root, CXT_Element, "Cache");
|
||||
|
||||
CPLCreateXMLElementAndValue(
|
||||
cache,
|
||||
"Path",
|
||||
absPath(module.wmsCacheLocation()).string().c_str()
|
||||
);
|
||||
CPLCreateXMLElementAndValue(cache, "Depth", "4");
|
||||
CPLCreateXMLElementAndValue(cache, "Expires", "315576000"); // 10 years
|
||||
CPLCreateXMLElementAndValue(
|
||||
cache,
|
||||
"MaxSize",
|
||||
std::to_string(module.wmsCacheSize()).c_str()
|
||||
);
|
||||
|
||||
// The serialization only needs to be one if the cache didn't exist
|
||||
// already
|
||||
shouldSerializeXml = true;
|
||||
}
|
||||
|
||||
if (module.isInOfflineMode()) {
|
||||
CPLXMLNode* offlineMode = CPLSearchXMLNode(root, "OfflineMode");
|
||||
if (!offlineMode) {
|
||||
CPLCreateXMLElementAndValue(root, "OfflineMode", "true");
|
||||
shouldSerializeXml = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shouldSerializeXml) {
|
||||
content = std::string(CPLSerializeXMLTree(root));
|
||||
//CPLSerializeXMLTreeToFile(root, (_datasetFilePath + ".xml").c_str());
|
||||
}
|
||||
std::optional<std::string> cache = mrfCache();
|
||||
if (cache.has_value()) {
|
||||
content = cache.value();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <modules/globebrowsing/src/basictypes.h>
|
||||
#include <modules/globebrowsing/src/rawtile.h>
|
||||
#include <modules/globebrowsing/src/tiletextureinitdata.h>
|
||||
#include <modules/globebrowsing/src/tilecacheproperties.h>
|
||||
#include <ghoul/misc/boolean.h>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
@@ -53,6 +54,7 @@ public:
|
||||
* \param baseDirectory, the base directory to use in future loading operations
|
||||
*/
|
||||
RawTileDataReader(std::string filePath, TileTextureInitData initData,
|
||||
TileCacheProperties cacheProperties,
|
||||
PerformPreprocessing preprocess = PerformPreprocessing::No);
|
||||
~RawTileDataReader();
|
||||
|
||||
@@ -65,6 +67,8 @@ public:
|
||||
glm::ivec2 fullPixelSize() const;
|
||||
|
||||
private:
|
||||
std::optional<std::string> mrfCache();
|
||||
|
||||
void initialize();
|
||||
|
||||
RawTile::ReadError rasterRead(int rasterBand, const IODescription& io,
|
||||
@@ -97,6 +101,7 @@ private:
|
||||
int _maxChunkLevel = -1;
|
||||
|
||||
const TileTextureInitData _initData;
|
||||
const TileCacheProperties _cacheProperties;
|
||||
const PerformPreprocessing _preprocess;
|
||||
TileDepthTransform _depthTransform = { .scale = 0.f, .offset = 0.f };
|
||||
|
||||
|
||||
42
modules/globebrowsing/src/tilecacheproperties.h
Normal file
42
modules/globebrowsing/src/tilecacheproperties.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* *
|
||||
* 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_CACHE_PROPERTIES___H__
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_CACHE_PROPERTIES___H__
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
struct TileCacheProperties {
|
||||
bool enabled = false;
|
||||
std::string compression;
|
||||
std::string path;
|
||||
int quality;
|
||||
int blockSize;
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE_CACHE_PROPERTIES___H__
|
||||
@@ -48,10 +48,25 @@ namespace {
|
||||
"complete image if a single image is used"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo CompressionInfo = {
|
||||
"Compression",
|
||||
"Compression Algorithm",
|
||||
"The compression algorithm to use for MRF cached tiles"
|
||||
};
|
||||
|
||||
enum class [[codegen::stringify()]] Compression {
|
||||
PNG = 0,
|
||||
JPEG,
|
||||
LERC
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(DefaultTileProvider)]] Parameters {
|
||||
// User-facing name of this tile provider
|
||||
std::optional<std::string> name;
|
||||
|
||||
// Identifier of the enclosing layer to which tiles are provided
|
||||
std::optional<std::string> identifier;
|
||||
|
||||
// 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
|
||||
@@ -70,6 +85,32 @@ namespace {
|
||||
// Determines if the tiles should be preprocessed before uploading to the GPU
|
||||
std::optional<bool> performPreProcessing;
|
||||
|
||||
struct CacheSettings {
|
||||
// Specifies whether to use caching or not
|
||||
std::optional<bool> enabled;
|
||||
|
||||
// [[codegen::verbatim(CompressionInfo.description)]]
|
||||
enum class [[codegen::map(Compression)]] Compression {
|
||||
PNG = 0,
|
||||
JPEG,
|
||||
LERC
|
||||
};
|
||||
|
||||
// The compression algorithm to use for cached tiles
|
||||
std::optional<Compression> compression;
|
||||
|
||||
// The quality setting of the compression alogrithm, only valid for JPEG
|
||||
std::optional<int> quality [[codegen::inrange(0, 100)]];
|
||||
|
||||
// The block-size of the MRF cache
|
||||
std::optional<int> blockSize [[codegen::greater(0)]];
|
||||
};
|
||||
// Specifies the cache settings that should be applied to this layer
|
||||
std::optional<CacheSettings> cacheSettings;
|
||||
|
||||
// The name of the enclosing globe
|
||||
std::optional<std::string> globeName;
|
||||
|
||||
};
|
||||
#include "defaulttileprovider_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -105,17 +146,53 @@ DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary)
|
||||
_performPreProcessing = _layerGroupID == layers::Group::ID::HeightLayers;
|
||||
_performPreProcessing = p.performPreProcessing.value_or(_performPreProcessing);
|
||||
|
||||
// Get the name of the layergroup to which this layer belongs
|
||||
auto it = std::find_if(
|
||||
layers::Groups.begin(),
|
||||
layers::Groups.end(),
|
||||
[id = _layerGroupID](const layers::Group& gi) {
|
||||
return gi.id == id;
|
||||
}
|
||||
);
|
||||
auto layerGroup = it != layers::Groups.end() ? it->name : std::to_string(static_cast<int>(_layerGroupID));
|
||||
|
||||
std::string identifier = p.identifier.value_or("unspecified");
|
||||
std::string enclosing = p.globeName.value_or("unspecified");
|
||||
|
||||
std::string path = fmt::format("{}/{}/{}/", enclosing, layerGroup, identifier);
|
||||
|
||||
GlobeBrowsingModule& module = *global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
bool enabled = module.isMRFCachingEnabled();
|
||||
Compression compression =
|
||||
_layerGroupID == layers::Group::ID::HeightLayers ? Compression::LERC : Compression::JPEG;
|
||||
int quality = 75;
|
||||
int blockSize = 1024;
|
||||
if (p.cacheSettings.has_value()) {
|
||||
enabled = p.cacheSettings->enabled.value_or(enabled);
|
||||
if (p.cacheSettings->compression.has_value()) {
|
||||
compression = codegen::map<Compression>(*p.cacheSettings->compression);
|
||||
}
|
||||
quality = p.cacheSettings->quality.value_or(quality);
|
||||
blockSize = p.cacheSettings->blockSize.value_or(blockSize);
|
||||
}
|
||||
|
||||
_cacheProperties.enabled = enabled;
|
||||
_cacheProperties.path = path;
|
||||
_cacheProperties.quality = quality;
|
||||
_cacheProperties.blockSize = blockSize;
|
||||
_cacheProperties.compression = codegen::toString(compression);
|
||||
|
||||
TileTextureInitData initData(
|
||||
tileTextureInitData(_layerGroupID, _padTiles, pixelSize)
|
||||
);
|
||||
_tilePixelSize = initData.dimensions.x;
|
||||
initAsyncTileDataReader(initData);
|
||||
initAsyncTileDataReader(initData, _cacheProperties);
|
||||
|
||||
addProperty(_filePath);
|
||||
addProperty(_tilePixelSize);
|
||||
}
|
||||
|
||||
void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData) {
|
||||
void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData, TileCacheProperties cacheProperties) {
|
||||
ZoneScoped;
|
||||
|
||||
_asyncTextureDataProvider = std::make_unique<AsyncTileDataProvider>(
|
||||
@@ -123,6 +200,7 @@ void DefaultTileProvider::initAsyncTileDataReader(TileTextureInitData initData)
|
||||
std::make_unique<RawTileDataReader>(
|
||||
_filePath,
|
||||
initData,
|
||||
cacheProperties,
|
||||
RawTileDataReader::PerformPreprocessing(_performPreProcessing)
|
||||
)
|
||||
);
|
||||
@@ -189,7 +267,8 @@ void DefaultTileProvider::update() {
|
||||
|
||||
if (_asyncTextureDataProvider->shouldBeDeleted()) {
|
||||
initAsyncTileDataReader(
|
||||
tileTextureInitData(_layerGroupID, _padTiles, _tilePixelSize)
|
||||
tileTextureInitData(_layerGroupID, _padTiles, _tilePixelSize),
|
||||
_cacheProperties
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__DEFAULTTILEPROVIDER___H__
|
||||
|
||||
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
|
||||
|
||||
#include <modules/globebrowsing/src/tilecacheproperties.h>
|
||||
#include <modules/globebrowsing/src/asynctiledataprovider.h>
|
||||
#include <memory>
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
void initAsyncTileDataReader(TileTextureInitData initData);
|
||||
void initAsyncTileDataReader(TileTextureInitData initData, TileCacheProperties cacheProperties);
|
||||
|
||||
properties::StringProperty _filePath;
|
||||
properties::IntProperty _tilePixelSize;
|
||||
@@ -57,6 +57,7 @@ private:
|
||||
layers::Group::ID _layerGroupID = layers::Group::ID::Unknown;
|
||||
bool _performPreProcessing = false;
|
||||
bool _padTiles = true;
|
||||
TileCacheProperties _cacheProperties;
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
void render() override;
|
||||
void update() override;
|
||||
|
||||
float opacity() const;
|
||||
float opacity() const noexcept;
|
||||
glm::dvec2 fineTuneVector(const glm::dvec2& drag);
|
||||
bool isInitialized() const;
|
||||
bool isPointingSpacecraft() const;
|
||||
|
||||
@@ -377,7 +377,7 @@ void ScreenSpaceSkyBrowser::setOpacity(float opacity) {
|
||||
_opacity = opacity;
|
||||
}
|
||||
|
||||
float ScreenSpaceSkyBrowser::opacity() const {
|
||||
float ScreenSpaceSkyBrowser::opacity() const noexcept {
|
||||
return _opacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ RenderableConstellationsBase::RenderableConstellationsBase(
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
// Avoid reading files here, instead do it in multithreaded initialize()
|
||||
if (p.namesFile.has_value()) {
|
||||
|
||||
@@ -541,7 +541,6 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_dataMapping.bvColor = p.dataMapping.bv.value_or("");
|
||||
_dataMapping.bvColor.onChange([this]() { _dataIsDirty = true; });
|
||||
|
||||
@@ -259,7 +259,7 @@ void RenderableTravelSpeed::update(const UpdateData& data) {
|
||||
}
|
||||
|
||||
_targetPosition = _targetNode->worldPosition();
|
||||
SceneGraphNode* mySGNPointer = _parent;
|
||||
SceneGraphNode* mySGNPointer = parent();
|
||||
ghoul_assert(mySGNPointer, "Renderable have to be owned by scene graph node");
|
||||
_sourcePosition = mySGNPointer->worldPosition();
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ void RenderableModelProjection::initializeGL() {
|
||||
setBoundingSphere(_geometry->boundingRadius() * _modelScale);
|
||||
|
||||
// Set Interaction sphere size to be 10% of the bounding sphere
|
||||
setInteractionSphere(_boundingSphere * 0.1);
|
||||
setInteractionSphere(boundingSphere() * 0.1);
|
||||
}
|
||||
|
||||
void RenderableModelProjection::deinitializeGL() {
|
||||
|
||||
@@ -161,7 +161,6 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_numberOfPoints = p.numberOfPoints.value_or(_numberOfPoints);
|
||||
addProperty(_numberOfPoints);
|
||||
|
||||
Reference in New Issue
Block a user