[WIP] ColormapEnable not working

Co-authored-by: Victor Lindquist <VLLindqvist@users.noreply.github.com>
This commit is contained in:
Jacob Molin
2022-05-24 17:07:57 -06:00
parent 193c7cdf3e
commit df79184faf
16 changed files with 348 additions and 195 deletions

View File

@@ -30,7 +30,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/network/softwareconnection.h
${CMAKE_CURRENT_SOURCE_DIR}/network/networkengine.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepointscloud.h
${CMAKE_CURRENT_SOURCE_DIR}/simp.h
${CMAKE_CURRENT_SOURCE_DIR}/utils.h
${CMAKE_CURRENT_SOURCE_DIR}/syncablefloatdatastorage.h
${CMAKE_CURRENT_SOURCE_DIR}/interruptibleconcurrentqueue.h
${CMAKE_CURRENT_SOURCE_DIR}/interruptibleconcurrentqueue.inl
@@ -43,7 +43,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/network/softwareconnection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/network/networkengine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepointscloud.cpp
${CMAKE_CURRENT_SOURCE_DIR}/simp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/syncablefloatdatastorage.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -37,6 +37,8 @@ namespace {
namespace openspace {
using namespace softwareintegration;
NetworkEngine::NetworkEngine(const int port)
: _port{port}
{}

View File

@@ -28,7 +28,7 @@
#include <modules/softwareintegration/network/softwareconnection.h>
#include <modules/softwareintegration/pointdatamessagehandler.h>
#include <modules/softwareintegration/interruptibleconcurrentqueue.h>
#include <modules/softwareintegration/simp.h>
#include <modules/softwareintegration/utils.h>
#include <ghoul/io/socket/tcpsocketserver.h>
namespace openspace {
@@ -40,7 +40,7 @@ public:
struct IncomingMessage {
size_t connection_id{1};
SoftwareConnection::Message message{ simp::MessageType::Unknown };
SoftwareConnection::Message message{ softwareintegration::simp::MessageType::Unknown };
};
void start();

View File

@@ -266,11 +266,11 @@ SoftwareConnection::Message SoftwareConnection::receiveMessageFromSoftware() {
}
// Make sure that header matches the protocol version
if (protocolVersionIn != simp::ProtocolVersion) {
if (protocolVersionIn != softwareintegration::simp::ProtocolVersion) {
throw SoftwareConnectionLostError(fmt::format(
"Protocol versions do not match. Remote version: {}, Local version: {}",
protocolVersionIn,
simp::ProtocolVersion
softwareintegration::simp::ProtocolVersion
));
}
@@ -294,10 +294,10 @@ SoftwareConnection::Message SoftwareConnection::receiveMessageFromSoftware() {
// }
// LDEBUG(fmt::format("Message received with header: {}", rawHeader));
auto typeEnum = simp::getMessageType(type);
auto typeEnum = softwareintegration::simp::getMessageType(type);
// Receive the message data
if (typeEnum != simp::MessageType::Disconnection && typeEnum != simp::MessageType::Unknown) {
if (typeEnum != softwareintegration::simp::MessageType::Disconnection && typeEnum != softwareintegration::simp::MessageType::Unknown) {
subjectBuffer.resize(subjectSize);
if (!_socket->get(subjectBuffer.data(), subjectSize)) {
throw SoftwareConnectionLostError("Failed to read message from socket. Disconnecting.");

View File

@@ -26,7 +26,7 @@
#define __OPENSPACE_MODULE_SOFTWAREINTEGRATION___SOFTWARECONNECTION___H__
#include <openspace/network/messagestructures.h>
#include <modules/softwareintegration/simp.h>
#include <modules/softwareintegration/utils.h>
#include <ghoul/io/socket/tcpsocket.h>
#include <openspace/properties/property.h>
@@ -44,7 +44,7 @@ public:
using SubscribedProperties = std::unordered_map<std::string, PropertySubscriptions>;
struct Message {
simp::MessageType type;
softwareintegration::simp::MessageType type;
std::vector<char> content{};
std::string rawMessageType{ "" };
};

View File

@@ -24,7 +24,7 @@
#include <modules/softwareintegration/pointdatamessagehandler.h>
#include <modules/softwareintegration/softwareintegrationmodule.h>
#include <modules/softwareintegration/simp.h>
#include <modules/softwareintegration/utils.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/engine/globals.h>
@@ -45,6 +45,8 @@ namespace {
namespace openspace {
using namespace softwareintegration;
void PointDataMessageHandler::handlePointDataMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
size_t messageOffset = 0;
std::string identifier;
@@ -69,7 +71,7 @@ void PointDataMessageHandler::handlePointDataMessage(const std::vector<char>& me
}
// Use the renderable identifier as the data key
const std::string key = identifier + "-DataPoints";
const auto key = storage::getStorageKey(identifier, storage::Key::DataPoints);
auto module = global::moduleEngine->module<SoftwareIntegrationModule>();
module->storeData(key, std::move(points));
}
@@ -116,7 +118,7 @@ void PointDataMessageHandler::handleFixedColorMessage(const std::vector<char>& m
scripting::ScriptEngine::RemoteScripting::Yes
);
};
addCallback(identifier, callback);
addCallback(identifier, { callback });
}
void PointDataMessageHandler::handleColormapMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -141,22 +143,14 @@ void PointDataMessageHandler::handleColormapMessage(const std::vector<char>& mes
}
// Use the renderable identifier as the data key
const std::string key = identifier + "-Colormap";
const auto key = storage::getStorageKey(identifier, storage::Key::Colormap);
auto module = global::moduleEngine->module<SoftwareIntegrationModule>();
module->storeData(key, std::move(colorMap));
auto callback = [this, identifier, min, max] {
auto colormapLimitsCallback = [this, identifier, min, max] {
// Get renderable
auto r = getRenderable(identifier);
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.ColormapEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
properties::Property* colormapMinProperty = r->property("ColormapMin");
float colormapMin = std::any_cast<float>(colormapMinProperty->get());
if (min != colormapMin) {
@@ -181,7 +175,20 @@ void PointDataMessageHandler::handleColormapMessage(const std::vector<char>& mes
);
}
};
addCallback(identifier, callback);
addCallback(identifier, { colormapLimitsCallback });
auto enableColormapCallback = [this, identifier] {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.ColormapEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
};
// Callback
std::vector<storage::Key> dataToWaitFor{ storage::Key::Colormap, storage::Key::ColormapAttrData };
addCallback(identifier, { enableColormapCallback, dataToWaitFor });
}
void PointDataMessageHandler::handleAttributeDataMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -207,13 +214,12 @@ void PointDataMessageHandler::handleAttributeDataMessage(const std::vector<char>
auto module = global::moduleEngine->module<SoftwareIntegrationModule>();
// Use the renderable identifier as the data key
std::string key = identifier;
std::string key;
storage::Key keyEnum = storage::Key::Unknown;
if (usedFor == "ColormapAttributeData") {
key += "-CmapAttributeData";
}
else if (usedFor == "LinearSizeAttributeData") {
key += "-LinearSizeAttributeData";
if (storage::hasStorageKey(usedFor)) {
key = storage::getStorageKey(identifier, usedFor);
keyEnum = storage::getStorageKeyEnum(usedFor);
}
else {
LERROR(fmt::format(
@@ -223,29 +229,45 @@ void PointDataMessageHandler::handleAttributeDataMessage(const std::vector<char>
return;
}
std::vector<storage::Key> allDataToWaitFor{ keyEnum };
switch (keyEnum) {
case storage::Key::ColormapAttrData : {
allDataToWaitFor.push_back(storage::Key::Colormap);
break;
}
default:
break;
}
module->storeData(key, std::move(attributeData));
auto callback = [this, identifier, usedFor] {
if (usedFor == "ColormapAttributeData") {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.ColormapEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
}
if (usedFor == "LinearSizeAttributeData") {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.ColormapEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
auto callback = [this, identifier, keyEnum] {
switch (keyEnum) {
case storage::Key::ColormapAttrData : {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.ColormapEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
break;
}
case storage::Key::LinearSizeAttrData : {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.LinearSizeEnabled', {});",
identifier, "true"
),
scripting::ScriptEngine::RemoteScripting::Yes
);
break;
}
default:
break;
}
};
addCallback(identifier, callback);
addCallback(identifier, { callback, allDataToWaitFor });
}
void PointDataMessageHandler::handleOpacityMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -284,7 +306,7 @@ void PointDataMessageHandler::handleOpacityMessage(const std::vector<char>& mess
);
}
};
addCallback(identifier, callback);
addCallback(identifier, { callback });
}
void PointDataMessageHandler::handleFixedPointSizeMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -333,7 +355,7 @@ void PointDataMessageHandler::handleFixedPointSizeMessage(const std::vector<char
);
}
};
addCallback(identifier, callback);
addCallback(identifier, { callback });
}
void PointDataMessageHandler::handleLinearPointSizeMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -355,7 +377,7 @@ void PointDataMessageHandler::handleLinearPointSizeMessage(const std::vector<cha
return;
}
auto callback = [this, identifier, size, min, max] {
auto linearSizeCallback = [this, identifier, size, min, max] {
// Get renderable
auto r = getRenderable(identifier);
@@ -398,7 +420,10 @@ void PointDataMessageHandler::handleLinearPointSizeMessage(const std::vector<cha
scripting::ScriptEngine::RemoteScripting::Yes
);
}
};
addCallback(identifier, { linearSizeCallback });
auto enableLinearSizeCallback = [this, identifier] {
openspace::global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.LinearSizeEnabled', {});",
@@ -407,7 +432,13 @@ void PointDataMessageHandler::handleLinearPointSizeMessage(const std::vector<cha
scripting::ScriptEngine::RemoteScripting::Yes
);
};
addCallback(identifier, callback);
addCallback(
identifier,
{
enableLinearSizeCallback,
{ storage::Key::LinearSizeAttrData }
}
);
}
void PointDataMessageHandler::handleVisiblityMessage(const std::vector<char>& message, std::shared_ptr<SoftwareConnection> connection) {
@@ -437,7 +468,7 @@ void PointDataMessageHandler::handleVisiblityMessage(const std::vector<char>& me
scripting::ScriptEngine::RemoteScripting::Yes
);
};
addCallback(identifier, callback);
addCallback(identifier, { callback });
}
void PointDataMessageHandler::handleRemoveSGNMessage(const std::vector<char>& message,std::shared_ptr<SoftwareConnection> connection) {
@@ -488,10 +519,23 @@ void PointDataMessageHandler::postSync() {
auto r = getRenderable(identifier);
if (!r) throw std::exception{};
auto softwareIntegrationModule = global::moduleEngine->module<SoftwareIntegrationModule>();
auto callbacksIt = callbackList.begin();
while (callbacksIt != callbackList.end()) {
auto& callback = *callbacksIt;
auto& [callback, waitForData] = *callbacksIt;
try {
for (auto& waitFor : waitForData) {
if (
softwareIntegrationModule->isSyncDataDirty(
storage::getStorageKey(identifier, waitFor)
)
) {
throw std::exception{};
}
}
callback();
callbacksIt = callbackList.erase(callbacksIt);
}
@@ -568,7 +612,7 @@ void PointDataMessageHandler::checkRenderable(
auto subscriptionCallback = [this, identifier, connection] {
subscribeToRenderableUpdates(identifier, connection);
};
addCallback(identifier, subscriptionCallback);
addCallback(identifier, { subscriptionCallback });
}
else {
subscribeToRenderableUpdates(identifier, connection);
@@ -582,7 +626,7 @@ void PointDataMessageHandler::checkRenderable(
scripting::ScriptEngine::RemoteScripting::Yes
);
};
addCallback(identifier, reanchorCallback);
addCallback(identifier, { reanchorCallback });
}
void PointDataMessageHandler::subscribeToRenderableUpdates(
@@ -683,15 +727,18 @@ void PointDataMessageHandler::subscribeToRenderableUpdates(
}
void PointDataMessageHandler::addCallback(const std::string& identifier, const Callback& newCallback) {
void PointDataMessageHandler::addCallback(
const std::string& identifier,
const Callback& newCallback
) {
std::lock_guard guard(_onceNodeExistsCallbacksMutex);
auto it = _onceNodeExistsCallbacks.find(identifier);
if (it == _onceNodeExistsCallbacks.end()) {
CallbackList callbacks{ std::move(newCallback) };
_onceNodeExistsCallbacks.emplace(std::move(identifier), std::move(callbacks) );
CallbackList newCallbackList{ newCallback };
_onceNodeExistsCallbacks.emplace(identifier, newCallbackList);
}
else {
it->second.push_back(std::move(newCallback));
it->second.push_back(newCallback);
}
}

View File

@@ -36,8 +36,11 @@ namespace openspace {
class Renderable;
class PointDataMessageHandler {
using Callback = std::function<void()>;
using CallbackList = std::vector<std::function<void()>>;
struct Callback {
std::function<void()> function;
std::vector<softwareintegration::storage::Key> waitForData = {};
};
using CallbackList = std::vector<Callback>;
using CallbackMap = std::unordered_map<std::string, CallbackList>;
public:
@@ -62,7 +65,10 @@ private:
void subscribeToRenderableUpdates(const std::string& identifier, std::shared_ptr<SoftwareConnection> connection);
void addCallback(const std::string& identifier, const Callback& newCallback);
void addCallback(
const std::string& identifier,
const Callback& newCallback
);
CallbackMap _onceNodeExistsCallbacks;
std::mutex _onceNodeExistsCallbacksMutex;

View File

@@ -24,6 +24,7 @@
#include <modules/softwareintegration/rendering/renderablepointscloud.h>
#include <modules/softwareintegration/utils.h>
#include <modules/softwareintegration/softwareintegrationmodule.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
@@ -158,6 +159,8 @@ namespace {
namespace openspace {
using namespace softwareintegration;
documentation::Documentation RenderablePointsCloud::Documentation() {
return codegen::doc<Parameters>("softwareintegration_renderable_pointscloud");
}
@@ -461,7 +464,7 @@ void RenderablePointsCloud::update(const UpdateData&) {
if (!_colormapTexture) {
LINFO("Color map not loaded. Has it been sent from external software?");
}
else {
if (colormapAttributeData->empty()) {
LINFO("Color map attribute data not loaded. Has it been sent from external software?");
}
_colormapEnabled = false;
@@ -483,38 +486,37 @@ bool RenderablePointsCloud::checkDataStorage() {
bool updatedDataSlices = false;
auto softwareIntegrationModule = global::moduleEngine->module<SoftwareIntegrationModule>();
std::string dataPointsKey = _identifier.value() + "-DataPoints";
std::string colormapKey = _identifier.value() + "-Colormap";
std::string colormapScalarsKey = _identifier.value() + "-CmapAttributeData";
std::string linearSizeScalarsKey = _identifier.value() + "-LinearSizeAttributeData";
auto dataPointsKey = storage::getStorageKey(_identifier.value(), storage::Key::DataPoints);
auto colormapKey = storage::getStorageKey(_identifier.value(), storage::Key::Colormap);
auto colormapAttrDataKey = storage::getStorageKey(_identifier.value(), storage::Key::ColormapAttrData);
auto linearSizeAttrDataKey = storage::getStorageKey(_identifier.value(), storage::Key::LinearSizeAttrData);
if (softwareIntegrationModule->isDataDirty(dataPointsKey)) {
loadData(dataPointsKey, softwareIntegrationModule);
loadData(softwareIntegrationModule);
updatedDataSlices = true;
}
if (softwareIntegrationModule->isDataDirty(colormapKey)) {
loadColormap(colormapKey, softwareIntegrationModule);
loadColormap(softwareIntegrationModule);
}
if (softwareIntegrationModule->isDataDirty(colormapScalarsKey)) {
loadCmapAttributeData(colormapScalarsKey, softwareIntegrationModule);
if (softwareIntegrationModule->isDataDirty(colormapAttrDataKey)) {
loadCmapAttributeData(softwareIntegrationModule);
updatedDataSlices = true;
}
if (softwareIntegrationModule->isDataDirty(linearSizeScalarsKey)) {
loadLinearSizeAttributeData(linearSizeScalarsKey, softwareIntegrationModule);
if (softwareIntegrationModule->isDataDirty(linearSizeAttrDataKey)) {
loadLinearSizeAttributeData(softwareIntegrationModule);
updatedDataSlices = true;
}
return updatedDataSlices;
}
void RenderablePointsCloud::loadData(
const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule
) {
void RenderablePointsCloud::loadData(SoftwareIntegrationModule* softwareIntegrationModule) {
// Fetch data from module's centralized storage
auto fullPointData = softwareIntegrationModule->fetchData(storageKey);
std::string key = storage::getStorageKey(_identifier.value(), storage::Key::DataPoints);
auto fullPointData = softwareIntegrationModule->fetchData(key);
if (fullPointData.empty()) {
LWARNING("There was an issue trying to fetch the point data from the centralized storage.");
@@ -547,10 +549,9 @@ void RenderablePointsCloud::loadData(
}
}
void RenderablePointsCloud::loadColormap(
const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule
) {
std::vector<float> colorMap = softwareIntegrationModule->fetchData(storageKey);
void RenderablePointsCloud::loadColormap(SoftwareIntegrationModule* softwareIntegrationModule) {
std::string key = storage::getStorageKey(_identifier.value(), storage::Key::Colormap);
auto colorMap = softwareIntegrationModule->fetchData(key);
if (colorMap.empty()) {
LWARNING("There was an issue trying to fetch the colormap data from the centralized storage.");
@@ -576,10 +577,9 @@ void RenderablePointsCloud::loadColormap(
_hasLoadedColormap = true;
}
void RenderablePointsCloud::loadCmapAttributeData(
const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule
) {
auto colormapAttributeData = softwareIntegrationModule->fetchData(storageKey);
void RenderablePointsCloud::loadCmapAttributeData(SoftwareIntegrationModule* softwareIntegrationModule) {
std::string key = storage::getStorageKey(_identifier.value(), storage::Key::ColormapAttrData);
auto colormapAttributeData = softwareIntegrationModule->fetchData(key);
if (colormapAttributeData.empty()) {
LWARNING("There was an issue trying to fetch the colormap data from the centralized storage.");
@@ -606,13 +606,12 @@ void RenderablePointsCloud::loadCmapAttributeData(
}
_hasLoadedColormapAttributeData = true;
LDEBUG("Rerendering colormap attribute data");
LDEBUG("Rerendering colormap attribute data");
}
void RenderablePointsCloud::loadLinearSizeAttributeData(
const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule
) {
auto linearSizeAttributeData = softwareIntegrationModule->fetchData(storageKey);
void RenderablePointsCloud::loadLinearSizeAttributeData(SoftwareIntegrationModule* softwareIntegrationModule) {
std::string key = storage::getStorageKey(_identifier.value(), storage::Key::LinearSizeAttrData);
auto linearSizeAttributeData = softwareIntegrationModule->fetchData(key);
if (linearSizeAttributeData.empty()) {
LWARNING("There was an issue trying to fetch the linear size attribute data from the centralized storage.");

View File

@@ -28,7 +28,6 @@
#include <optional>
#include <openspace/rendering/renderable.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/stringproperty.h>
@@ -64,10 +63,10 @@ public:
static documentation::Documentation Documentation();
protected:
void loadData(const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule);
void loadColormap(const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule);
void loadCmapAttributeData(const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule);
void loadLinearSizeAttributeData(const std::string& storageKey, SoftwareIntegrationModule* softwareIntegrationModule);
void loadData(SoftwareIntegrationModule* softwareIntegrationModule);
void loadColormap(SoftwareIntegrationModule* softwareIntegrationModule);
void loadCmapAttributeData(SoftwareIntegrationModule* softwareIntegrationModule);
void loadLinearSizeAttributeData(SoftwareIntegrationModule* softwareIntegrationModule);
bool checkDataStorage();

View File

@@ -69,6 +69,8 @@ void main() {
dvec4 dpos = modelMatrix * dvec4(dvec3(pos.xyz), 1.0);
float scaleMultiply = 1.0e15 * size;
scaleMultiply *= 15; // TODO: FIX POINT SIZE, NOW IT'S ARBRITRARY
if (linearSizeEnabled) {
float interpolatedSizeAtt = 1.0;

View File

@@ -65,6 +65,10 @@ bool SoftwareIntegrationModule::isDataDirty(const std::string& key) {
return _syncableFloatDataStorage.isDirty(key);
}
bool SoftwareIntegrationModule::isSyncDataDirty(const std::string& key) {
return _syncableFloatDataStorage.isSyncDirty(key);
}
void SoftwareIntegrationModule::internalInitialize(const ghoul::Dictionary&) {
global::syncEngine->addSyncables(getSyncables());
auto fRenderable = FactoryManager::ref().factory<Renderable>();

View File

@@ -43,6 +43,7 @@ public:
void storeData(const std::string& key, const std::vector<float>& data);
const std::vector<float>& fetchData(const std::string& key);
bool isDataDirty(const std::string& key);
bool isSyncDataDirty(const std::string& key);
std::vector<documentation::Documentation> documentations() const override;

View File

@@ -23,6 +23,8 @@
****************************************************************************************/
#include <modules/softwareintegration/syncablefloatdatastorage.h>
#include <modules/softwareintegration/utils.h>
#include <openspace/util/syncbuffer.h>
#include <ghoul/logging/logmanager.h>
@@ -34,125 +36,134 @@ namespace {
namespace openspace {
using namespace softwareintegration;
/* ============== SyncEngine functions ============== */
void SyncableFloatDataStorage::encode(SyncBuffer* syncBuffer) {
// ZoneScoped
std::lock_guard guard(_mutex);
syncBuffer->encode(_storageDirty);
if (!_storageDirty) return;
size_t nDataEntries = _storage.size();
syncBuffer->encode(nDataEntries);
for (auto& [key, value] : _storage) {
syncBuffer->encode(value.syncDirty);
// Only encode data if it is dirty, to save bandwidth
if (!value.syncDirty) continue;
syncBuffer->encode(key);
syncBuffer->encode(value.dirty);
// Go trough all data in data entry.
// Sequentially structured as: x1, y1, z1, x2, y2, z2...
size_t nItemsInDataEntry = value.data.size();
syncBuffer->encode(nItemsInDataEntry);
// syncBuffer->encode(value.data);
// Only encode data if it is dirty, to save bandwidth
if (value.dirty) {
// Go trough all data in data entry.
// Sequentially structured as: x1, y1, z1, x2, y2, z2...
size_t nItemsInDataEntry = value.data.size();
syncBuffer->encode(nItemsInDataEntry);
for (auto val : value.data) {
syncBuffer->encode(val);
}
for (auto val : value.data) {
syncBuffer->encode(val);
}
value.syncDirty = false;
}
}
void SyncableFloatDataStorage::decode(SyncBuffer* syncBuffer) {
std::lock_guard guard(_mutex);
std::lock_guard guard(_mutex);
bool storageDirty;
syncBuffer->decode(storageDirty);
if (!storageDirty) return;
size_t nDataEntries;
syncBuffer->decode(nDataEntries);
for (size_t i = 0; i < nDataEntries; ++i) {
bool dirty;
syncBuffer->decode(dirty);
if (!dirty) continue;
std::string key;
syncBuffer->decode(key);
bool dirty;
syncBuffer->decode(dirty);
if (dirty) {
size_t nItemsInDataEntry;
syncBuffer->decode(nItemsInDataEntry);
std::vector<float> dataEntry;
dataEntry.reserve(nItemsInDataEntry);
for (size_t j = 0; j < nItemsInDataEntry; ++j) {
float value;
syncBuffer->decode(value);
dataEntry.push_back(value);
}
insertAssign(key, Value{ dataEntry, dirty });
size_t nItemsInDataEntry;
syncBuffer->decode(nItemsInDataEntry);
std::vector<float> dataEntry{};
// dataEntry.resize(nItemsInDataEntry);
// syncBuffer->decode(dataEntry);
dataEntry.reserve(nItemsInDataEntry);
for (size_t j = 0; j < nItemsInDataEntry; ++j) {
float value;
syncBuffer->decode(value);
dataEntry.push_back(std::move(value));
}
insertAssign(key, Value{ dataEntry });
}
}
void SyncableFloatDataStorage::postSync(bool isMaster) {
std::lock_guard guard(_mutex);
if (isMaster) {
bool nothingDirty = true;
for (auto& [key, value] : _storage) {
if (value.dirty) {
value.dirty = false;
if (value.syncDirty) {
nothingDirty = false;
break;
}
}
if (nothingDirty) {
_storageDirty = false;
}
}
}
/* ================================================== */
const SyncableFloatDataStorage::ValueData& SyncableFloatDataStorage::fetch(const Key& key) {
LDEBUG(fmt::format("Loading data from float data storage: {}", key));
LDEBUG(fmt::format("Loading data from float data storage: {} ms", key));
std::lock_guard guard(_mutex);
auto it = find(key);
if (it == end()) {
LERROR(fmt::format(
"Could not find data with key '{}' in the centralized data storage", key
));
return std::move(ValueData{});
}
if (it == end()) {
LERROR(fmt::format(
"Could not find data with key '{}' in the centralized data storage", key
));
return ValueData{};
}
it->second.localDirty = false;
it->second.dirty = false;
return it->second.data;
return it->second.data;
}
bool SyncableFloatDataStorage::isDirty(const Key& key) {
auto it = find(key);
if (it == end()) {
return false;
}
if (it == end()) {
return false;
}
return it->second.localDirty;
return it->second.dirty;
}
bool SyncableFloatDataStorage::isSyncDirty(const Key& key) {
auto it = find(key);
if (it == end()) {
return false;
}
return it->second.syncDirty;
}
void SyncableFloatDataStorage::store(const Key& key, const ValueData& data) {
LDEBUG(fmt::format("Storing data in float data storage: {}", key));
Value value{ data, true, true };
auto old = find(key);
if (old != end()) {
glm::vec3 firstValueOld{};
for (glm::vec3::length_type i = 0; i < glm::vec3::length(); ++i) {
firstValueOld[i] = old->second.data[i];
}
LDEBUG(fmt::format(
"First data point: old: {}", firstValueOld
));
}
insertAssign(key, std::move(value));
auto newVal = find(key);
if (newVal != end()) {
glm::vec3 firstValueNew{};
for (glm::vec3::length_type i = 0; i < glm::vec3::length(); ++i) {
firstValueNew[i] = newVal->second.data[i];
}
LDEBUG(fmt::format(
"First data point: new {}", firstValueNew
));
}
std::lock_guard guard(_mutex);
insertAssign(key, { data });
_storageDirty = true;
}
/* =============== Utility functions ================ */

View File

@@ -38,8 +38,8 @@ public:
struct Value {
// a dataset stored like x1, y1, z1, x2, y2 ....
std::vector<float> data;
bool dirty;
bool localDirty;
bool syncDirty = true;
bool dirty = true;
};
using ValueData = decltype(Value::data);
using Key = std::string;
@@ -55,6 +55,7 @@ public:
const ValueData& fetch(const Key& key);
bool isDirty(const Key& key);
bool isSyncDirty(const Key& key);
void store(const Key& key, const ValueData& data);
private:
@@ -76,6 +77,9 @@ private:
std::mutex _mutex;
Storage _storage;
bool _storageDirty = true;
};
} // namespace openspace

View File

@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/softwareintegration/simp.h>
#include <modules/softwareintegration/utils.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionaryluaformatter.h>
@@ -35,23 +35,68 @@ namespace {
namespace openspace {
namespace softwareintegration {
namespace storage {
std::string getStorageKey(const std::string& identifier, Key key) {
auto it = std::find_if(
_keyStringFromKey.begin(),
_keyStringFromKey.end(),
[key](const std::pair<const std::string, Key>& p) {
return key == p.second;
}
);
if (it == _keyStringFromKey.end()) {
LDEBUG("Trying to get string of key that doesn't exist in syncable data storage...");
return "";
}
return identifier + "-" + it->first;
}
std::string getStorageKey(const std::string& identifier, const std::string& key) {
if (_keyStringFromKey.count(key) == 0) {
LDEBUG(fmt::format(
"Trying to get string of key {}, which doesn't exist in syncable data storage...",
key
));
return "";
}
return getStorageKey(identifier, _keyStringFromKey.at(key));
}
bool hasStorageKey(const std::string& key) {
return _keyStringFromKey.count(key) > 0;
}
Key getStorageKeyEnum(const std::string& key) {
if (hasStorageKey(key)) {
return _keyStringFromKey.at(key);
}
return Key::Unknown;
}
} // namespace storage
namespace simp {
SimpError::SimpError(const utils::ErrorCode _errorCode, const std::string& msg)
SimpError::SimpError(const tools::ErrorCode _errorCode, const std::string& msg)
: errorCode{errorCode}, ghoul::RuntimeError(fmt::format("{}: Error Code: {} - {}", "SIMP error", static_cast<uint32_t>(_errorCode), msg), "Software Integration Messaging Protocol error")
{}
bool utils::isEndOfCurrentValue(const std::vector<char>& message, size_t offset) {
bool tools::isEndOfCurrentValue(const std::vector<char>& message, size_t offset) {
if (offset >= message.size()) {
throw SimpError(
utils::ErrorCode::OffsetLargerThanMessageSize,
tools::ErrorCode::OffsetLargerThanMessageSize,
"Unexpectedly reached the end of the message..."
);
}
if (message.size() > 0 && offset == message.size() - 1 && message[offset] != SEP) {
throw SimpError(
utils::ErrorCode::ReachedEndBeforeSeparator,
tools::ErrorCode::ReachedEndBeforeSeparator,
"Reached end of message before reading separator character..."
);
}
@@ -60,19 +105,19 @@ bool utils::isEndOfCurrentValue(const std::vector<char>& message, size_t offset)
}
MessageType getMessageType(const std::string& type) {
if (utils::_messageTypeFromSIMPType.count(type) == 0) return MessageType::Unknown;
return utils::_messageTypeFromSIMPType.at(type);
if (tools::_messageTypeFromSIMPType.count(type) == 0) return MessageType::Unknown;
return tools::_messageTypeFromSIMPType.at(type);
}
std::string getSIMPType(const MessageType& type) {
auto it = std::find_if(
utils::_messageTypeFromSIMPType.begin(),
utils::_messageTypeFromSIMPType.end(),
tools::_messageTypeFromSIMPType.begin(),
tools::_messageTypeFromSIMPType.end(),
[type](const std::pair<const std::string, MessageType>& p) {
return type == p.second;
}
);
if (it == utils::_messageTypeFromSIMPType.end()) return "UNKN";
if (it == tools::_messageTypeFromSIMPType.end()) return "UNKN";
return it->first;
}
@@ -144,7 +189,7 @@ int readIntValue(const std::vector<char>& message, size_t& offset) {
int value;
bool isHex = false;
while (!utils::isEndOfCurrentValue(message, offset)) {
while (!tools::isEndOfCurrentValue(message, offset)) {
char c = message[offset];
if (c == 'x' || c == 'X') isHex = true;
string_value.push_back(c);
@@ -156,7 +201,7 @@ int readIntValue(const std::vector<char>& message, size_t& offset) {
}
catch(std::exception &err) {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Error when trying to parse the integer {}: {}", string_value, err.what())
);
}
@@ -169,7 +214,7 @@ float readFloatValue(const std::vector<char>& message, size_t& offset) {
std::string string_value;
float value;
while (!utils::isEndOfCurrentValue(message, offset)) {
while (!tools::isEndOfCurrentValue(message, offset)) {
string_value.push_back(message[offset]);
offset++;
}
@@ -179,7 +224,7 @@ float readFloatValue(const std::vector<char>& message, size_t& offset) {
}
catch(std::exception &err) {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Error when trying to parse the float {}: {}", string_value, err.what())
);
}
@@ -193,7 +238,7 @@ void readColormap(
) {
colorMap.reserve(nColors * 4);
while (message[offset] != SEP) {
glm::vec4 color = utils::readSingleColor(message, offset);
glm::vec4 color = tools::readSingleColor(message, offset);
// Colormap should be stored in a sequential vector
// of floats for syncing between nodes and when
@@ -207,10 +252,10 @@ void readColormap(
offset++;
}
glm::vec4 utils::readSingleColor(const std::vector<char>& message, size_t& offset) {
glm::vec4 tools::readSingleColor(const std::vector<char>& message, size_t& offset) {
if (message[offset] != '[') {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Expected to read '[', got {} in 'readColor'", message[offset])
);
}
@@ -223,7 +268,7 @@ glm::vec4 utils::readSingleColor(const std::vector<char>& message, size_t& offse
if (message[offset] != ']') {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Expected to read ']', got {} in 'readColor'", message[offset])
);
}
@@ -233,14 +278,14 @@ glm::vec4 utils::readSingleColor(const std::vector<char>& message, size_t& offse
}
glm::vec4 readColor(const std::vector<char>& message, size_t& offset) {
glm::vec4 color = utils::readSingleColor(message, offset);
glm::vec4 color = tools::readSingleColor(message, offset);
++offset;
return color;
}
std::string readString(const std::vector<char>& message, size_t& offset) {
std::string value;
while (!utils::isEndOfCurrentValue(message, offset)) {
while (!tools::isEndOfCurrentValue(message, offset)) {
value.push_back(message[offset]);
++offset;
}
@@ -258,10 +303,10 @@ void readPointData(
) {
pointData.reserve(nPoints * dimensionality);
while (!utils::isEndOfCurrentValue(message, offset)) {
while (!tools::isEndOfCurrentValue(message, offset)) {
if (message[offset] != '[') {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Expected to read '[', got {} in 'readPointData'", message[offset])
);
}
@@ -273,7 +318,7 @@ void readPointData(
if (message[offset] != ']') {
throw SimpError(
utils::ErrorCode::Generic,
tools::ErrorCode::Generic,
fmt::format("Expected to read ']', got {} in 'readPointData'", message[offset])
);
}
@@ -285,4 +330,6 @@ void readPointData(
} // namespace simp
} // namespace softwareintegration
} // namespace openspace

View File

@@ -29,6 +29,35 @@
namespace openspace {
namespace softwareintegration {
namespace storage {
enum class Key : uint32_t {
DataPoints = 0,
Colormap,
ColormapAttrData,
LinearSizeAttrData,
Unknown
};
const std::unordered_map<std::string, Key> _keyStringFromKey {
{"DataPoints", Key::DataPoints},
{"Colormap", Key::Colormap},
{"ColormapAttributeData", Key::ColormapAttrData},
{"LinearSizeAttributeData", Key::LinearSizeAttrData},
};
std::string getStorageKey(const std::string& identifier, Key key);
std::string getStorageKey(const std::string& identifier, const std::string& key);
Key getStorageKeyEnum(const std::string& key);
bool hasStorageKey(const std::string& key);
} // namespace storage
namespace simp {
const std::string ProtocolVersion = "1.9";
@@ -50,7 +79,7 @@ enum class MessageType : uint32_t {
Unknown
};
namespace utils {
namespace tools {
enum class ErrorCode : uint32_t {
ReachedEndBeforeSeparator = 0,
@@ -77,12 +106,12 @@ glm::vec4 readSingleColor(const std::vector<char>& message, size_t& offset);
bool isEndOfCurrentValue(const std::vector<char>& message, size_t offset);
} // namespace utils
} // namespace tools
class SimpError : public ghoul::RuntimeError {
public:
utils::ErrorCode errorCode;
explicit SimpError(const utils::ErrorCode _errorCode, const std::string& msg);
tools::ErrorCode errorCode;
explicit SimpError(const tools::ErrorCode _errorCode, const std::string& msg);
};
@@ -127,6 +156,8 @@ void readColormap(
} // namespace simp
} // namespace softwareintegration
} // namespace openspace
#endif // __OPENSPACE_MODULE_SOFTWAREINTEGRATION___SIMP___H__