Merge branch 'master' into feature/model-opacity

* Solve conflicts in renderablemodel.cpp and renderabletrail.cpp
This commit is contained in:
Malin E
2023-04-12 17:03:40 +02:00
110 changed files with 1679 additions and 662 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -130,7 +130,6 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary)
const Parameters p = codegen::bake<Parameters>(dictionary);
addProperty(_opacity);
registerUpdateRenderBinFromOpacity();
_speckFile = absPath(p.file);

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@@ -377,7 +377,7 @@ void ScreenSpaceSkyBrowser::setOpacity(float opacity) {
_opacity = opacity;
}
float ScreenSpaceSkyBrowser::opacity() const {
float ScreenSpaceSkyBrowser::opacity() const noexcept {
return _opacity;
}

View File

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

View File

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

View File

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

View File

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

View File

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