Job::~Job() {}
template
-ConcurrentJobManager::ConcurrentJobManager(std::shared_ptr pool)
+ConcurrentJobManager::ConcurrentJobManager(ThreadPool pool)
: threadPool(pool)
{ }
template
void ConcurrentJobManager::enqueueJob(std::shared_ptr> job) {
- threadPool->enqueue([this, job]() {
+ threadPool.enqueue([this, job]() {
job->execute();
std::lock_guard lock(_finishedJobsMutex);
_finishedJobs.push(job);
@@ -49,7 +49,7 @@ void ConcurrentJobManager::enqueueJob(std::shared_ptr> job) {
template
void ConcurrentJobManager::clearEnqueuedJobs() {
- threadPool->clearTasks();
+ threadPool.clearTasks();
}
template
diff --git a/modules/globebrowsing/other/distanceswitch.cpp b/modules/globebrowsing/other/distanceswitch.cpp
index 1b6ff8349f..aeb95de079 100644
--- a/modules/globebrowsing/other/distanceswitch.cpp
+++ b/modules/globebrowsing/other/distanceswitch.cpp
@@ -32,7 +32,6 @@ namespace globebrowsing {
DistanceSwitch::~DistanceSwitch() {}
bool DistanceSwitch::initialize() {
- _objectScale = 1.0;
for (unsigned int i = 0; i < _renderables.size(); ++i) {
_renderables[i]->initialize();
}
@@ -46,44 +45,32 @@ bool DistanceSwitch::deinitialize() {
return true;
}
-
void DistanceSwitch::render(const RenderData& data) {
- if (_maxDistances.size() == 0) {
- return;
- }
-
- double distanceToCamera = distance(data.camera.positionVec3(), data.modelTransform.translation);
-
- if (distanceToCamera > _maxDistances.back() * _objectScale) {
- return;
- }
+ const double distanceToCamera =
+ distance(data.camera.positionVec3(), data.modelTransform.translation);
+ // This distance will be enough to render the globe as one pixel if the field of
+ // view is 'fov' radians and the screen resolution is 'res' pixels.
+ const double fov = 2 * glm::pi() / 6; // 60 degrees
+ int res = 2880;
+
// linear search through nodes to find which Renderable to render
- for (unsigned int i = 0; i < _renderables.size(); ++i) {
- if (distanceToCamera < _maxDistances[i] * _objectScale) {
- _renderables[i]->render(data);
- return;
+ for (std::shared_ptr renderable : _renderables) {
+ const double distance = res * renderable->boundingSphere() / tan(fov / 2);
+ if (distanceToCamera < distance) {
+ renderable->render(data);
}
}
}
void DistanceSwitch::update(const UpdateData& data) {
- _objectScale = data.modelTransform.scale;
- for (unsigned int i = 0; i < _renderables.size(); ++i) {
- _renderables[i]->update(data);
+ for (std::shared_ptr renderable : _renderables) {
+ renderable->update(data);
}
}
-void DistanceSwitch::addSwitchValue(std::shared_ptr renderable,
- double maxDistance)
-{
- ghoul_assert(maxDistance > 0, "Renderable must have a positive maxDistance");
- if (_maxDistances.size() > 0) {
- ghoul_assert(maxDistance > _maxDistances.back(),
- "Renderables must be inserted in ascending order wrt distance");
- }
+void DistanceSwitch::addSwitchValue(std::shared_ptr renderable) {
_renderables.push_back(renderable);
- _maxDistances.push_back(maxDistance);
}
} // namespace globebrowsing
diff --git a/modules/globebrowsing/other/distanceswitch.h b/modules/globebrowsing/other/distanceswitch.h
index 9f26e35f43..2ba77a9d90 100644
--- a/modules/globebrowsing/other/distanceswitch.h
+++ b/modules/globebrowsing/other/distanceswitch.h
@@ -39,7 +39,7 @@ namespace globebrowsing {
/**
* Selects a specific Renderable to be used for rendering, based on distance to the
* camera
-*/
+ */
class DistanceSwitch {
public:
~DistanceSwitch();
@@ -50,20 +50,17 @@ public:
/**
* Picks the first Renderable with the associated maxDistance greater than the
* current distance to the camera
- */
+ */
void render(const RenderData& data);
void update(const UpdateData& data);
/**
- * Adds a new renderable (first argument) which may be rendered only if the distance
- * to the camera is less than maxDistance (second argument)
- */
- void addSwitchValue(std::shared_ptr renderable, double maxDistance);
+ * Adds a new renderable
+ */
+ void addSwitchValue(std::shared_ptr renderable);
private:
std::vector> _renderables;
- std::vector _maxDistances;
- double _objectScale;
};
} // namespace globebrowsing
diff --git a/modules/globebrowsing/other/lruthreadpool.h b/modules/globebrowsing/other/lruthreadpool.h
index 35a370a179..1b89e04ce1 100644
--- a/modules/globebrowsing/other/lruthreadpool.h
+++ b/modules/globebrowsing/other/lruthreadpool.h
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
// Implementatin based on http://progsch.net/wordpress/?p=81
@@ -65,6 +66,7 @@ template
class LRUThreadPool {
public:
LRUThreadPool(size_t numThreads, size_t queueSize);
+ LRUThreadPool(const LRUThreadPool& toCopy);
~LRUThreadPool();
void enqueue(std::function f, KeyType key);
diff --git a/modules/globebrowsing/other/lruthreadpool.inl b/modules/globebrowsing/other/lruthreadpool.inl
index 329767e3bc..bcc57029b5 100644
--- a/modules/globebrowsing/other/lruthreadpool.inl
+++ b/modules/globebrowsing/other/lruthreadpool.inl
@@ -68,11 +68,18 @@ LRUThreadPool::LRUThreadPool(size_t numThreads, size_t queueSize)
}
}
+template
+LRUThreadPool::LRUThreadPool(const LRUThreadPool& toCopy)
+ : LRUThreadPool(toCopy._workers.size(), toCopy._queuedTasks.maximumCacheSize())
+{ }
+
// the destructor joins all threads
template
LRUThreadPool::~LRUThreadPool() {
- // Stop all threads
- _stop = true;
+ {
+ std::unique_lock lock(_queueMutex);
+ _stop = true;
+ }
_condition.notify_all();
// join them
diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h
index f2314b07f5..6b166dd1a2 100644
--- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h
+++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.h
@@ -43,7 +43,7 @@ namespace globebrowsing {
template
class PrioritizingConcurrentJobManager {
public:
- PrioritizingConcurrentJobManager(std::shared_ptr> pool);
+ PrioritizingConcurrentJobManager(LRUThreadPool pool);
/**
* Enqueues a job which is identified using a given key
@@ -85,9 +85,10 @@ public:
private:
ConcurrentQueue>> _finishedJobs;
- /// An LRU thread pool is used since the jobs can be bumped and hence prioritized.
- std::shared_ptr> _threadPool;
std::mutex _finishedJobsMutex;
+ /// An LRU thread pool is used since the jobs can be bumped and hence prioritized.
+ LRUThreadPool _threadPool;
+
};
} // namespace globebrowsing
diff --git a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl
index ebe0147947..dbfbcbefdf 100644
--- a/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl
+++ b/modules/globebrowsing/other/prioritizingconcurrentjobmanager.inl
@@ -29,7 +29,7 @@ namespace globebrowsing {
template
PrioritizingConcurrentJobManager::PrioritizingConcurrentJobManager(
- std::shared_ptr> pool)
+ LRUThreadPool pool)
: _threadPool(pool)
{ }
@@ -37,7 +37,7 @@ template
void PrioritizingConcurrentJobManager::enqueueJob(std::shared_ptr> job,
KeyType key)
{
- _threadPool->enqueue([this, job]() {
+ _threadPool.enqueue([this, job]() {
job->execute();
std::lock_guard lock(_finishedJobsMutex);
_finishedJobs.push(job);
@@ -47,23 +47,23 @@ void PrioritizingConcurrentJobManager::enqueueJob(std::shared_ptr
std::vector
PrioritizingConcurrentJobManager::getKeysToUnfinishedJobs() {
- return _threadPool->getUnqueuedTasksKeys();
+ return _threadPool.getUnqueuedTasksKeys();
}
template
std::vector
PrioritizingConcurrentJobManager::getKeysToEnqueuedJobs() {
- return _threadPool->getQueuedTasksKeys();
+ return _threadPool.getQueuedTasksKeys();
}
template
bool PrioritizingConcurrentJobManager::touch(KeyType key) {
- return _threadPool->touch(key);
+ return _threadPool.touch(key);
}
template
void PrioritizingConcurrentJobManager::clearEnqueuedJobs() {
- _threadPool->clearEnqueuedTasks();
+ _threadPool.clearEnqueuedTasks();
}
template
diff --git a/modules/globebrowsing/other/threadpool.cpp b/modules/globebrowsing/other/threadpool.cpp
index 10de678202..a5a6fb718a 100644
--- a/modules/globebrowsing/other/threadpool.cpp
+++ b/modules/globebrowsing/other/threadpool.cpp
@@ -67,10 +67,17 @@ ThreadPool::ThreadPool(size_t numThreads)
}
}
+ThreadPool::ThreadPool(const ThreadPool& toCopy)
+ : ThreadPool(toCopy.workers.size())
+{ }
+
// the destructor joins all threads
ThreadPool::~ThreadPool() {
// stop all threads
- stop = true;
+ {
+ std::unique_lock lock(queue_mutex);
+ stop = true;
+ }
condition.notify_all();
// join them
diff --git a/modules/globebrowsing/other/threadpool.h b/modules/globebrowsing/other/threadpool.h
index 97bf25190b..475714086f 100644
--- a/modules/globebrowsing/other/threadpool.h
+++ b/modules/globebrowsing/other/threadpool.h
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
// Implementatin based on http://progsch.net/wordpress/?p=81
@@ -50,6 +51,7 @@ private:
class ThreadPool {
public:
ThreadPool(size_t numThreads);
+ ThreadPool(const ThreadPool& toCopy);
~ThreadPool();
void enqueue(std::function f);
diff --git a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp
index 5b77c34f9b..ce2fa871ef 100644
--- a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp
+++ b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp
@@ -38,7 +38,7 @@ void GPUHeightLayer::setValue(ghoul::opengl::ProgramObject* programObject,
int pileSize)
{
GPULayer::setValue(programObject, layer, tileIndex, pileSize);
- _gpuDepthTransform.setValue(programObject, layer.tileProvider()->depthTransform());
+ _gpuDepthTransform.setValue(programObject, layer.depthTransform());
}
void GPUHeightLayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.cpp b/modules/globebrowsing/rendering/gpu/gpulayer.cpp
index e02dd15a45..edfeb457ef 100644
--- a/modules/globebrowsing/rendering/gpu/gpulayer.cpp
+++ b/modules/globebrowsing/rendering/gpu/gpulayer.cpp
@@ -33,15 +33,51 @@ void GPULayer::setValue(ghoul::opengl::ProgramObject* programObject, const Layer
const TileIndex& tileIndex, int pileSize)
{
ChunkTilePile chunkTilePile = layer.getChunkTilePile(tileIndex, pileSize);
- gpuChunkTilePile.setValue(programObject, chunkTilePile);
gpuRenderSettings.setValue(programObject, layer.renderSettings());
+ gpuLayerAdjustment.setValue(programObject, layer.layerAdjustment());
+
+ switch (layer.type()) {
+ // Intentional fall through. Same for all tile layers
+ case layergroupid::TypeID::DefaultTileLayer:
+ case layergroupid::TypeID::SingleImageTileLayer:
+ case layergroupid::TypeID::SizeReferenceTileLayer:
+ case layergroupid::TypeID::TemporalTileLayer:
+ case layergroupid::TypeID::TileIndexTileLayer:
+ case layergroupid::TypeID::ByIndexTileLayer:
+ case layergroupid::TypeID::ByLevelTileLayer:
+ gpuChunkTilePile.setValue(programObject, chunkTilePile);
+ break;
+ case layergroupid::TypeID::SolidColor:
+ gpuColor.setValue(programObject, layer.otherTypesProperties().color.value());
+ break;
+ default:
+ break;
+ }
}
void GPULayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer,
const std::string& nameBase, int pileSize)
{
- gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize);
gpuRenderSettings.bind(layer.renderSettings(), programObject, nameBase + "settings.");
+ gpuLayerAdjustment.bind(layer.layerAdjustment(), programObject, nameBase + "adjustment.");
+
+ switch (layer.type()) {
+ // Intentional fall through. Same for all tile layers
+ case layergroupid::TypeID::DefaultTileLayer:
+ case layergroupid::TypeID::SingleImageTileLayer:
+ case layergroupid::TypeID::SizeReferenceTileLayer:
+ case layergroupid::TypeID::TemporalTileLayer:
+ case layergroupid::TypeID::TileIndexTileLayer:
+ case layergroupid::TypeID::ByIndexTileLayer:
+ case layergroupid::TypeID::ByLevelTileLayer:
+ gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize);
+ break;
+ case layergroupid::TypeID::SolidColor:
+ gpuColor.bind(programObject, nameBase + "color");
+ break;
+ default:
+ break;
+ }
}
void GPULayer::deactivate() {
diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.h b/modules/globebrowsing/rendering/gpu/gpulayer.h
index 3cc2e881c9..746c581b25 100644
--- a/modules/globebrowsing/rendering/gpu/gpulayer.h
+++ b/modules/globebrowsing/rendering/gpu/gpulayer.h
@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER___H__
#include
+#include
#include
#include
#include
@@ -73,6 +74,10 @@ public:
private:
GPUChunkTilePile gpuChunkTilePile;
GPULayerRenderSettings gpuRenderSettings;
+ GPULayerAdjustment gpuLayerAdjustment;
+
+ // Adjustment layer stuff
+ GPUData gpuColor;
};
} // namespace globebrowsing
diff --git a/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp
new file mode 100644
index 0000000000..69ff1707bb
--- /dev/null
+++ b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.cpp
@@ -0,0 +1,64 @@
+/*****************************************************************************************
+ * *
+ * OpenSpace *
+ * *
+ * Copyright (c) 2014-2017 *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this *
+ * software and associated documentation files (the "Software"), to deal in the Software *
+ * without restriction, including without limitation the rights to use, copy, modify, *
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
+ * permit persons to whom the Software is furnished to do so, subject to the following *
+ * conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included in all copies *
+ * or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ ****************************************************************************************/
+
+#include
+#include
+
+namespace openspace {
+namespace globebrowsing {
+
+void GPULayerAdjustment::setValue(ghoul::opengl::ProgramObject* programObject,
+ const LayerAdjustment& layerAdjustment)
+{
+ switch (layerAdjustment.type()) {
+ case layergroupid::AdjustmentTypeID::None:
+ break;
+ case layergroupid::AdjustmentTypeID::ChromaKey: {
+ gpuChromaKeyColor.setValue(programObject, layerAdjustment.chromaKeyColor.value());
+ gpuChromaKeyTolerance.setValue(programObject, layerAdjustment.chromaKeyTolerance.value());
+ break;
+ }
+ case layergroupid::AdjustmentTypeID::TransferFunction:
+ break;
+ }
+}
+
+void GPULayerAdjustment::bind(const LayerAdjustment& layerAdjustment, ghoul::opengl::ProgramObject* programObject,
+ const std::string& nameBase)
+{
+ switch (layerAdjustment.type()) {
+ case layergroupid::AdjustmentTypeID::None:
+ break;
+ case layergroupid::AdjustmentTypeID::ChromaKey: {
+ gpuChromaKeyColor.bind(programObject, nameBase + "chromaKeyColor");
+ gpuChromaKeyTolerance.bind(programObject, nameBase + "chromaKeyTolerance");
+ break;
+ }
+ case layergroupid::AdjustmentTypeID::TransferFunction:
+ break;
+ }
+}
+
+} // namespace globebrowsing
+} // namespace openspace
diff --git a/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h
new file mode 100644
index 0000000000..3a53b8808f
--- /dev/null
+++ b/modules/globebrowsing/rendering/gpu/gpulayeradjustment.h
@@ -0,0 +1,56 @@
+/*****************************************************************************************
+ * *
+ * OpenSpace *
+ * *
+ * Copyright (c) 2014-2017 *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this *
+ * software and associated documentation files (the "Software"), to deal in the Software *
+ * without restriction, including without limitation the rights to use, copy, modify, *
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
+ * permit persons to whom the Software is furnished to do so, subject to the following *
+ * conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included in all copies *
+ * or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ ****************************************************************************************/
+
+#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__
+#define __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__
+
+#include
+
+namespace ghoul { namespace opengl {
+class ProgramObject;
+}}
+
+namespace openspace {
+namespace globebrowsing {
+
+struct LayerAdjustment;
+
+class GPULayerAdjustment{
+public:
+ void setValue(ghoul::opengl::ProgramObject* programObject,
+ const LayerAdjustment& layerAdjustment);
+
+ void bind(const LayerAdjustment& layerAdjustment,
+ ghoul::opengl::ProgramObject* programObject,
+ const std::string& nameBase);
+
+private:
+ GPUData gpuChromaKeyColor;
+ GPUData gpuChromaKeyTolerance;
+};
+
+} // namespace globebrowsing
+} // namespace openspace
+
+#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GPULAYER_ADJUSMENT___H__
diff --git a/modules/globebrowsing/rendering/layer/layer.cpp b/modules/globebrowsing/rendering/layer/layer.cpp
index 5f50476aab..d4f482ba8c 100644
--- a/modules/globebrowsing/rendering/layer/layer.cpp
+++ b/modules/globebrowsing/rendering/layer/layer.cpp
@@ -30,60 +30,296 @@ namespace openspace {
namespace globebrowsing {
namespace {
+ const char* _loggerCat = "Layer";
+
const char* keyName = "Name";
const char* keyEnabled = "Enabled";
const char* keyLayerGroupID = "LayerGroupID";
const char* keySettings = "Settings";
+ const char* keyAdjustment = "Adjustment";
+ const char* KeyBlendMode = "BlendMode";
}
-Layer::Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict)
+Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict)
: properties::PropertyOwner(layerDict.value(keyName))
+ , _typeOption(
+ "type",
+ "Type",
+ properties::OptionProperty::DisplayType::Dropdown
+ )
+ , _blendModeOption(
+ "blendMode",
+ "Blend Mode",
+ properties::OptionProperty::DisplayType::Dropdown
+ )
, _enabled(properties::BoolProperty("enabled", "Enabled", false))
, _reset("reset", "Reset")
-{
- // We add the id to the dictionary since it needs to be known by
- // the tile provider
- ghoul::Dictionary newLayerDict = layerDict;
- newLayerDict.setValue(keyLayerGroupID, id);
-
- _tileProvider = std::shared_ptr(
- tileprovider::TileProvider::createFromDictionary(newLayerDict));
-
- // Something else went wrong and no exception was thrown
- if (_tileProvider == nullptr) {
- throw ghoul::RuntimeError("Unable to create TileProvider '" + name() + "'");
+ , _tileProvider(nullptr)
+ , _otherTypesProperties{
+ properties::Vec3Property (
+ "color",
+ "Color",
+ glm::vec4(1.f, 1.f, 1.f, 1.f),
+ glm::vec4(0.f),
+ glm::vec4(1.f))
}
+ , _layerGroupId(id)
+{
+ layergroupid::TypeID typeID = parseTypeIdFromDictionary(layerDict);
+ if (typeID == layergroupid::TypeID::Unknown) {
+ throw ghoul::RuntimeError("Unknown layer type!");
+ }
+
+ initializeBasedOnType(typeID, layerDict);
bool enabled = false; // defaults to false if unspecified
layerDict.getValue(keyEnabled, enabled);
_enabled.setValue(enabled);
+ // Initialize settings
ghoul::Dictionary settingsDict;
if (layerDict.getValue(keySettings, settingsDict)) {
_renderSettings.setValuesFromDictionary(settingsDict);
}
- if (id == layergroupid::ID::GrayScaleColorOverlays) {
- _renderSettings.addProperty(_renderSettings.valueBlending);
- _renderSettings.useValueBlending = true;
+
+ // Initiallize layer adjustment
+ ghoul::Dictionary adjustmentDict;
+ if (layerDict.getValue(keyAdjustment, adjustmentDict)) {
+ _layerAdjustment.setValuesFromDictionary(adjustmentDict);
}
- _reset.onChange([&](){
- _tileProvider->reset();
+ // Add options to option properties
+ for (int i = 0; i < layergroupid::NUM_LAYER_TYPES; ++i) {
+ _typeOption.addOption(i, layergroupid::LAYER_TYPE_NAMES[i]);
+ }
+ _typeOption.setValue(static_cast(typeID));
+ _type = static_cast(_typeOption.value());
+
+ for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) {
+ _blendModeOption.addOption(i, layergroupid::BLEND_MODE_NAMES[i]);
+ }
+
+ // Initialize blend mode
+ std::string blendModeName;
+ if (layerDict.getValue(KeyBlendMode, blendModeName)) {
+ layergroupid::BlendModeID blendModeID =
+ layergroupid::getBlendModeIDFromName(blendModeName);
+ _blendModeOption.setValue(static_cast(blendModeID));
+ }
+ else {
+ _blendModeOption.setValue(static_cast(layergroupid::BlendModeID::Normal));
+ }
+
+ // On change callbacks definitions
+ _enabled.onChange([&](){
+ if (_onChangeCallback) {
+ _onChangeCallback();
+ }
});
+ _reset.onChange([&](){
+ if (_tileProvider) {
+ _tileProvider->reset();
+ }
+ });
+
+ _typeOption.onChange([&](){
+ removeVisibleProperties();
+ _type = static_cast(_typeOption.value());
+ ghoul::Dictionary dict;
+ initializeBasedOnType(type(), dict);
+ addVisibleProperties();
+ if (_onChangeCallback) {
+ _onChangeCallback();
+ }
+ });
+
+ _blendModeOption.onChange([&](){
+ if (_onChangeCallback) {
+ _onChangeCallback();
+ }
+ });
+
+ _layerAdjustment.onChange([&](){
+ if (_onChangeCallback) {
+ _onChangeCallback();
+ }
+ });
+
+ _typeOption.setReadOnly(true);
+
+ // Add the properties
+ addProperty(_typeOption);
+ addProperty(_blendModeOption);
addProperty(_enabled);
addProperty(_reset);
+ _otherTypesProperties.color.setViewOption(properties::Property::ViewOptions::Color);
+
+ addVisibleProperties();
+
addPropertySubOwner(_renderSettings);
- addPropertySubOwner(*_tileProvider);
+ addPropertySubOwner(_layerAdjustment);
}
ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const {
- return _tileProvider->getChunkTilePile(tileIndex, pileSize);
+ if (_tileProvider) {
+ return _tileProvider->getChunkTilePile(tileIndex, pileSize);
+ }
+ else {
+ ChunkTilePile chunkTilePile;
+ chunkTilePile.resize(pileSize);
+ for (int i = 0; i < pileSize; ++i) {
+ chunkTilePile[i].tile = Tile::TileUnavailable;
+ chunkTilePile[i].uvTransform.uvOffset = { 0, 0 };
+ chunkTilePile[i].uvTransform.uvScale = { 1, 1 };
+ }
+ return chunkTilePile;
+ }
+}
+
+Tile::Status Layer::getTileStatus(const TileIndex& index) const {
+ if (_tileProvider) {
+ return _tileProvider->getTileStatus(index);
+ }
+ else {
+ return Tile::Status::Unavailable;
+ }
+}
+
+layergroupid::TypeID Layer::type() const {
+ return _type;
+};
+
+layergroupid::BlendModeID Layer::blendMode() const {
+ return static_cast(_blendModeOption.value());
+};
+
+
+TileDepthTransform Layer::depthTransform() const {
+ if (_tileProvider) {
+ return _tileProvider->depthTransform();
+ }
+ else {
+ return {1.0f, 0.0f};
+ }
+}
+
+bool Layer::enabled() const {
+ return _enabled.value();
+}
+
+tileprovider::TileProvider* Layer::tileProvider() const {
+ return _tileProvider.get();
+}
+
+const Layer::OtherTypesProperties& Layer::otherTypesProperties() const {
+ return _otherTypesProperties;
+}
+
+const LayerRenderSettings& Layer::renderSettings() const {
+ return _renderSettings;
+}
+
+const LayerAdjustment& Layer::layerAdjustment() const {
+ return _layerAdjustment;
}
void Layer::onChange(std::function callback) {
- _enabled.onChange(callback);
+ _onChangeCallback = callback;
+}
+
+void Layer::update() {
+ if (_tileProvider) {
+ _tileProvider->update();
+ }
+}
+
+layergroupid::TypeID Layer::parseTypeIdFromDictionary(
+ const ghoul::Dictionary& initDict) const
+{
+ if (initDict.hasKeyAndValue("Type")) {
+ const std::string typeString = initDict.value("Type");
+ return layergroupid::getTypeIDFromTypeString(typeString);
+ }
+ else {
+ return layergroupid::TypeID::DefaultTileLayer;
+ }
+}
+
+void Layer::initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict) {
+ switch (typeId) {
+ // Intentional fall through. Same for all tile layers
+ case layergroupid::TypeID::DefaultTileLayer:
+ case layergroupid::TypeID::SingleImageTileLayer:
+ case layergroupid::TypeID::SizeReferenceTileLayer:
+ case layergroupid::TypeID::TemporalTileLayer:
+ case layergroupid::TypeID::TileIndexTileLayer:
+ case layergroupid::TypeID::ByIndexTileLayer:
+ case layergroupid::TypeID::ByLevelTileLayer: {
+ // We add the id to the dictionary since it needs to be known by
+ // the tile provider
+ ghoul::Dictionary tileProviderInitDict = initDict;
+ tileProviderInitDict.setValue(keyLayerGroupID, _layerGroupId);
+ if (tileProviderInitDict.hasKeyAndValue(keyName)) {
+ std::string name;
+ tileProviderInitDict.getValue(keyName, name);
+ LDEBUG("Initializing tile provider for layer: '" + name + "'");
+ }
+ _tileProvider = std::shared_ptr(
+ tileprovider::TileProvider::createFromDictionary(typeId, tileProviderInitDict)
+ );
+ break;
+ }
+ case layergroupid::TypeID::SolidColor:
+ break;
+ default:
+ throw ghoul::RuntimeError("Unable to create layer. Unknown type.");
+ break;
+ }
+}
+
+void Layer::addVisibleProperties() {
+ switch (type()) {
+ // Intentional fall through. Same for all tile layers
+ case layergroupid::TypeID::DefaultTileLayer:
+ case layergroupid::TypeID::SingleImageTileLayer:
+ case layergroupid::TypeID::SizeReferenceTileLayer:
+ case layergroupid::TypeID::TemporalTileLayer:
+ case layergroupid::TypeID::TileIndexTileLayer:
+ case layergroupid::TypeID::ByIndexTileLayer:
+ case layergroupid::TypeID::ByLevelTileLayer:
+ if (_tileProvider) {
+ addPropertySubOwner(*_tileProvider);
+ }
+ break;
+ case layergroupid::TypeID::SolidColor:
+ addProperty(_otherTypesProperties.color);
+ default:
+ break;
+ }
+}
+
+void Layer::removeVisibleProperties() {
+ switch (type()) {
+ // Intentional fall through. Same for all tile layers
+ case layergroupid::TypeID::DefaultTileLayer:
+ case layergroupid::TypeID::SingleImageTileLayer:
+ case layergroupid::TypeID::SizeReferenceTileLayer:
+ case layergroupid::TypeID::TemporalTileLayer:
+ case layergroupid::TypeID::TileIndexTileLayer:
+ case layergroupid::TypeID::ByIndexTileLayer:
+ case layergroupid::TypeID::ByLevelTileLayer:
+ if (_tileProvider) {
+ removePropertySubOwner(*_tileProvider);
+ }
+ break;
+ case layergroupid::TypeID::SolidColor:
+ removeProperty(_otherTypesProperties.color);
+ break;
+ default:
+ break;
+ }
}
} // namespace globebrowsing
diff --git a/modules/globebrowsing/rendering/layer/layer.h b/modules/globebrowsing/rendering/layer/layer.h
index 437eae8ef2..c8380e5b4f 100644
--- a/modules/globebrowsing/rendering/layer/layer.h
+++ b/modules/globebrowsing/rendering/layer/layer.h
@@ -25,14 +25,17 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER___H__
-#include
-
#include
+
+#include
#include
#include
+#include
+#include
#include
#include
+#include
namespace openspace {
namespace globebrowsing {
@@ -41,29 +44,55 @@ namespace tileprovider {
class TileProvider;
}
-/**
- * Simple struct which is used to enable/disable TileProvider
- * and associate is with a name. It also holds layer specific information
- * which is used in rendering of layer.
- */
class Layer : public properties::PropertyOwner {
public:
- Layer(layergroupid::ID id, const ghoul::Dictionary& layerDict);
+ /**
+ * Properties used when the layer type is not a tile type layer. These properties
+ * can be added or removed depending on the layer type.
+ */
+ struct OtherTypesProperties {
+ properties::Vec3Property color;
+ };
+
+ Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict);
ChunkTilePile getChunkTilePile(const TileIndex& tileIndex, int pileSize) const;
+ Tile::Status getTileStatus(const TileIndex& index) const;
- bool enabled() const { return _enabled.value(); }
- tileprovider::TileProvider* tileProvider() const { return _tileProvider.get(); }
- const LayerRenderSettings& renderSettings() const { return _renderSettings; }
-
+ layergroupid::TypeID type() const;
+ layergroupid::BlendModeID blendMode() const;
+ TileDepthTransform depthTransform() const;
+ bool enabled() const;
+ tileprovider::TileProvider* tileProvider() const;
+ const OtherTypesProperties& otherTypesProperties() const;
+ const LayerRenderSettings& renderSettings() const;
+ const LayerAdjustment& layerAdjustment() const;
+
void onChange(std::function callback);
+
+ void update();
private:
+ layergroupid::TypeID parseTypeIdFromDictionary(const ghoul::Dictionary& initDict) const;
+ void initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict);
+ void addVisibleProperties();
+ void removeVisibleProperties();
+
+ properties::OptionProperty _typeOption;
+ properties::OptionProperty _blendModeOption;
properties::BoolProperty _enabled;
properties::TriggerProperty _reset;
+
+ layergroupid::TypeID _type;
std::shared_ptr _tileProvider;
+ OtherTypesProperties _otherTypesProperties;
LayerRenderSettings _renderSettings;
-};
+ LayerAdjustment _layerAdjustment;
+
+ const layergroupid::GroupID _layerGroupId;
+
+ std::function _onChangeCallback;
+ };
} // namespace globebrowsing
} // namespace openspace
diff --git a/modules/globebrowsing/rendering/layer/layeradjustment.cpp b/modules/globebrowsing/rendering/layer/layeradjustment.cpp
new file mode 100644
index 0000000000..80b038612b
--- /dev/null
+++ b/modules/globebrowsing/rendering/layer/layeradjustment.cpp
@@ -0,0 +1,134 @@
+/*****************************************************************************************
+ * *
+ * OpenSpace *
+ * *
+ * Copyright (c) 2014-2017 *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this *
+ * software and associated documentation files (the "Software"), to deal in the Software *
+ * without restriction, including without limitation the rights to use, copy, modify, *
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
+ * permit persons to whom the Software is furnished to do so, subject to the following *
+ * conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included in all copies *
+ * or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ ****************************************************************************************/
+
+#include
+
+namespace openspace {
+namespace globebrowsing {
+
+namespace {
+ const char* keyType = "Type";
+ const char* keyChromaKeyColor = "ChromaKeyColor";
+ const char* keyChromaKeyTolerance = "ChromaKeyTolerance";
+}
+
+LayerAdjustment::LayerAdjustment()
+ : properties::PropertyOwner("adjustment")
+ , _typeOption(
+ "type",
+ "Type",
+ properties::OptionProperty::DisplayType::Dropdown
+ )
+ , chromaKeyColor(
+ "chromaKeyColor",
+ "Chroma key color",
+ glm::vec3(0.f, 0.f, 0.f),
+ glm::vec3(0.f),
+ glm::vec3(1.f)
+ )
+ , chromaKeyTolerance(
+ "chromaKeyTolerance",
+ "Chroma key tolerance",
+ 0,
+ 0,
+ 1
+ )
+ , _onChangeCallback([](){})
+{
+ // Add options to option properties
+ for (int i = 0; i < layergroupid::NUM_ADJUSTMENT_TYPES; ++i) {
+ _typeOption.addOption(i, layergroupid::ADJUSTMENT_TYPE_NAMES[i]);
+ }
+ _typeOption.setValue(static_cast(layergroupid::AdjustmentTypeID::None));
+ _type = static_cast(_typeOption.value());
+
+ _typeOption.onChange([&](){
+ removeVisibleProperties();
+ _type = static_cast(_typeOption.value());
+ addVisibleProperties();
+ _onChangeCallback();
+ });
+ chromaKeyColor.setViewOption(properties::Property::ViewOptions::Color);
+
+ addProperty(_typeOption);
+ addVisibleProperties();
+}
+
+void LayerAdjustment::setValuesFromDictionary(
+ const ghoul::Dictionary& adjustmentDict)
+{
+ std::string dictType;
+ glm::vec3 dictChromaKeyColor;
+ float dictChromaKeyTolerance;
+
+ if (adjustmentDict.getValue(keyType, dictType)) {
+ _typeOption.setValue(
+ static_cast(layergroupid::getAdjustmentTypeIDFromName(dictType)));
+ }
+ if (adjustmentDict.getValue(keyChromaKeyColor, dictChromaKeyColor)) {
+ chromaKeyColor.setValue(dictChromaKeyColor);
+ }
+ if (adjustmentDict.getValue(keyChromaKeyTolerance, dictChromaKeyTolerance)) {
+ chromaKeyTolerance.setValue(dictChromaKeyTolerance);
+ }
+}
+
+layergroupid::AdjustmentTypeID LayerAdjustment::type() const {
+ return _type;
+}
+
+void LayerAdjustment::addVisibleProperties() {
+ switch (type()) {
+ case layergroupid::AdjustmentTypeID::None:
+ break;
+ case layergroupid::AdjustmentTypeID::ChromaKey: {
+ addProperty(chromaKeyColor);
+ addProperty(chromaKeyTolerance);
+ break;
+ }
+ case layergroupid::AdjustmentTypeID::TransferFunction:
+ break;
+ }
+}
+
+void LayerAdjustment::removeVisibleProperties() {
+ switch (type()) {
+ case layergroupid::AdjustmentTypeID::None:
+ break;
+ case layergroupid::AdjustmentTypeID::ChromaKey: {
+ removeProperty(chromaKeyColor);
+ removeProperty(chromaKeyTolerance);
+ break;
+ }
+ case layergroupid::AdjustmentTypeID::TransferFunction:
+ break;
+ }
+}
+
+void LayerAdjustment::onChange(std::function callback) {
+ _onChangeCallback = std::move(callback);
+}
+
+} // namespace globebrowsing
+} // namespace openspace
diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h b/modules/globebrowsing/rendering/layer/layeradjustment.h
similarity index 64%
rename from modules/globebrowsing/tile/tileprovider/presentationslideprovider.h
rename to modules/globebrowsing/rendering/layer/layeradjustment.h
index 4b331777a1..20b9f11a78 100644
--- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h
+++ b/modules/globebrowsing/rendering/layer/layeradjustment.h
@@ -22,48 +22,51 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
-#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__
-#define __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__
+#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__
+#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__
-#include
-#include
+#include
-#include
-#include
+#include
#include
-
-#include
-#include
+#include
+#include
namespace openspace {
namespace globebrowsing {
+
namespace tileprovider {
+ class TileProvider;
+}
-class PresentationSlideProvider : public TileProvider {
+class LayerAdjustment : public properties::PropertyOwner
+{
public:
- PresentationSlideProvider(const ghoul::Dictionary& dictionary);
- PresentationSlideProvider(const std::string& imagePath);
- virtual ~PresentationSlideProvider() = default;
+ LayerAdjustment();
+ ~LayerAdjustment() = default;
- virtual Tile getTile(const TileIndex& tileIndex) override;
- virtual Tile::Status getTileStatus(const TileIndex& index) override;
- virtual TileDepthTransform depthTransform() override;
- virtual void update() override;
- virtual void reset() override;
- virtual int maxLevel() override;
+ void setValuesFromDictionary(const ghoul::Dictionary& adjustmentDict);
+
+ layergroupid::AdjustmentTypeID type() const;
+
+ // Properties
+ properties::Vec3Property chromaKeyColor;
+ properties::FloatProperty chromaKeyTolerance;
+
+ void onChange(std::function callback);
private:
- TileProvider* slideProvider();
+ void addVisibleProperties();
+ void removeVisibleProperties();
+
+ properties::OptionProperty _typeOption;
+ layergroupid::AdjustmentTypeID _type;
- TileIndex _tileIndex;
- properties::IntProperty _slideIndex;
- std::vector> _slideProviders;
- std::unique_ptr _defaultProvider;
+ std::function _onChangeCallback;
};
-} // namespace tileprovider
} // namespace globebrowsing
} // namespace openspace
-#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__
+#endif // __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_ADJUSTMENT___H__
diff --git a/modules/globebrowsing/rendering/layer/layergroup.cpp b/modules/globebrowsing/rendering/layer/layergroup.cpp
index 94f5d8cf5d..7b038c8f58 100644
--- a/modules/globebrowsing/rendering/layer/layergroup.cpp
+++ b/modules/globebrowsing/rendering/layer/layergroup.cpp
@@ -26,35 +26,36 @@
#include
+namespace {
+ const char* _loggerCat = "LayerGroup";
+}
+
namespace openspace {
namespace globebrowsing {
-LayerGroup::LayerGroup(std::string name)
- : properties::PropertyOwner(std::move(name))
+LayerGroup::LayerGroup(layergroupid::GroupID id)
+ : properties::PropertyOwner(std::move(layergroupid::LAYER_GROUP_NAMES[id]))
+ , _groupId(id)
, _levelBlendingEnabled("blendTileLevels", "blend tile levels", false)
{
addProperty(_levelBlendingEnabled);
}
-LayerGroup::LayerGroup(layergroupid::ID id, const ghoul::Dictionary& dict)
- : LayerGroup(layergroupid::LAYER_GROUP_NAMES[id])
+LayerGroup::LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict)
+ : LayerGroup(id)
{
for (size_t i = 0; i < dict.size(); i++) {
std::string dictKey = std::to_string(i + 1);
ghoul::Dictionary layerDict = dict.value(dictKey);
try {
- _layers.push_back(std::make_shared(id, layerDict));
+ addLayer(layerDict);
}
catch (const ghoul::RuntimeError& e) {
LERRORC(e.component, e.message);
continue;
}
}
-
- for (const auto& layer : _layers) {
- addPropertySubOwner(layer.get());
- }
}
void LayerGroup::update() {
@@ -62,12 +63,48 @@ void LayerGroup::update() {
for (const auto& layer : _layers) {
if (layer->enabled()) {
- layer->tileProvider()->update();
+ layer->update();
_activeLayers.push_back(layer);
}
}
}
+void LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {
+ if (!layerDict.hasKeyAndValue("Name")) {
+ LERROR("'Name' must be specified for layer.");
+ return;
+ }
+ auto layer = std::make_shared(_groupId, layerDict);
+ layer->onChange(_onChangeCallback);
+ if (hasPropertySubOwner(layer->name())) {
+ LINFO("Layer with name " + layer->name() + " already exists.");
+ }
+ else {
+ _layers.push_back(layer);
+ update();
+ if(_onChangeCallback) {
+ _onChangeCallback();
+ }
+ addPropertySubOwner(layer.get());
+ }
+}
+
+void LayerGroup::deleteLayer(const std::string& layerName) {
+ for (std::vector>::iterator it = _layers.begin(); it != _layers.end(); ++it) {
+ if (it->get()->name() == layerName) {
+ removePropertySubOwner(it->get());
+ _layers.erase(it);
+ update();
+ if(_onChangeCallback) {
+ _onChangeCallback();
+ }
+ LINFO("Deleted layer " + layerName);
+ return;
+ }
+ }
+ LERROR("Could not find layer " + layerName);
+}
+
const std::vector>& LayerGroup::layers() const {
return _layers;
}
@@ -81,10 +118,10 @@ int LayerGroup::pileSize() const{
}
void LayerGroup::onChange(std::function callback) {
- _onChangeCallback = callback;
- _levelBlendingEnabled.onChange(callback);
+ _onChangeCallback = std::move(callback);
+ _levelBlendingEnabled.onChange(_onChangeCallback);
for (const std::shared_ptr& layer : _layers) {
- layer->onChange(callback);
+ layer->onChange(_onChangeCallback);
}
}
diff --git a/modules/globebrowsing/rendering/layer/layergroup.h b/modules/globebrowsing/rendering/layer/layergroup.h
index d19e9b76d6..8cf6d22d9b 100644
--- a/modules/globebrowsing/rendering/layer/layergroup.h
+++ b/modules/globebrowsing/rendering/layer/layergroup.h
@@ -47,12 +47,15 @@ namespace tileprovider {
* Convenience class for dealing with multiple Layers.
*/
struct LayerGroup : public properties::PropertyOwner {
- LayerGroup(std::string name);
- LayerGroup(layergroupid::ID id, const ghoul::Dictionary& dict);
+ LayerGroup(layergroupid::GroupID id);
+ LayerGroup(layergroupid::GroupID id, const ghoul::Dictionary& dict);
/// Updates all layers tile providers within this group
void update();
+ void addLayer(const ghoul::Dictionary& layerDict);
+ void deleteLayer(const std::string& layerName);
+
/// @returns const vector of all layers
const std::vector>& layers() const;
@@ -67,6 +70,7 @@ struct LayerGroup : public properties::PropertyOwner {
void onChange(std::function callback);
private:
+ const layergroupid::GroupID _groupId;
std::vector> _layers;
std::vector> _activeLayers;
diff --git a/modules/globebrowsing/rendering/layer/layergroupid.h b/modules/globebrowsing/rendering/layer/layergroupid.h
index 07b58ca247..8445c4b962 100644
--- a/modules/globebrowsing/rendering/layer/layergroupid.h
+++ b/modules/globebrowsing/rendering/layer/layergroupid.h
@@ -25,32 +25,133 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYERGROUPID___H__
+#include
namespace openspace {
namespace globebrowsing {
namespace layergroupid {
-static const int NUM_LAYER_GROUPS = 7;
-static const char* LAYER_GROUP_NAMES[NUM_LAYER_GROUPS] = {
+static const int NUM_LAYER_GROUPS = 5;
+static const std::string LAYER_GROUP_NAMES[NUM_LAYER_GROUPS] = {
"HeightLayers",
"ColorLayers",
- "ColorOverlays",
- "GrayScaleLayers",
- "GrayScaleColorOverlays",
+ "Overlays",
"NightLayers",
"WaterMasks"
};
-enum ID {
+enum GroupID {
HeightLayers,
ColorLayers,
- ColorOverlays,
- GrayScaleLayers,
- GrayScaleColorOverlays,
+ Overlays,
NightLayers,
- WaterMasks
+ WaterMasks,
+ Unknown,
};
+static const int NUM_LAYER_TYPES = 8;
+static const std::string LAYER_TYPE_NAMES[NUM_LAYER_TYPES] = {
+ "DefaultTileLayer",
+ "SingleImageTileLayer",
+ "SizeReferenceTileLayer",
+ "TemporalTileLayer",
+ "TileIndexTileLayer",
+ "ByIndexTileLayer",
+ "ByLevelTileLayer",
+ "SolidColor",
+};
+
+/**
+ This enumeration is specified explicitly since it is used in the shader as well.
+ */
+enum class TypeID {
+ Unknown = -1,
+ DefaultTileLayer = 0,
+ SingleImageTileLayer = 1,
+ SizeReferenceTileLayer = 2,
+ TemporalTileLayer = 3,
+ TileIndexTileLayer = 4,
+ ByIndexTileLayer = 5,
+ ByLevelTileLayer = 6,
+ SolidColor = 7,
+};
+
+static const int NUM_ADJUSTMENT_TYPES = 3;
+static const std::string ADJUSTMENT_TYPE_NAMES[NUM_ADJUSTMENT_TYPES] = {
+ "None",
+ "ChromaKey",
+ "TransferFunction",
+};
+
+/**
+ This enumeration is specified explicitly since it is used in the shader as well.
+ */
+enum class AdjustmentTypeID {
+ None = 0,
+ ChromaKey = 1,
+ TransferFunction = 2,
+};
+
+static const int NUM_BLEND_MODES = 5;
+static const std::string BLEND_MODE_NAMES[NUM_BLEND_MODES] = {
+ "Normal",
+ "Multiply",
+ "Add",
+ "Subtract",
+ "Color",
+};
+
+/**
+ This enumeration is specified explicitly since it is used in the shader as well.
+ */
+enum class BlendModeID {
+ Normal = 0,
+ Multiply = 1,
+ Add = 2,
+ Subtract = 3,
+ Color = 4,
+};
+
+static TypeID getTypeIDFromTypeString(std::string typeString) {
+ for (int i = 0; i < NUM_LAYER_TYPES; ++i) {
+ if (typeString == LAYER_TYPE_NAMES[i]) {
+ return static_cast(i);
+ }
+ }
+ return TypeID::Unknown;
+}
+
+static layergroupid::GroupID getGroupIDFromName(std::string layerGroupName) {
+ for (int i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) {
+ if (layerGroupName == layergroupid::LAYER_GROUP_NAMES[i]) {
+ return static_cast(i);
+ }
+ }
+ return GroupID::Unknown;
+}
+
+static layergroupid::AdjustmentTypeID getAdjustmentTypeIDFromName(
+ std::string adjustmentTypeName)
+{
+ for (int i = 0; i < layergroupid::NUM_ADJUSTMENT_TYPES; ++i) {
+ if (adjustmentTypeName == layergroupid::ADJUSTMENT_TYPE_NAMES[i]) {
+ return static_cast(i);
+ }
+ }
+ return AdjustmentTypeID::None;
+}
+
+static layergroupid::BlendModeID getBlendModeIDFromName(
+ std::string blendModeName)
+{
+ for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) {
+ if (blendModeName == layergroupid::BLEND_MODE_NAMES[i]) {
+ return static_cast(i);
+ }
+ }
+ return BlendModeID::Normal;
+}
+
} // namespace layergroupid
} // namespace globebrowsing
} // namespace openspace
diff --git a/modules/globebrowsing/rendering/layer/layermanager.cpp b/modules/globebrowsing/rendering/layer/layermanager.cpp
index df8165bc25..b3f2aabb8a 100644
--- a/modules/globebrowsing/rendering/layer/layermanager.cpp
+++ b/modules/globebrowsing/rendering/layer/layermanager.cpp
@@ -31,23 +31,38 @@
namespace openspace {
namespace globebrowsing {
+namespace {
+ const char* _loggerCat = "LayerManager";
+}
+
LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict)
: properties::PropertyOwner("Layers")
{
- if (layergroupid::NUM_LAYER_GROUPS != layerGroupsDict.size()) {
- throw ghoul::RuntimeError(
- "Number of Layer Groups must be equal to " + layergroupid::NUM_LAYER_GROUPS);
+ // First create empty layer groups in case not all are specified
+ _layerGroups.resize(layergroupid::NUM_LAYER_GROUPS);
+ for (int i = 0; i < _layerGroups.size(); ++i) {
+ ghoul::Dictionary emptyDict;
+ _layerGroups[i] = std::make_shared(
+ static_cast(i), emptyDict
+ );
}
- // Create all the categories of tile providers
- for (size_t i = 0; i < layerGroupsDict.size(); i++) {
- const std::string& groupName = layergroupid::LAYER_GROUP_NAMES[i];
- ghoul::Dictionary layerGroupDict =
- layerGroupsDict.value(groupName);
+ std::vector layerGroupNamesInDict = layerGroupsDict.keys();
- _layerGroups.push_back(
- std::make_shared(
- static_cast(i), layerGroupDict));
+ // Create all the layer groups
+ for (const std::string groupName : layerGroupNamesInDict) {
+
+ layergroupid::GroupID groupId = layergroupid::getGroupIDFromName(groupName);
+
+ if (groupId != layergroupid::GroupID::Unknown) {
+ ghoul::Dictionary layerGroupDict =
+ layerGroupsDict.value(groupName);
+ _layerGroups[static_cast(groupId)] =
+ std::make_shared(groupId, layerGroupDict);
+ }
+ else {
+ LWARNING("Unknown layer group: " + groupName);
+ }
}
for (const std::shared_ptr& layerGroup : _layerGroups) {
@@ -55,11 +70,21 @@ LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict)
}
}
+void LayerManager::addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict) {
+ ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known");
+ _layerGroups[groupId]->addLayer(layerDict);
+}
+
+void LayerManager::deleteLayer(layergroupid::GroupID groupId, std::string layerName) {
+ ghoul_assert(groupId != layergroupid::Unknown, "Layer group ID must be known");
+ _layerGroups[groupId]->deleteLayer(layerName);
+}
+
const LayerGroup& LayerManager::layerGroup(size_t groupId) {
return *_layerGroups[groupId];
}
-const LayerGroup& LayerManager::layerGroup(layergroupid::ID groupId) {
+const LayerGroup& LayerManager::layerGroup(layergroupid::GroupID groupId) {
return *_layerGroups[groupId];
}
@@ -92,45 +117,35 @@ void LayerManager::reset(bool includeDisabled) {
}
}
-TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::ID id,
+TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::GroupID id,
size_t preferredTileSize)
{
switch (id) {
- case layergroupid::ID::HeightLayers: {
+ case layergroupid::GroupID::HeightLayers: {
size_t tileSize = preferredTileSize ? preferredTileSize : 64;
return TileTextureInitData(tileSize, tileSize, GL_FLOAT,
ghoul::opengl::Texture::Format::Red,
TileTextureInitData::ShouldAllocateDataOnCPU::Yes);
}
- case layergroupid::ID::ColorLayers: {
+ case layergroupid::GroupID::ColorLayers: {
size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RGBA);
+ ghoul::opengl::Texture::Format::BGRA);
}
- case layergroupid::ID::ColorOverlays: {
+ case layergroupid::GroupID::Overlays: {
size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RGBA);
+ ghoul::opengl::Texture::Format::BGRA);
}
- case layergroupid::ID::GrayScaleLayers: {
+ case layergroupid::GroupID::NightLayers: {
size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RG);
+ ghoul::opengl::Texture::Format::BGRA);
}
- case layergroupid::ID::GrayScaleColorOverlays: {
+ case layergroupid::GroupID::WaterMasks: {
size_t tileSize = preferredTileSize ? preferredTileSize : 512;
return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RG);
- }
- case layergroupid::ID::NightLayers: {
- size_t tileSize = preferredTileSize ? preferredTileSize : 512;
- return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RGBA);
- }
- case layergroupid::ID::WaterMasks: {
- size_t tileSize = preferredTileSize ? preferredTileSize : 512;
- return TileTextureInitData(tileSize, tileSize, GL_UNSIGNED_BYTE,
- ghoul::opengl::Texture::Format::RGBA);
+ ghoul::opengl::Texture::Format::BGRA);
}
default: {
ghoul_assert(false, "Unknown layer group ID");
@@ -138,10 +153,10 @@ TileTextureInitData LayerManager::getTileTextureInitData(layergroupid::ID id,
}
}
-bool LayerManager::shouldPerformPreProcessingOnLayergroup(layergroupid::ID id) {
+bool LayerManager::shouldPerformPreProcessingOnLayergroup(layergroupid::GroupID id) {
// Only preprocess height layers by default
switch (id) {
- case layergroupid::ID::HeightLayers: return true;
+ case layergroupid::GroupID::HeightLayers: return true;
default: return false;
}
}
diff --git a/modules/globebrowsing/rendering/layer/layermanager.h b/modules/globebrowsing/rendering/layer/layermanager.h
index 22ef5a79a3..454a02d9f8 100644
--- a/modules/globebrowsing/rendering/layer/layermanager.h
+++ b/modules/globebrowsing/rendering/layer/layermanager.h
@@ -28,6 +28,7 @@
#include
#include
+#include
#include
#include
@@ -45,8 +46,11 @@ class LayerManager : public properties::PropertyOwner {
public:
LayerManager(const ghoul::Dictionary& textureCategoriesDictionary);
+ void addLayer(layergroupid::GroupID groupId, ghoul::Dictionary layerDict);
+ void deleteLayer(layergroupid::GroupID groupId, std::string layerName);
+
const LayerGroup& layerGroup(size_t groupId);
- const LayerGroup& layerGroup(layergroupid::ID);
+ const LayerGroup& layerGroup(layergroupid::GroupID);
bool hasAnyBlendingLayersEnabled() const;
@@ -55,10 +59,10 @@ public:
void update();
void reset(bool includingDisabled = false);
- static TileTextureInitData getTileTextureInitData(layergroupid::ID id,
+ static TileTextureInitData getTileTextureInitData(layergroupid::GroupID id,
size_t preferredTileSize = 0);
- static bool shouldPerformPreProcessingOnLayergroup(layergroupid::ID id);
+ static bool shouldPerformPreProcessingOnLayergroup(layergroupid::GroupID id);
void onChange(std::function callback);
private:
diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp
index 6fe1474c58..8cbbd95a79 100644
--- a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp
+++ b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp
@@ -37,11 +37,12 @@ namespace {
LayerRenderSettings::LayerRenderSettings()
: properties::PropertyOwner("Settings")
- , opacity(properties::FloatProperty("Opacity", "opacity", 1.f, 0.f, 1.f))
- , gamma(properties::FloatProperty("Gamma", "gamma", 1, 0, 5))
- , multiplier(properties::FloatProperty("Multiplier", "multiplier", 1.f, 0.f, 20.f))
- , offset(properties::FloatProperty("Offset", "offset", 0.f, -10000.f, 10000.f))
- , valueBlending(properties::FloatProperty("Value blending", "valueBlending",
+ , setDefault("setDefault", "Set Default")
+ , opacity(properties::FloatProperty("opacity", "Opacity", 1.f, 0.f, 1.f))
+ , gamma(properties::FloatProperty("gamma", "Gamma", 1, 0, 5))
+ , multiplier(properties::FloatProperty("multiplier", "Multiplier", 1.f, 0.f, 20.f))
+ , offset(properties::FloatProperty("offset", "Offset", 0.f, -10000.f, 10000.f))
+ , valueBlending(properties::FloatProperty("valueBlending", "Value Blending",
1.f, 0.f, 1.f))
, useValueBlending(false)
{
@@ -50,6 +51,9 @@ LayerRenderSettings::LayerRenderSettings()
addProperty(gamma);
addProperty(multiplier);
addProperty(offset);
+ addProperty(setDefault);
+
+ setDefault.onChange([this](){ setDefaultValues(); });
}
void LayerRenderSettings::setValuesFromDictionary(
@@ -62,19 +66,19 @@ void LayerRenderSettings::setValuesFromDictionary(
float dictValueBlending;
if(renderSettingsDict.getValue(keyOpacity, dictOpacity)) {
- opacity.setValue(dictOpacity);
+ opacity = dictOpacity;
}
if(renderSettingsDict.getValue(keyGamma, dictGamma)) {
- gamma.setValue(dictGamma);
+ gamma = dictGamma;
}
if(renderSettingsDict.getValue(keyMultiplier, dictMultiplier)) {
- multiplier.setValue(dictMultiplier);
+ multiplier = dictMultiplier;
}
if(renderSettingsDict.getValue(keyOffset, dictOffset)) {
- multiplier.setValue(dictOffset);
+ multiplier = dictOffset;
}
if(renderSettingsDict.getValue(keyValueBlending, dictValueBlending)) {
- valueBlending.setValue(dictValueBlending);
+ valueBlending = dictValueBlending;
useValueBlending = true;
}
}
@@ -100,5 +104,13 @@ glm::vec4 LayerRenderSettings::performLayerSettings(glm::vec4 currentValue) cons
return newValue;
}
+void LayerRenderSettings::setDefaultValues() {
+ opacity = 1.f;
+ gamma = 1.f;
+ multiplier = 1.f;
+ offset = 0.f;
+ valueBlending = 1.f;
+}
+
} // namespace globebrowsing
} // namespace openspace
diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.h b/modules/globebrowsing/rendering/layer/layerrendersettings.h
index 2fb4ea2432..95538ee28d 100644
--- a/modules/globebrowsing/rendering/layer/layerrendersettings.h
+++ b/modules/globebrowsing/rendering/layer/layerrendersettings.h
@@ -28,6 +28,7 @@
#include
#include
+#include
namespace openspace {
namespace globebrowsing {
@@ -35,6 +36,8 @@ namespace globebrowsing {
struct LayerRenderSettings : public properties::PropertyOwner {
LayerRenderSettings();
+ properties::TriggerProperty setDefault;
+
properties::FloatProperty opacity;
properties::FloatProperty gamma;
properties::FloatProperty multiplier;
@@ -52,6 +55,9 @@ struct LayerRenderSettings : public properties::PropertyOwner {
/// This function matches the function with the same name in the
/// shader code
glm::vec4 performLayerSettings(glm::vec4 currentValue) const;
+
+private:
+ void setDefaultValues();
};
} // namespace globebrowsing
diff --git a/modules/globebrowsing/rendering/layershadermanager.cpp b/modules/globebrowsing/rendering/layershadermanager.cpp
index 0dc6aceb99..502dbbc150 100644
--- a/modules/globebrowsing/rendering/layershadermanager.cpp
+++ b/modules/globebrowsing/rendering/layershadermanager.cpp
@@ -40,7 +40,10 @@ namespace globebrowsing {
bool LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData::operator==(
const LayerGroupPreprocessingData& other) const {
- return lastLayerIdx == other.lastLayerIdx &&
+ return layerType == other.layerType &&
+ blendMode == other.blendMode &&
+ layerAdjustmentType == other.layerAdjustmentType &&
+ lastLayerIdx == other.lastLayerIdx &&
layerBlendingEnabled == other.layerBlendingEnabled;
}
@@ -72,10 +75,19 @@ LayerShaderManager::LayerShaderPreprocessingData
for (size_t i = 0; i < layergroupid::NUM_LAYER_GROUPS; i++) {
LayerShaderManager::LayerShaderPreprocessingData::LayerGroupPreprocessingData
layeredTextureInfo;
- auto layerGroup = layerManager->layerGroup(i);
+
+ const LayerGroup& layerGroup = layerManager->layerGroup(i);
+ std::vector> layers = layerGroup.activeLayers();
+
layeredTextureInfo.lastLayerIdx = layerGroup.activeLayers().size() - 1;
layeredTextureInfo.layerBlendingEnabled = layerGroup.layerBlendingEnabled();
+ for (const std::shared_ptr& layer : layers) {
+ layeredTextureInfo.layerType.push_back(layer->type());
+ layeredTextureInfo.blendMode.push_back(layer->blendMode());
+ layeredTextureInfo.layerAdjustmentType.push_back(layer->layerAdjustment().type());
+ }
+
preprocessingData.layeredTextureInfo[i] = layeredTextureInfo;
}
@@ -153,8 +165,41 @@ void LayerShaderManager::recompileShaderProgram(
"blend" + groupName,
textureTypes[i].layerBlendingEnabled
);
+
+ // This is to avoid errors from shader preprocessor
+ std::string keyLayerType = groupName + "0" + "LayerType";
+ shaderDictionary.setValue(keyLayerType, 0);
+
+ for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
+ std::string key = groupName + std::to_string(j) + "LayerType";
+ shaderDictionary.setValue(key, static_cast(textureTypes[i].layerType[j]));
+ }
+
+ // This is to avoid errors from shader preprocessor
+ std::string keyBlendMode = groupName + "0" + "BlendMode";
+ shaderDictionary.setValue(keyBlendMode, 0);
+
+ for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
+ std::string key = groupName + std::to_string(j) + "BlendMode";
+ shaderDictionary.setValue(key, static_cast(textureTypes[i].blendMode[j]));
+ }
+
+ // This is to avoid errors from shader preprocessor
+ std::string keyLayerAdjustmentType = groupName + "0" + "LayerAdjustmentType";
+ shaderDictionary.setValue(keyLayerAdjustmentType, 0);
+
+ for (int j = 0; j < textureTypes[i].lastLayerIdx + 1; ++j) {
+ std::string key = groupName + std::to_string(j) + "LayerAdjustmentType";
+ shaderDictionary.setValue(key, static_cast(textureTypes[i].layerAdjustmentType[j]));
+ }
}
+ ghoul::Dictionary layerGroupNames;
+ for (int i = 0; i < layergroupid::NUM_LAYER_GROUPS; ++i) {
+ layerGroupNames.setValue(std::to_string(i), layergroupid::LAYER_GROUP_NAMES[i]);
+ }
+ shaderDictionary.setValue("layerGroups", layerGroupNames);
+
// Other settings such as "useAtmosphere"
auto keyValuePairs = _preprocessingData.keyValuePairs;
for (size_t i = 0; i < keyValuePairs.size(); i++) {
diff --git a/modules/globebrowsing/rendering/layershadermanager.h b/modules/globebrowsing/rendering/layershadermanager.h
index d6712c382b..026e98ecd0 100644
--- a/modules/globebrowsing/rendering/layershadermanager.h
+++ b/modules/globebrowsing/rendering/layershadermanager.h
@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_GLOBEBROWSING___LAYER_SHADER_MANAGER___H__
#include
+#include