From 9b7e2c6b38ef757852daeef591d4333b86e4a23b Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 16 Mar 2017 22:29:43 -0600 Subject: [PATCH 01/34] Initial commit of tags added to properties to enable grouping. --- include/openspace/properties/property.h | 17 ++++ src/properties/property.cpp | 9 ++ src/scene/scene.cpp | 17 ++++ src/scene/scene_lua.inl | 120 +++++++++++++++++++++--- 4 files changed, 150 insertions(+), 13 deletions(-) diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 54e7a07532..8cca565ef7 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -328,6 +328,20 @@ public: */ const ghoul::Dictionary& metaData() const; + /** + * Returns a list of all tags that have been assigned to the Property. Useful for + * trying to find a match for a desired batch operation on Properties. + * \return Pointer to vector of string tags that were assigned to the Property + */ + const std::vector* getTags(void) const; + + /** + * Adds a tag to the Property's list of assigned tags. Tags are useful for creating + * groups of Properties that can be used in batch operations. + * \param tag The string that is to be assigned to the Property + */ + void addTag(std::string tag); + protected: static const char* IdentifierKey; static const char* NameKey; @@ -383,6 +397,9 @@ protected: /// The callback function that will be invoked whenever the encapsulated value changes std::function _onChangeCallback; + + /// Collection of string tag(s) assigned to this property + std::vector _tags; }; } // namespace properties diff --git a/src/properties/property.cpp b/src/properties/property.cpp index c7cb5ddd44..06bf067281 100644 --- a/src/properties/property.cpp +++ b/src/properties/property.cpp @@ -211,5 +211,14 @@ std::string Property::generateAdditionalDescription() const { return ""; } +const std::vector* Property::getTags(void) const { + return &_tags; +} + +void Property::addTag(std::string tag) { + _tags.push_back(tag); +} + + } // namespace properties } // namespace openspace diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index bd44f78b65..b45dfcff68 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -672,6 +672,23 @@ scripting::LuaLibrary Scene::luaLibrary() { "the first argument. The second argument can be any type, but it has to " "match the type that the property expects.", }, + { + "setPropertyGroup", + &luascriptfunctions::property_setGroup, + "string, string, *", + "Sets all properties that belong to a tagged group AND match the " + "URI (with optional wildcards) in the first argument. Second argument is " + "the tag name to match. The third argument can be any type, but it has to " + "match tye type that the property expects.", + }, + { + "setPropertyGroupSingle", + &luascriptfunctions::property_setGroupSingle, + "string, *", + "Sets all properties that belong to a tagged group. The first argument " + "is the tag name to match. The second argument can be any time, but it " + "has to match tye type that the property expects.", + }, { "getPropertyValue", &luascriptfunctions::property_getValue, diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index fc849204b7..d971689db0 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -28,7 +28,20 @@ namespace openspace { namespace { -void applyRegularExpression(lua_State* L, std::regex regex, std::vector properties, int type) { +void executePropertySet(properties::Property* prop, lua_State* L) { + prop->setLuaValue(L); + //ensure properties are synced over parallel connection + std::string value; + prop->getStringValue(value); + /*OsEng.parallelConnection().scriptMessage( + prop->fullyQualifiedIdentifier(), + value + );*/ +} + +void applyRegularExpression(lua_State* L, std::regex regex, + std::vector properties, int type, + const std::string* tagToMatch = nullptr) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; @@ -47,17 +60,16 @@ void applyRegularExpression(lua_State* L, std::regex regex, std::vectortypeLua()) << "'" ); } - else { - prop->setLuaValue(L); - //ensure properties are synced over parallel connection - std::string value; - prop->getStringValue(value); -/* OsEng.parallelConnection().scriptMessage( - prop->fullyQualifiedIdentifier(), - value - );*/ + else if (tagToMatch) { + for (const std::string tagEvaluate : *prop->getTags()) { + if (tagEvaluate.compare(*tagToMatch) == 0) { + executePropertySet(prop, L); + break; + } + } + } else { + executePropertySet(prop, L); } - } } } @@ -85,7 +97,8 @@ int property_setValueSingle(lua_State* L) { properties::Property* prop = property(uri); if (!prop) { - LERRORC("property_setValue", errorLocation(L) << "Property with URI '" << uri << "' was not found"); + LERRORC("property_setValue", errorLocation(L) << "Property with URI '" + << uri << "' was not found"); return 0; } @@ -131,7 +144,8 @@ int property_setValueRegex(lua_State* L) { ); } catch (const std::regex_error& e) { - LERRORC("property_setValueRegex", "Malformed regular expression: '" << regex << "'"); + LERRORC("property_setValueRegex", "Malformed regular expression: '" + << regex << "'"); } return 0; @@ -174,6 +188,86 @@ int property_setValue(lua_State* L) { return 0; } +/** + * \ingroup LuaScripts + * setPropertyGroupSingle(string, *): + * Sets value of any property containing a tag that matches that of the first argument + * to the value of the second argument, which is arbirtrary, but must agree with the + * type the denoted Property expects + */ +int property_setGroupSingle(lua_State* L) { + using ghoul::lua::errorLocation; + using ghoul::lua::luaTypeToString; + + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments); + + std::string tagToMatch = luaL_checkstring(L, -2); + const int type = lua_type(L, -1); + + for (properties::Property* prop : allProperties()) { + for (std::string tagEvaluate : *prop->getTags()) { + if (tagEvaluate.compare(tagToMatch) == 0) { + if (type != prop->typeLua()) { + LERRORC("property_setValue", errorLocation(L) << "Property '" + << prop->guiName() << "' does not accept input of type '" + << luaTypeToString(type) << "'. Requested type: '" + << luaTypeToString(prop->typeLua()) << "'"); + return 0; + } + else { + prop->setLuaValue(L); + //ensure properties are synced over parallel connection + std::string value; + prop->getStringValue(value); + //OsEng.parallelConnection().scriptMessage( + prop->fullyQualifiedIdentifier(), value); + break; + } + } + } + } + + return 0; +} + +/** + * \ingroup LuaScripts + * setPropertyGroup(string, string, *): + * Sets all properties identified by the URI (with potential wildcards) in the first + * argument, AND contain a tag that matches that given in the second argument. The third + * argument can be any type, but it has to match the type that the property(s) expect. + */ + +int property_setGroup(lua_State* L) { + using ghoul::lua::errorLocation; + using ghoul::lua::luaTypeToString; + + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 3, nArguments); + + std::string tag = luaL_checkstring(L, -2); + std::string regex = luaL_checkstring(L, -3); + + // Replace all wildcards * with the correct regex (.*) + size_t startPos = regex.find("*"); + while (startPos != std::string::npos) { + regex.replace(startPos, 1, "(.*)"); + startPos += 4; + startPos = regex.find("*", startPos); + } + + applyRegularExpression( + L, + std::regex(regex/*, std::regex_constants::optimize*/), + allProperties(), + lua_type(L, -1), + &tag + ); + + return 0; +} + /** * \ingroup LuaScripts * getPropertyValue(string): From fab9185b33265f922af049305c689f0b4152e135 Mon Sep 17 00:00:00 2001 From: GPayne Date: Fri, 17 Mar 2017 11:17:06 -0600 Subject: [PATCH 02/34] Added additional function for group to accept regex expression for URI --- src/scene/scene.cpp | 18 +++++++-- src/scene/scene_lua.inl | 87 +++++++++++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index b45dfcff68..aed03d9479 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -684,10 +684,20 @@ scripting::LuaLibrary Scene::luaLibrary() { { "setPropertyGroupSingle", &luascriptfunctions::property_setGroupSingle, - "string, *", - "Sets all properties that belong to a tagged group. The first argument " - "is the tag name to match. The second argument can be any time, but it " - "has to match tye type that the property expects.", + "string, string, *", + "Sets all properties that belong to a tagged group AND match the " + "URI (requires exact match) in the first argument. Second argument is " + "the tag name to match. The third argument can be any type, but it has to " + "match tye type that the property expects.", + }, + { + "setPropertyGroupRegex", + &luascriptfunctions::property_setGroupRegex, + "string, string, *", + "Sets all properties that belong to a tagged group AND match the " + "URI regex in the first argument. Second argument is the tag name to" + "match. The third argument can be any type, but it has to match the " + "type that the property expects.", }, { "getPropertyValue", diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index d971689db0..e0f97421d9 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -190,40 +190,46 @@ int property_setValue(lua_State* L) { /** * \ingroup LuaScripts - * setPropertyGroupSingle(string, *): - * Sets value of any property containing a tag that matches that of the first argument - * to the value of the second argument, which is arbirtrary, but must agree with the - * type the denoted Property expects + * setPropertyGroupSingle(string, string, *): + * Sets all properties identified by the URI (requires exact match) in the first + * argument, AND contain a tag that matches that given in the second argument. The third + * argument can be any type, but it has to match the type that the property(s) expect. */ int property_setGroupSingle(lua_State* L) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments); + SCRIPT_CHECK_ARGUMENTS("property_setGroupSingle", L, 2, nArguments); + std::string uri = luaL_checkstring(L, -3); std::string tagToMatch = luaL_checkstring(L, -2); const int type = lua_type(L, -1); - for (properties::Property* prop : allProperties()) { - for (std::string tagEvaluate : *prop->getTags()) { - if (tagEvaluate.compare(tagToMatch) == 0) { - if (type != prop->typeLua()) { - LERRORC("property_setValue", errorLocation(L) << "Property '" - << prop->guiName() << "' does not accept input of type '" - << luaTypeToString(type) << "'. Requested type: '" - << luaTypeToString(prop->typeLua()) << "'"); - return 0; - } - else { - prop->setLuaValue(L); - //ensure properties are synced over parallel connection - std::string value; - prop->getStringValue(value); - //OsEng.parallelConnection().scriptMessage( - prop->fullyQualifiedIdentifier(), value); - break; - } + properties::Property* prop = property(uri); + if (!prop) { + LERRORC("property_setValue", errorLocation(L) << "Property with URI '" + << uri << "' was not found"); + return 0; + } + + for (std::string tagEvaluate : *prop->getTags()) { + if (tagEvaluate.compare(tagToMatch) == 0) { + if (type != prop->typeLua()) { + LERRORC("property_setValue", errorLocation(L) << "Property '" + << prop->guiName() << "' does not accept input of type '" + << luaTypeToString(type) << "'. Requested type: '" + << luaTypeToString(prop->typeLua()) << "'"); + return 0; + } + else { + prop->setLuaValue(L); + //ensure properties are synced over parallel connection + std::string value; + prop->getStringValue(value); + //OsEng.parallelConnection().scriptMessage( + // prop->fullyQualifiedIdentifier(), value); + break; } } } @@ -268,6 +274,39 @@ int property_setGroup(lua_State* L) { return 0; } +/** + * \ingroup LuaScripts + * setPropertyGroupRegex(string, *): + * Sets all properties that pass the regular expression in the first argument. The second + * argument can be any type, but it has to match the type of the properties that matched + * the regular expression. The regular expression has to be of the ECMAScript grammar. +*/ +int property_setGroupRegex(lua_State* L) { + using ghoul::lua::errorLocation; + using ghoul::lua::luaTypeToString; + + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("property_setGroupRegex<", L, 2, nArguments); + + std::string regex = luaL_checkstring(L, -3); + std::string tag = luaL_checkstring(L, -2); + try { + applyRegularExpression( + L, + std::regex(regex, std::regex_constants::optimize), + allProperties(), + lua_type(L, -1), + &tag + ); + } + catch (const std::regex_error& e) { + LERRORC("property_setValueRegex", "Malformed regular expression: '" + << regex << "'"); + } + + return 0; +} + /** * \ingroup LuaScripts * getPropertyValue(string): From ae2cb222b046891468a1da50e2e0ed7d6f761566 Mon Sep 17 00:00:00 2001 From: GPayne Date: Tue, 21 Mar 2017 11:35:09 -0600 Subject: [PATCH 03/34] Switched to using propertyowners in grouping, and group/tag name in group syntax --- data/scene/mercury/mercury.mod | 3 +- include/openspace/properties/property.h | 16 ---- include/openspace/properties/propertyowner.h | 16 ++++ include/openspace/scene/scenegraphnode.h | 1 + src/properties/property.cpp | 9 -- src/properties/propertyowner.cpp | 8 ++ src/scene/scene.cpp | 25 +++--- src/scene/scene_lua.inl | 86 +++++++++++++------- src/scene/scenegraphnode.cpp | 8 ++ 9 files changed, 106 insertions(+), 66 deletions(-) diff --git a/data/scene/mercury/mercury.mod b/data/scene/mercury/mercury.mod index aa4be9675d..7902252625 100644 --- a/data/scene/mercury/mercury.mod +++ b/data/scene/mercury/mercury.mod @@ -62,7 +62,8 @@ return { }, Color = {0.6, 0.5, 0.5 }, Period = 87.968, - Resolution = 100 + Resolution = 100, + Tag = "defaultTrails" } } } diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 8cca565ef7..1db90523fe 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -328,20 +328,6 @@ public: */ const ghoul::Dictionary& metaData() const; - /** - * Returns a list of all tags that have been assigned to the Property. Useful for - * trying to find a match for a desired batch operation on Properties. - * \return Pointer to vector of string tags that were assigned to the Property - */ - const std::vector* getTags(void) const; - - /** - * Adds a tag to the Property's list of assigned tags. Tags are useful for creating - * groups of Properties that can be used in batch operations. - * \param tag The string that is to be assigned to the Property - */ - void addTag(std::string tag); - protected: static const char* IdentifierKey; static const char* NameKey; @@ -398,8 +384,6 @@ protected: /// The callback function that will be invoked whenever the encapsulated value changes std::function _onChangeCallback; - /// Collection of string tag(s) assigned to this property - std::vector _tags; }; } // namespace properties diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index e26af2db6f..aa5f138faf 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -207,6 +207,20 @@ public: /// \see PropertyOwner::removePropertySubOwner(PropertyOwner*) void removePropertySubOwner(PropertyOwner& owner); + /** + * Returns a list of all tags that have been assigned to the Property. Useful for + * trying to find a match for a desired batch operation on Properties. + * \return Pointer to vector of string tags that were assigned to the Property + */ + const std::vector* getTags(void) const; + + /** + * Adds a tag to the Property's list of assigned tags. Tags are useful for creating + * groups of Properties that can be used in batch operations. + * \param tag The string that is to be assigned to the Property + */ + void addTag(std::string tag); + private: /// The name of this PropertyOwner std::string _name; @@ -218,6 +232,8 @@ private: std::vector _subOwners; /// The associations between group identifiers of Property's and human-readable names std::map _groupNames; + /// Collection of string tag(s) assigned to this property + std::vector _tags; }; } // namespace properties diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index 1acce2442e..dd1310625d 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -59,6 +59,7 @@ public: static const std::string KeyName; static const std::string KeyParentName; static const std::string KeyDependencies; + static const std::string KeyTag; SceneGraphNode(); ~SceneGraphNode(); diff --git a/src/properties/property.cpp b/src/properties/property.cpp index 06bf067281..c7cb5ddd44 100644 --- a/src/properties/property.cpp +++ b/src/properties/property.cpp @@ -211,14 +211,5 @@ std::string Property::generateAdditionalDescription() const { return ""; } -const std::vector* Property::getTags(void) const { - return &_tags; -} - -void Property::addTag(std::string tag) { - _tags.push_back(tag); -} - - } // namespace properties } // namespace openspace diff --git a/src/properties/propertyowner.cpp b/src/properties/propertyowner.cpp index e45cd9279f..373e2a8da4 100644 --- a/src/properties/propertyowner.cpp +++ b/src/properties/propertyowner.cpp @@ -324,5 +324,13 @@ const std::string& PropertyOwner::name() const { return _name; } +const std::vector* PropertyOwner::getTags(void) const { + return &_tags; +} + +void PropertyOwner::addTag(std::string tag) { + _tags.push_back(tag); +} + } // namespace properties } // namespace openspace diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index aed03d9479..44fbd504d6 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -675,29 +675,30 @@ scripting::LuaLibrary Scene::luaLibrary() { { "setPropertyGroup", &luascriptfunctions::property_setGroup, - "string, string, *", + "string, *", "Sets all properties that belong to a tagged group AND match the " - "URI (with optional wildcards) in the first argument. Second argument is " - "the tag name to match. The third argument can be any type, but it has to " - "match tye type that the property expects.", + "URI (with optional wildcards) in the first argument (group tag name is " + "given in place of property owner name). The second argument can be any " + "type, but it has to match the type that the property expects.", }, { "setPropertyGroupSingle", &luascriptfunctions::property_setGroupSingle, - "string, string, *", + "string, *", "Sets all properties that belong to a tagged group AND match the " - "URI (requires exact match) in the first argument. Second argument is " - "the tag name to match. The third argument can be any type, but it has to " - "match tye type that the property expects.", + "URI (requires exact match) in the first argument (group tag name is " + "given in place of property owner name). The second argument can be any " + "type, but it has to match the type that the property expects.", }, { "setPropertyGroupRegex", &luascriptfunctions::property_setGroupRegex, - "string, string, *", + "string, *", "Sets all properties that belong to a tagged group AND match the " - "URI regex in the first argument. Second argument is the tag name to" - "match. The third argument can be any type, but it has to match the " - "type that the property expects.", + "URI (allows regular expression syntax) in the first argument " + "(group tag name is given in place of property owner name). The second " + "argument can be any type, but it has to match the type that the " + "property expects.", }, { "getPropertyValue", diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index e0f97421d9..023001dc4a 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -73,6 +73,38 @@ void applyRegularExpression(lua_State* L, std::regex regex, } } } + +std::string extractGroupNameFromUri(std::string command) { + return command.substr(0, command.find_first_of(".")); +} + +template +PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, + const std::string tagToMatch) { + PropertyOwner* tagMatchOwner = nullptr; + PropertyOwner* owner = prop->owner(); + + if (owner != nullptr) { + std::vector* tags = owner->getTags(); + for (currTag : tags) { + if (currTag == tagToMatch) { + tagMatchOwner = owner; + break; + } + } + + //Call recursively until we find an owner with matching tag or the top of the + // ownership list + if (tagMatchOwner == nullptr) + tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch); + } + return tagMatchOwner; +} + +std::string replaceUriGroupNameWith(std::string uri, std::string ownerName) { + size_t pos = uri.find_first_of("."); + return ownerName + "." + uri.substr(pos); +} } @@ -190,10 +222,11 @@ int property_setValue(lua_State* L) { /** * \ingroup LuaScripts - * setPropertyGroupSingle(string, string, *): - * Sets all properties identified by the URI (requires exact match) in the first - * argument, AND contain a tag that matches that given in the second argument. The third - * argument can be any type, but it has to match the type that the property(s) expect. + * setPropertyGroupSingle(string, *): + * Sets all properties that belong to a tagged group AND match the URI (requires exact + * match) in the first argument (group tag name is given in place of property owner + * name). The second argument can be any type, but it has to match the type that the + * property expects. */ int property_setGroupSingle(lua_State* L) { using ghoul::lua::errorLocation; @@ -202,19 +235,16 @@ int property_setGroupSingle(lua_State* L) { int nArguments = lua_gettop(L); SCRIPT_CHECK_ARGUMENTS("property_setGroupSingle", L, 2, nArguments); - std::string uri = luaL_checkstring(L, -3); - std::string tagToMatch = luaL_checkstring(L, -2); + std::string uri = luaL_checkstring(L, -2); const int type = lua_type(L, -1); - - properties::Property* prop = property(uri); - if (!prop) { - LERRORC("property_setValue", errorLocation(L) << "Property with URI '" - << uri << "' was not found"); - return 0; - } - - for (std::string tagEvaluate : *prop->getTags()) { - if (tagEvaluate.compare(tagToMatch) == 0) { + std::string tagToMatch = extractGroupNameFromUri(uri); + + for (properties::Property* prop : allProperties()) { + //std::string id = prop->fullyQualifiedIdentifier(); + PropertyOwner* matchingTaggedOwner = findPropertyOwnerWithMatchingGroupTag(prop, + tagToMatch); + if (matchingTaggedOwner != nullptr) { + uri = replaceUriGroupNameWith(uri, matchingTaggedOwner.name()); if (type != prop->typeLua()) { LERRORC("property_setValue", errorLocation(L) << "Property '" << prop->guiName() << "' does not accept input of type '" @@ -239,10 +269,11 @@ int property_setGroupSingle(lua_State* L) { /** * \ingroup LuaScripts - * setPropertyGroup(string, string, *): - * Sets all properties identified by the URI (with potential wildcards) in the first - * argument, AND contain a tag that matches that given in the second argument. The third - * argument can be any type, but it has to match the type that the property(s) expect. + * setPropertyGroup(string, *): + * Sets all properties that belong to a tagged group AND match the URI (with optional + * wildcards) in the first argument (group tag name is given in place of property owner + * name). The second argument can be any type, but it has to match the type that the + * property expects. */ int property_setGroup(lua_State* L) { @@ -250,10 +281,9 @@ int property_setGroup(lua_State* L) { using ghoul::lua::luaTypeToString; int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 3, nArguments); + SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 2, nArguments); - std::string tag = luaL_checkstring(L, -2); - std::string regex = luaL_checkstring(L, -3); + std::string regex = luaL_checkstring(L, -2); // Replace all wildcards * with the correct regex (.*) size_t startPos = regex.find("*"); @@ -277,9 +307,10 @@ int property_setGroup(lua_State* L) { /** * \ingroup LuaScripts * setPropertyGroupRegex(string, *): - * Sets all properties that pass the regular expression in the first argument. The second - * argument can be any type, but it has to match the type of the properties that matched - * the regular expression. The regular expression has to be of the ECMAScript grammar. + * Sets all properties that belong to a tagged group AND match the URI (allows regular + * expression syntax) in the first argument (group tag name is given in place of property + * owner name). The second argument can be any type, but it has to match the type that + * the property expects. */ int property_setGroupRegex(lua_State* L) { using ghoul::lua::errorLocation; @@ -288,8 +319,7 @@ int property_setGroupRegex(lua_State* L) { int nArguments = lua_gettop(L); SCRIPT_CHECK_ARGUMENTS("property_setGroupRegex<", L, 2, nArguments); - std::string regex = luaL_checkstring(L, -3); - std::string tag = luaL_checkstring(L, -2); + std::string regex = luaL_checkstring(L, -2); try { applyRegularExpression( L, diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index d19effd97b..a039c20a07 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -64,6 +64,7 @@ const std::string SceneGraphNode::RootNodeName = "Root"; const std::string SceneGraphNode::KeyName = "Name"; const std::string SceneGraphNode::KeyParentName = "Parent"; const std::string SceneGraphNode::KeyDependencies = "Dependencies"; +const std::string SceneGraphNode::KeyTag = "Tag"; SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){ openspace::documentation::testSpecificationAndThrow( @@ -139,6 +140,13 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di LDEBUG("Successfully created scale for '" << result->name() << "'"); } + if (dictionary.hasKey(KeyTag)) { + std::string tagString; + dictionary.getValue(KeyTag, tagString); + result->addTag(tagString); + LDEBUG("Successfully added tag for '" << result->name() << "'"); + } + LDEBUG("Successfully created SceneGraphNode '" << result->name() << "'"); return result; From 701489c969f900aebde7abd3c9bd17293da9d537 Mon Sep 17 00:00:00 2001 From: GPayne Date: Tue, 21 Mar 2017 20:22:04 -0600 Subject: [PATCH 04/34] Fixed problems with searching for properties tagged with group name, but still doesn't find tagged owner --- src/scene/scene_lua.inl | 137 +++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 58 deletions(-) diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 023001dc4a..97bd868256 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -39,19 +39,50 @@ void executePropertySet(properties::Property* prop, lua_State* L) { );*/ } +template +properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, +const std::string tagToMatch) { + properties::PropertyOwner* tagMatchOwner = nullptr; + properties::PropertyOwner* owner = prop->owner(); + + if (owner != nullptr) { + std::vector* tags = (std::vector*)owner->getTags(); + for (std::string currTag : *tags) { + if (tagToMatch.compare(currTag) == 0) { + tagMatchOwner = owner; + break; + } + } + + //Call recursively until we find an owner with matching tag or the top of the + // ownership list + if (tagMatchOwner == nullptr) + tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch); + } + return tagMatchOwner; +} + void applyRegularExpression(lua_State* L, std::regex regex, std::vector properties, int type, - const std::string* tagToMatch = nullptr) { + std::string groupName = "") { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; - + bool isGroupMode = (groupName.compare("") != 0) ? true : false; + for (properties::Property* prop : properties) { // Check the regular expression for all properties std::string id = prop->fullyQualifiedIdentifier(); + if (std::regex_match(id, regex)) { // If the fully qualified id matches the regular expression, we queue the // value change if the types agree - + if (isGroupMode) { + properties::PropertyOwner* matchingTaggedOwner = findPropertyOwnerWithMatchingGroupTag(prop, + groupName); + if (matchingTaggedOwner == nullptr) + continue; + } + if (type != prop->typeLua()) { LERRORC("property_setValue", errorLocation(L) << "Property '" << @@ -59,16 +90,8 @@ void applyRegularExpression(lua_State* L, std::regex regex, "' does not accept input of type '" << luaTypeToString(type) << "'. Requested type: '" << luaTypeToString(prop->typeLua()) << "'" ); - } - else if (tagToMatch) { - for (const std::string tagEvaluate : *prop->getTags()) { - if (tagEvaluate.compare(*tagToMatch) == 0) { - executePropertySet(prop, L); - break; - } - } } else { - executePropertySet(prop, L); + executePropertySet(prop, L); } } } @@ -78,33 +101,15 @@ std::string extractGroupNameFromUri(std::string command) { return command.substr(0, command.find_first_of(".")); } -template -PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, - const std::string tagToMatch) { - PropertyOwner* tagMatchOwner = nullptr; - PropertyOwner* owner = prop->owner(); - - if (owner != nullptr) { - std::vector* tags = owner->getTags(); - for (currTag : tags) { - if (currTag == tagToMatch) { - tagMatchOwner = owner; - break; - } - } - - //Call recursively until we find an owner with matching tag or the top of the - // ownership list - if (tagMatchOwner == nullptr) - tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch); - } - return tagMatchOwner; -} - std::string replaceUriGroupNameWith(std::string uri, std::string ownerName) { size_t pos = uri.find_first_of("."); return ownerName + "." + uri.substr(pos); } + +std::string extractUriWithoutGroupName(std::string uri) { + size_t pos = uri.find_first_of("."); + return uri.substr(pos); +} } @@ -237,29 +242,38 @@ int property_setGroupSingle(lua_State* L) { std::string uri = luaL_checkstring(L, -2); const int type = lua_type(L, -1); - std::string tagToMatch = extractGroupNameFromUri(uri); + std::string tagToMatch = extractGroupNameFromUri(uri); + std::string pathRemainderToMatch = extractUriWithoutGroupName(uri); for (properties::Property* prop : allProperties()) { - //std::string id = prop->fullyQualifiedIdentifier(); - PropertyOwner* matchingTaggedOwner = findPropertyOwnerWithMatchingGroupTag(prop, - tagToMatch); - if (matchingTaggedOwner != nullptr) { - uri = replaceUriGroupNameWith(uri, matchingTaggedOwner.name()); - if (type != prop->typeLua()) { - LERRORC("property_setValue", errorLocation(L) << "Property '" - << prop->guiName() << "' does not accept input of type '" - << luaTypeToString(type) << "'. Requested type: '" - << luaTypeToString(prop->typeLua()) << "'"); - return 0; - } - else { - prop->setLuaValue(L); - //ensure properties are synced over parallel connection - std::string value; - prop->getStringValue(value); - //OsEng.parallelConnection().scriptMessage( - // prop->fullyQualifiedIdentifier(), value); - break; + std::string propFullId = prop->fullyQualifiedIdentifier(); + //Look for a match in the uri with the group name (first term) removed + int propMatchLength = propFullId.length() - pathRemainderToMatch.length(); + + if (propMatchLength >= 0) { + std::string thisPropMatchId = propFullId.substr(propMatchLength); + //If remainder of uri matches (with group name removed), + if (pathRemainderToMatch.compare(thisPropMatchId) == 0) { + properties::PropertyOwner* matchingTaggedOwner + = findPropertyOwnerWithMatchingGroupTag(prop, tagToMatch); + if (matchingTaggedOwner != nullptr) { + if (type != prop->typeLua()) { + LERRORC("property_setValue", errorLocation(L) << "Property '" + << prop->guiName() << "' does not accept input of type '" + << luaTypeToString(type) << "'. Requested type: '" + << luaTypeToString(prop->typeLua()) << "'"); + return 0; + } + else { + prop->setLuaValue(L); + //ensure properties are synced over parallel connection + std::string value; + prop->getStringValue(value); + //OsEng.parallelConnection().scriptMessage( + // prop->fullyQualifiedIdentifier(), value); + break; + } + } } } } @@ -284,6 +298,7 @@ int property_setGroup(lua_State* L) { SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 2, nArguments); std::string regex = luaL_checkstring(L, -2); + std::string groupName = extractGroupNameFromUri(regex); // Replace all wildcards * with the correct regex (.*) size_t startPos = regex.find("*"); @@ -292,13 +307,15 @@ int property_setGroup(lua_State* L) { startPos += 4; startPos = regex.find("*", startPos); } + //Remove group name from start of regex and replace with '.*' + regex = replaceUriGroupNameWith(regex, ".*"); applyRegularExpression( L, std::regex(regex/*, std::regex_constants::optimize*/), allProperties(), lua_type(L, -1), - &tag + groupName ); return 0; @@ -320,13 +337,17 @@ int property_setGroupRegex(lua_State* L) { SCRIPT_CHECK_ARGUMENTS("property_setGroupRegex<", L, 2, nArguments); std::string regex = luaL_checkstring(L, -2); + std::string groupName = extractGroupNameFromUri(regex); + //Remove group name from start of regex and replace with '.*' + regex = replaceUriGroupNameWith(regex, ".*"); + try { applyRegularExpression( L, std::regex(regex, std::regex_constants::optimize), allProperties(), lua_type(L, -1), - &tag + groupName ); } catch (const std::regex_error& e) { From 95f4b249b925d15cb9a0bde400fb081ad88e44c1 Mon Sep 17 00:00:00 2001 From: GPayne Date: Wed, 22 Mar 2017 14:10:53 -0600 Subject: [PATCH 05/34] Fixed problem exiting before addressing all tags. Added tags to renderable class. --- src/rendering/renderable.cpp | 6 ++++++ src/scene/scene_lua.inl | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index ab22ebe710..e68b83a174 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -41,6 +41,8 @@ namespace { const char* keyStart = "StartTime"; const char* keyEnd = "EndTime"; const char* KeyType = "Type"; + + const char* keyTag = "Tag"; } namespace openspace { @@ -111,6 +113,10 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) dictionary.getValue(keyStart, _startTime); dictionary.getValue(keyEnd, _endTime); + std::string tagName; + dictionary.getValue(keyTag, tagName); + if (! tagName.empty()) + addTag(tagName); if (_startTime != "" && _endTime != "") { _hasTimeInterval = true; diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 97bd868256..0edd629a01 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -57,7 +57,7 @@ const std::string tagToMatch) { //Call recursively until we find an owner with matching tag or the top of the // ownership list if (tagMatchOwner == nullptr) - tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch); + tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch); } return tagMatchOwner; } @@ -250,6 +250,9 @@ int property_setGroupSingle(lua_State* L) { //Look for a match in the uri with the group name (first term) removed int propMatchLength = propFullId.length() - pathRemainderToMatch.length(); +if( propFullId.substr(0, 31).compare("MercuryTrail.renderable.enabled") == 0 ) + int type2 = 3; + if (propMatchLength >= 0) { std::string thisPropMatchId = propFullId.substr(propMatchLength); //If remainder of uri matches (with group name removed), @@ -262,7 +265,7 @@ int property_setGroupSingle(lua_State* L) { << prop->guiName() << "' does not accept input of type '" << luaTypeToString(type) << "'. Requested type: '" << luaTypeToString(prop->typeLua()) << "'"); - return 0; + continue; } else { prop->setLuaValue(L); @@ -271,7 +274,7 @@ int property_setGroupSingle(lua_State* L) { prop->getStringValue(value); //OsEng.parallelConnection().scriptMessage( // prop->fullyQualifiedIdentifier(), value); - break; + //break; } } } From 40de0a962405ed0808c06cd5b0517a3e5518ea35 Mon Sep 17 00:00:00 2001 From: GPayne Date: Wed, 22 Mar 2017 14:25:08 -0600 Subject: [PATCH 06/34] Added tags to solar system planet .mod files for testing. --- data/scene/earth/earth.mod | 5 +++-- data/scene/jupiter/jupiter/jupiter.mod | 5 +++-- data/scene/mars/mars.mod | 3 ++- data/scene/neptune/neptune.mod | 5 +++-- data/scene/saturn/saturn/saturn.mod | 3 ++- data/scene/uranus/uranus.mod | 5 +++-- data/scene/venus/venus.mod | 3 ++- 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/data/scene/earth/earth.mod b/data/scene/earth/earth.mod index 78b3a3bb90..7722adb042 100644 --- a/data/scene/earth/earth.mod +++ b/data/scene/earth/earth.mod @@ -78,9 +78,10 @@ return { -- EndTime = "2017 JAN 01 12:00:00.000", -- SampleInterval = 3600 Period = 365.242, - Resolution = 1000 + Resolution = 1000, + Tag = "defaultTrails" }, - GuiName = "/Solar/EarthTrail" + GuiName = "/Solar/EarthTrail", }, --[[ { diff --git a/data/scene/jupiter/jupiter/jupiter.mod b/data/scene/jupiter/jupiter/jupiter.mod index 6302b66739..e4bbb0cd73 100644 --- a/data/scene/jupiter/jupiter/jupiter.mod +++ b/data/scene/jupiter/jupiter/jupiter.mod @@ -64,7 +64,8 @@ return { }, Color = { 0.8, 0.7, 0.7 }, Period = 4330.595, - Resolution = 1000 - } + Resolution = 1000, + }, + Tag = "defaultTrails" } } diff --git a/data/scene/mars/mars.mod b/data/scene/mars/mars.mod index 54e33cbd6c..afbfafd2ec 100644 --- a/data/scene/mars/mars.mod +++ b/data/scene/mars/mars.mod @@ -56,7 +56,8 @@ return { }, Color = { 0.814, 0.305, 0.220 }, Period = 686.973, - Resolution = 1000 + Resolution = 1000, + Tag = "defaultTrails" } } } diff --git a/data/scene/neptune/neptune.mod b/data/scene/neptune/neptune.mod index 5967f0a8fe..d25d973ab7 100644 --- a/data/scene/neptune/neptune.mod +++ b/data/scene/neptune/neptune.mod @@ -52,7 +52,8 @@ return { }, Color = {0.2, 0.5, 1.0 }, Period = 60200, - Resolution = 1000 - }, + Resolution = 1000, + Tag = "defaultTrails" + } } } diff --git a/data/scene/saturn/saturn/saturn.mod b/data/scene/saturn/saturn/saturn.mod index 4dc0a215c6..7aff69281e 100644 --- a/data/scene/saturn/saturn/saturn.mod +++ b/data/scene/saturn/saturn/saturn.mod @@ -76,7 +76,8 @@ return { }, Color = {0.85,0.75,0.51 }, Period = 10746.94, - Resolution = 1000 + Resolution = 1000, + Tag = "defaultTrails" }, } } diff --git a/data/scene/uranus/uranus.mod b/data/scene/uranus/uranus.mod index 7d0a559780..8f4ce17384 100644 --- a/data/scene/uranus/uranus.mod +++ b/data/scene/uranus/uranus.mod @@ -58,7 +58,8 @@ return { }, Color = {0.60, 0.95, 1.00 }, Period = 30588.740, - Resolution = 1000 - }, + Resolution = 1000, + Tag = "defaultTrails" + } } } diff --git a/data/scene/venus/venus.mod b/data/scene/venus/venus.mod index c7943047d3..1a187b2dff 100644 --- a/data/scene/venus/venus.mod +++ b/data/scene/venus/venus.mod @@ -56,7 +56,8 @@ return { }, Color = { 1.0, 0.5, 0.2 }, Period = 224.695, - Resolution = 1000 + Resolution = 1000, + Tag = "defaultTrails" } } } From bcdd906ad7f40a06a77c169a0664a120f34bc58a Mon Sep 17 00:00:00 2001 From: GPayne Date: Fri, 31 Mar 2017 15:14:00 -0600 Subject: [PATCH 07/34] Some minor changes and added tag support to screenspacerenderable --- include/openspace/properties/propertyowner.h | 2 +- src/properties/propertyowner.cpp | 4 ++-- src/rendering/renderable.cpp | 2 -- src/rendering/screenspacerenderable.cpp | 7 ++++++- src/scene/scene_lua.inl | 6 +++--- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index aa5f138faf..8795fbffc7 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -212,7 +212,7 @@ public: * trying to find a match for a desired batch operation on Properties. * \return Pointer to vector of string tags that were assigned to the Property */ - const std::vector* getTags(void) const; + const std::vector tags() const; /** * Adds a tag to the Property's list of assigned tags. Tags are useful for creating diff --git a/src/properties/propertyowner.cpp b/src/properties/propertyowner.cpp index 373e2a8da4..fe27cc0503 100644 --- a/src/properties/propertyowner.cpp +++ b/src/properties/propertyowner.cpp @@ -324,8 +324,8 @@ const std::string& PropertyOwner::name() const { return _name; } -const std::vector* PropertyOwner::getTags(void) const { - return &_tags; +const std::vector PropertyOwner::tags() const { + return _tags; } void PropertyOwner::addTag(std::string tag) { diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index e68b83a174..5a90dbb990 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -41,7 +41,6 @@ namespace { const char* keyStart = "StartTime"; const char* keyEnd = "EndTime"; const char* KeyType = "Type"; - const char* keyTag = "Tag"; } @@ -117,7 +116,6 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) dictionary.getValue(keyTag, tagName); if (! tagName.empty()) addTag(tagName); - if (_startTime != "" && _endTime != "") { _hasTimeInterval = true; } diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index cc89ab046d..2f3ca4cc90 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -47,7 +47,7 @@ namespace { const char* KeyScale = "Scale"; const char* KeyDepth = "Depth"; const char* KeyAlpha = "Alpha"; - + const char* keyTag = "Tag"; const float PlaneDepth = -2.f; } @@ -146,6 +146,11 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary dictionary.getValue(KeyDepth, _depth); dictionary.getValue(KeyAlpha, _alpha); + std::string tagName; + dictionary.getValue(keyTag, tagName); + if (! tagName.empty()) + addTag(tagName); + // Setting spherical/euclidean onchange handler _useFlatScreen.onChange([this](){ if (_useFlatScreen) { diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 0edd629a01..353c10ee8a 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -46,8 +46,8 @@ const std::string tagToMatch) { properties::PropertyOwner* owner = prop->owner(); if (owner != nullptr) { - std::vector* tags = (std::vector*)owner->getTags(); - for (std::string currTag : *tags) { + std::vector tags = (std::vector)owner->tags(); + for (std::string currTag : tags) { if (tagToMatch.compare(currTag) == 0) { tagMatchOwner = owner; break; @@ -67,7 +67,7 @@ void applyRegularExpression(lua_State* L, std::regex regex, std::string groupName = "") { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; - bool isGroupMode = (groupName.compare("") != 0) ? true : false; + bool isGroupMode = (groupName.empty()) ? false : true; for (properties::Property* prop : properties) { // Check the regular expression for all properties From fcd2becd3480e670608e96971eaea0ad6510ebe0 Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 6 Apr 2017 12:21:40 -0600 Subject: [PATCH 08/34] Combined setPropertyValue* functions to combine single or group/tagged property operations --- src/scene/scene.cpp | 60 ++++----- src/scene/scene_lua.inl | 263 +++++++++++++++------------------------- 2 files changed, 120 insertions(+), 203 deletions(-) diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 44fbd504d6..f010b75987 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -651,55 +651,39 @@ scripting::LuaLibrary Scene::luaLibrary() { "setPropertyValue", &luascriptfunctions::property_setValue, "string, *", - "Sets all properties identified by the URI (with potential wildcards) in " - "the first argument. The second argument can be any type, but it has to " - "match the type that the property (or properties) expect." + "Sets all property(s) identified by the URI (with potential wildcards) " + "in the first argument. The second argument can be any type, but it has " + "to match the type that the property (or properties) expect. If the " + "first term (separated by '.') in the uri is bracketed with { }, then " + "this term is treated as a group tag name, and the function will " + "search through all property owners to find those that are tagged with " + "this group name, and set their property values accordingly." }, { "setPropertyValueRegex", &luascriptfunctions::property_setValueRegex, "string, *", - "Sets all properties that pass the regular expression in the first " - "argument. The second argument can be any type, but it has to match the " - "type of the properties that matched the regular expression. The regular " - "expression has to be of the ECMAScript grammar." + "Sets all property(s) that pass the regular expression in the first " + "argument. The second argument can be any type, but it has to match " + "the type of the properties that matched the regular expression. " + "The regular expression has to be of the ECMAScript grammar. If the " + "first term (separated by '.') in the uri is bracketed with { }, then " + "this term is treated as a group tag name, and the function will search " + "through all property owners to find those that are tagged with this " + "group name, and set their property values accordingly." }, { "setPropertyValueSingle", &luascriptfunctions::property_setValueSingle, "string, *", - "Sets a property identified by the URI in " - "the first argument. The second argument can be any type, but it has to " - "match the type that the property expects.", + "Sets all property(s) identified by the URI in the first argument to the " + "value passed in the second argument. The type of the second argument is " + "arbitrary, but it must agree with the type the denoted Property expects. " + "If the first term (separated by '.') in the uri is bracketed with { }, " + " then this term is treated as a group tag name, and the function will " + "search through all property owners to find those that are tagged with " + "this group name, and set their property values accordingly." }, - { - "setPropertyGroup", - &luascriptfunctions::property_setGroup, - "string, *", - "Sets all properties that belong to a tagged group AND match the " - "URI (with optional wildcards) in the first argument (group tag name is " - "given in place of property owner name). The second argument can be any " - "type, but it has to match the type that the property expects.", - }, - { - "setPropertyGroupSingle", - &luascriptfunctions::property_setGroupSingle, - "string, *", - "Sets all properties that belong to a tagged group AND match the " - "URI (requires exact match) in the first argument (group tag name is " - "given in place of property owner name). The second argument can be any " - "type, but it has to match the type that the property expects.", - }, - { - "setPropertyGroupRegex", - &luascriptfunctions::property_setGroupRegex, - "string, *", - "Sets all properties that belong to a tagged group AND match the " - "URI (allows regular expression syntax) in the first argument " - "(group tag name is given in place of property owner name). The second " - "argument can be any type, but it has to match the type that the " - "property expects.", - }, { "getPropertyValue", &luascriptfunctions::property_getValue, diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 353c10ee8a..81635f7c67 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -97,8 +97,21 @@ void applyRegularExpression(lua_State* L, std::regex regex, } } -std::string extractGroupNameFromUri(std::string command) { - return command.substr(0, command.find_first_of(".")); +bool doesUriContainGroupTag(const std::string command) { + std::string name = command.substr(0, command.find_first_of(".")); + if (name.front() == '{' && name.back() == '}') + return true; + else + return false; +} + +std::string extractGroupNameFromUri(const std::string command) { + if (doesUriContainGroupTag(command)) { + std::string name = command.substr(0, command.find_first_of(".")); + return name.substr(1, name.length() - 2); + } else { + return command; + } } std::string replaceUriGroupNameWith(std::string uri, std::string ownerName) { @@ -115,36 +128,15 @@ std::string extractUriWithoutGroupName(std::string uri) { namespace luascriptfunctions { -/** - * \ingroup LuaScripts - * setPropertyValueSingle(string, *): - * Sets the property identified by the URI in the first argument to the value passed to - * the second argument. The type of the second argument is arbitrary, but it must agree - * with the type the denoted Property expects - */ -int property_setValueSingle(lua_State* L) { +int setPropertyCall_single(properties::Property* prop, std::string uri, lua_State* L, + const int type) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; - - int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments); - - std::string uri = luaL_checkstring(L, -2); - const int type = lua_type(L, -1); - - properties::Property* prop = property(uri); - if (!prop) { - LERRORC("property_setValue", errorLocation(L) << "Property with URI '" - << uri << "' was not found"); - return 0; - } - - + if (type != prop->typeLua()) { LERRORC("property_setValue", errorLocation(L) << "Property '" << uri << "' does not accept input of type '" << luaTypeToString(type) << "'. Requested type: '" << luaTypeToString(prop->typeLua()) << "'"); - return 0; } else { prop->setLuaValue(L); @@ -159,149 +151,78 @@ int property_setValueSingle(lua_State* L) { /** * \ingroup LuaScripts - * setPropertyValueRegex(string, *): - * Sets all properties that pass the regular expression in the first argument. The second - * argument can be any type, but it has to match the type of the properties that matched - * the regular expression. The regular expression has to be of the ECMAScript grammar. -*/ -int property_setValueRegex(lua_State* L) { + * setPropertyValueSingle(string, *): + * Sets all property(s) identified by the URI in the first argument to the value passed + * in the second argument. The type of the second argument is arbitrary, but it must + * agree with the type the denoted Property expects. + * If the first term (separated by '.') in the uri is bracketed with { }, then this + * term is treated as a group tag name, and the function will search through all + * property owners to find those that are tagged with this group name, and set their + * property values accordingly. + */ +int property_setValueSingle(lua_State* L) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setValueRegex<", L, 2, nArguments); + SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments); - std::string regex = luaL_checkstring(L, -2); - try { - applyRegularExpression( - L, - std::regex(regex, std::regex_constants::optimize), - allProperties(), - lua_type(L, -1) - ); - } - catch (const std::regex_error& e) { - LERRORC("property_setValueRegex", "Malformed regular expression: '" - << regex << "'"); + std::string uri = luaL_checkstring(L, -2); + const int type = lua_type(L, -1); + + if (doesUriContainGroupTag(uri)) { + std::string tagToMatch = extractGroupNameFromUri(uri); + std::string pathRemainderToMatch = extractUriWithoutGroupName(uri); + for (properties::Property* prop : allProperties()) { + std::string propFullId = prop->fullyQualifiedIdentifier(); + //Look for a match in the uri with the group name (first term) removed + int propMatchLength = propFullId.length() - pathRemainderToMatch.length(); + + if (propMatchLength >= 0) { + std::string thisPropMatchId = propFullId.substr(propMatchLength); + //If remainder of uri matches (with group name removed), + if (pathRemainderToMatch.compare(thisPropMatchId) == 0) { + properties::PropertyOwner* matchingTaggedOwner + = findPropertyOwnerWithMatchingGroupTag(prop, tagToMatch); + if (matchingTaggedOwner != nullptr) { + setPropertyCall_single(prop, uri, L, type); + } + } + } + } + } else { + properties::Property* prop = property(uri); + if (!prop) { + LERRORC("property_setValue", errorLocation(L) << "Property with URI '" + << uri << "' was not found"); + return 0; + } + setPropertyCall_single(prop, uri, L, type); } return 0; } /** -* \ingroup LuaScripts -* setPropertyValue(string, *): -* Sets all properties identified by the URI (with potential wildcards) in the first -* argument. The second argument can be any type, but it has to match the type that the -* property (or properties) expect. -*/ + * \ingroup LuaScripts + * setPropertyValue(string, *): + * Sets all property(s) identified by the URI (with potential wildcards) in the first + * argument. The second argument can be any type, but it has to match the type that the + * property (or properties) expect. + * If the first term (separated by '.') in the uri is bracketed with { }, then this + * term is treated as a group tag name, and the function will search through all + * property owners to find those that are tagged with this group name, and set their + * property values accordingly. + */ int property_setValue(lua_State* L) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; - int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setValue", L, 2, nArguments); - - std::string regex = luaL_checkstring(L, -2); - - // Replace all wildcards * with the correct regex (.*) - size_t startPos = regex.find("*"); - while (startPos != std::string::npos) { - regex.replace(startPos, 1, "(.*)"); - startPos += 4; - - startPos = regex.find("*", startPos); - } - - - applyRegularExpression( - L, - std::regex(regex/*, std::regex_constants::optimize*/), - allProperties(), - lua_type(L, -1) - ); - - return 0; -} - -/** - * \ingroup LuaScripts - * setPropertyGroupSingle(string, *): - * Sets all properties that belong to a tagged group AND match the URI (requires exact - * match) in the first argument (group tag name is given in place of property owner - * name). The second argument can be any type, but it has to match the type that the - * property expects. - */ -int property_setGroupSingle(lua_State* L) { - using ghoul::lua::errorLocation; - using ghoul::lua::luaTypeToString; - - int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setGroupSingle", L, 2, nArguments); - - std::string uri = luaL_checkstring(L, -2); - const int type = lua_type(L, -1); - std::string tagToMatch = extractGroupNameFromUri(uri); - std::string pathRemainderToMatch = extractUriWithoutGroupName(uri); - - for (properties::Property* prop : allProperties()) { - std::string propFullId = prop->fullyQualifiedIdentifier(); - //Look for a match in the uri with the group name (first term) removed - int propMatchLength = propFullId.length() - pathRemainderToMatch.length(); - -if( propFullId.substr(0, 31).compare("MercuryTrail.renderable.enabled") == 0 ) - int type2 = 3; - - if (propMatchLength >= 0) { - std::string thisPropMatchId = propFullId.substr(propMatchLength); - //If remainder of uri matches (with group name removed), - if (pathRemainderToMatch.compare(thisPropMatchId) == 0) { - properties::PropertyOwner* matchingTaggedOwner - = findPropertyOwnerWithMatchingGroupTag(prop, tagToMatch); - if (matchingTaggedOwner != nullptr) { - if (type != prop->typeLua()) { - LERRORC("property_setValue", errorLocation(L) << "Property '" - << prop->guiName() << "' does not accept input of type '" - << luaTypeToString(type) << "'. Requested type: '" - << luaTypeToString(prop->typeLua()) << "'"); - continue; - } - else { - prop->setLuaValue(L); - //ensure properties are synced over parallel connection - std::string value; - prop->getStringValue(value); - //OsEng.parallelConnection().scriptMessage( - // prop->fullyQualifiedIdentifier(), value); - //break; - } - } - } - } - } - - return 0; -} - -/** - * \ingroup LuaScripts - * setPropertyGroup(string, *): - * Sets all properties that belong to a tagged group AND match the URI (with optional - * wildcards) in the first argument (group tag name is given in place of property owner - * name). The second argument can be any type, but it has to match the type that the - * property expects. - */ - -int property_setGroup(lua_State* L) { - using ghoul::lua::errorLocation; - using ghoul::lua::luaTypeToString; - int nArguments = lua_gettop(L); SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 2, nArguments); - std::string regex = luaL_checkstring(L, -2); - std::string groupName = extractGroupNameFromUri(regex); + std::string groupName; // Replace all wildcards * with the correct regex (.*) size_t startPos = regex.find("*"); @@ -310,9 +231,14 @@ int property_setGroup(lua_State* L) { startPos += 4; startPos = regex.find("*", startPos); } - //Remove group name from start of regex and replace with '.*' - regex = replaceUriGroupNameWith(regex, ".*"); - + + if (doesUriContainGroupTag(regex)) { + groupName = extractGroupNameFromUri(regex); + std::string pathRemainderToMatch = extractUriWithoutGroupName(regex); + //Remove group name from start of regex and replace with '.*' + regex = replaceUriGroupNameWith(regex, ".*"); + } + applyRegularExpression( L, std::regex(regex/*, std::regex_constants::optimize*/), @@ -326,24 +252,31 @@ int property_setGroup(lua_State* L) { /** * \ingroup LuaScripts - * setPropertyGroupRegex(string, *): - * Sets all properties that belong to a tagged group AND match the URI (allows regular - * expression syntax) in the first argument (group tag name is given in place of property - * owner name). The second argument can be any type, but it has to match the type that - * the property expects. + * setPropertyValueRegex(string, *): + * Sets all property(s) that pass the regular expression in the first argument. The second + * argument can be any type, but it has to match the type of the properties that matched + * the regular expression. The regular expression has to be of the ECMAScript grammar. + * If the first term (separated by '.') in the uri is bracketed with { }, then this + * term is treated as a group tag name, and the function will search through all + * property owners to find those that are tagged with this group name, and set their + * property values accordingly. */ -int property_setGroupRegex(lua_State* L) { +int property_setValueRegex(lua_State* L) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; int nArguments = lua_gettop(L); - SCRIPT_CHECK_ARGUMENTS("property_setGroupRegex<", L, 2, nArguments); - + SCRIPT_CHECK_ARGUMENTS("property_setValueRegex<", L, 2, nArguments); std::string regex = luaL_checkstring(L, -2); - std::string groupName = extractGroupNameFromUri(regex); - //Remove group name from start of regex and replace with '.*' - regex = replaceUriGroupNameWith(regex, ".*"); - + std::string groupName; + + if (doesUriContainGroupTag(regex)) { + groupName = extractGroupNameFromUri(regex); + std::string pathRemainderToMatch = extractUriWithoutGroupName(regex); + //Remove group name from start of regex and replace with '.*' + regex = replaceUriGroupNameWith(regex, ".*"); + } + try { applyRegularExpression( L, From d66561a1d31c329b6d4df705a1ab412eda5fed91 Mon Sep 17 00:00:00 2001 From: GPayne Date: Mon, 10 Apr 2017 15:05:06 -0600 Subject: [PATCH 09/34] Added option for single or multiple tags in a scenegraph node --- src/rendering/renderable.cpp | 21 +++++++++++++++++---- src/rendering/screenspacerenderable.cpp | 19 +++++++++++++++---- src/scene/scenegraphnode.cpp | 19 +++++++++++++++---- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 5a90dbb990..6b67fc9ef0 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -41,7 +41,7 @@ namespace { const char* keyStart = "StartTime"; const char* keyEnd = "EndTime"; const char* KeyType = "Type"; - const char* keyTag = "Tag"; + const char* KeyTag = "Tag"; } namespace openspace { @@ -112,10 +112,23 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) dictionary.getValue(keyStart, _startTime); dictionary.getValue(keyEnd, _endTime); + std::string tagName; - dictionary.getValue(keyTag, tagName); - if (! tagName.empty()) - addTag(tagName); + ghoul::Dictionary tagNames; + if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagName); + if (! tagName.empty()) + addTag(tagName); + } else if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagNames); + std::vector keys = tagNames.keys(); + for (const std::string key : keys) { + tagNames.getValue(key, tagName); + if (! tagName.empty()) + addTag(tagName); + } + } + if (_startTime != "" && _endTime != "") { _hasTimeInterval = true; } diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index 2f3ca4cc90..7fb525bfe0 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -47,7 +47,7 @@ namespace { const char* KeyScale = "Scale"; const char* KeyDepth = "Depth"; const char* KeyAlpha = "Alpha"; - const char* keyTag = "Tag"; + const char* KeyTag = "Tag"; const float PlaneDepth = -2.f; } @@ -147,9 +147,20 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary dictionary.getValue(KeyAlpha, _alpha); std::string tagName; - dictionary.getValue(keyTag, tagName); - if (! tagName.empty()) - addTag(tagName); + ghoul::Dictionary tagNames; + if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagName); + if (! tagName.empty()) + addTag(tagName); + } else if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagNames); + std::vector keys = tagNames.keys(); + for (const std::string key : keys) { + tagNames.getValue(key, tagName); + if (! tagName.empty()) + addTag(tagName); + } + } // Setting spherical/euclidean onchange handler _useFlatScreen.onChange([this](){ diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index a039c20a07..741c3d86c5 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -141,10 +141,21 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di } if (dictionary.hasKey(KeyTag)) { - std::string tagString; - dictionary.getValue(KeyTag, tagString); - result->addTag(tagString); - LDEBUG("Successfully added tag for '" << result->name() << "'"); + std::string tagName; + ghoul::Dictionary tagNames; + if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagName); + if (! tagName.empty()) + result->addTag(tagName); + } else if (dictionary.hasKeyAndValue(KeyTag)) { + dictionary.getValue(KeyTag, tagNames); + std::vector keys = tagNames.keys(); + for (const std::string key : keys) { + tagNames.getValue(key, tagName); + if (! tagName.empty()) + result->addTag(tagName); + } + } } LDEBUG("Successfully created SceneGraphNode '" From 665c9035a5937d75e058da3d466fbff274b5a2af Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 13 Apr 2017 11:52:29 -0400 Subject: [PATCH 10/34] Make RenderablePlanet not crash if the nighttextures are not present --- modules/space/rendering/renderableplanet.cpp | 17 +++++------------ modules/space/rendering/simplespheregeometry.h | 1 - 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/modules/space/rendering/renderableplanet.cpp b/modules/space/rendering/renderableplanet.cpp index 17bdd3c71d..cd77cff9a9 100644 --- a/modules/space/rendering/renderableplanet.cpp +++ b/modules/space/rendering/renderableplanet.cpp @@ -292,16 +292,7 @@ bool RenderablePlanet::initialize() { LERROR(ss.str()); } - loadTexture(); - - while ((err = glGetError()) != GL_NO_ERROR) { - const GLubyte * errString = gluErrorString(err); - std::stringstream ss; - ss << "Error loading textures. OpenGL error: " << errString << std::endl; - LERROR(ss.str()); - } - - _geometry->initialize(this); + _geometry->initialize(this); _programObject->deactivate(); @@ -309,6 +300,8 @@ bool RenderablePlanet::initialize() { const GLubyte * errString = gluErrorString(err); LERROR("Shader Programs Creation. OpenGL error: " << errString); } + + loadTexture(); return isReady(); } @@ -394,13 +387,13 @@ void RenderablePlanet::render(const RenderData& data) { _programObject->setUniform("texture1", dayUnit); // Bind possible night texture - if (_hasNightTexture) { + if (_hasNightTexture && _nightTexture) { nightUnit.activate(); _nightTexture->bind(); _programObject->setUniform("nightTex", nightUnit); } - if (_hasHeightTexture) { + if (_hasHeightTexture && _heightMapTexture) { heightUnit.activate(); _heightMapTexture->bind(); _programObject->setUniform("heightTex", heightUnit); diff --git a/modules/space/rendering/simplespheregeometry.h b/modules/space/rendering/simplespheregeometry.h index 35740746df..3604050944 100644 --- a/modules/space/rendering/simplespheregeometry.h +++ b/modules/space/rendering/simplespheregeometry.h @@ -46,7 +46,6 @@ public: bool initialize(Renderable* parent) override; void deinitialize() override; void render() override; - PowerScaledSphere* _planet; private: void createSphere(); From bef3f2b65217a339fb950023faaf22d32b66109d Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 13 Apr 2017 11:02:54 -0600 Subject: [PATCH 11/34] Added tags to solar system planets for grouping functionality, and added scale property to some planets --- data/scene/earth/earth.mod | 3 ++- data/scene/jupiter/jupiter/jupiter.mod | 3 ++- data/scene/mars/mars.mod | 7 ++++++- data/scene/mercury/mercury.mod | 3 ++- data/scene/neptune/neptune.mod | 11 ++++++++--- data/scene/saturn/saturn/saturn.mod | 3 ++- data/scene/uranus/uranus.mod | 9 +++++++-- data/scene/venus/venus.mod | 17 ++++++++++++----- 8 files changed, 41 insertions(+), 15 deletions(-) diff --git a/data/scene/earth/earth.mod b/data/scene/earth/earth.mod index 7722adb042..b0350ef340 100644 --- a/data/scene/earth/earth.mod +++ b/data/scene/earth/earth.mod @@ -49,6 +49,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", @@ -79,7 +80,7 @@ return { -- SampleInterval = 3600 Period = 365.242, Resolution = 1000, - Tag = "defaultTrails" + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} }, GuiName = "/Solar/EarthTrail", }, diff --git a/data/scene/jupiter/jupiter/jupiter.mod b/data/scene/jupiter/jupiter/jupiter.mod index e4bbb0cd73..087eef55c5 100644 --- a/data/scene/jupiter/jupiter/jupiter.mod +++ b/data/scene/jupiter/jupiter/jupiter.mod @@ -35,6 +35,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Translation = { Type = "StaticTranslation", @@ -66,6 +67,6 @@ return { Period = 4330.595, Resolution = 1000, }, - Tag = "defaultTrails" + Tag = "planetTrail_solarSystem" } } diff --git a/data/scene/mars/mars.mod b/data/scene/mars/mars.mod index afbfafd2ec..0388c18eda 100644 --- a/data/scene/mars/mars.mod +++ b/data/scene/mars/mars.mod @@ -35,12 +35,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_MARS", DestinationFrame = "GALACTIC", }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, } }, -- MarsTrail module @@ -57,7 +62,7 @@ return { Color = { 0.814, 0.305, 0.220 }, Period = 686.973, Resolution = 1000, - Tag = "defaultTrails" + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } diff --git a/data/scene/mercury/mercury.mod b/data/scene/mercury/mercury.mod index 7902252625..26666120e0 100644 --- a/data/scene/mercury/mercury.mod +++ b/data/scene/mercury/mercury.mod @@ -37,6 +37,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", @@ -63,7 +64,7 @@ return { Color = {0.6, 0.5, 0.5 }, Period = 87.968, Resolution = 100, - Tag = "defaultTrails" + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } diff --git a/data/scene/neptune/neptune.mod b/data/scene/neptune/neptune.mod index d25d973ab7..b02dd189b2 100644 --- a/data/scene/neptune/neptune.mod +++ b/data/scene/neptune/neptune.mod @@ -29,14 +29,19 @@ return { Textures = { Type = "simple", Color = "textures/neptune.jpg", - }, + } }, - Translation = { + Tag = "planet_solarSystem", + Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_NEPTUNE", DestinationFrame = "GALACTIC" }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, } }, -- NeptuneTrail module @@ -53,7 +58,7 @@ return { Color = {0.2, 0.5, 1.0 }, Period = 60200, Resolution = 1000, - Tag = "defaultTrails" + Tag = "planetTrail_solarSystem" } } } diff --git a/data/scene/saturn/saturn/saturn.mod b/data/scene/saturn/saturn/saturn.mod index 7aff69281e..fe85224aca 100644 --- a/data/scene/saturn/saturn/saturn.mod +++ b/data/scene/saturn/saturn/saturn.mod @@ -39,6 +39,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Rotation = { Type = "SpiceRotation", @@ -77,7 +78,7 @@ return { Color = {0.85,0.75,0.51 }, Period = 10746.94, Resolution = 1000, - Tag = "defaultTrails" + Tag = "planetTrail_solarSystem" }, } } diff --git a/data/scene/uranus/uranus.mod b/data/scene/uranus/uranus.mod index 8f4ce17384..43de1dd2ab 100644 --- a/data/scene/uranus/uranus.mod +++ b/data/scene/uranus/uranus.mod @@ -36,12 +36,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_URANUS", DestinationFrame = "ECLIPJ2000", - } + }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, }, }, @@ -59,7 +64,7 @@ return { Color = {0.60, 0.95, 1.00 }, Period = 30588.740, Resolution = 1000, - Tag = "defaultTrails" + Tag = "planetTrail_solarSystem" } } } diff --git a/data/scene/venus/venus.mod b/data/scene/venus/venus.mod index 1a187b2dff..eccce1786f 100644 --- a/data/scene/venus/venus.mod +++ b/data/scene/venus/venus.mod @@ -36,10 +36,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, - Rotation = { - Type = "SpiceRotation", - Frame = "IAU_VENUS", - Reference = "GALACTIC" + Tag = {"planet_solarSystem", "planet_terrestrial"}, + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "IAU_VENUS", + DestinationFrame = "GALACTIC" + }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, }, }, @@ -57,7 +64,7 @@ return { Color = { 1.0, 0.5, 0.2 }, Period = 224.695, Resolution = 1000, - Tag = "defaultTrails" + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } From 7a7fef239c4bd1b49f88025500b1f502cc19a82d Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 13 Apr 2017 11:12:26 -0600 Subject: [PATCH 12/34] Made changes according to pull request feedback --- include/openspace/properties/property.h | 1 - include/openspace/properties/propertyowner.h | 2 +- src/properties/propertyowner.cpp | 4 +- src/rendering/renderable.cpp | 19 +++--- src/rendering/screenspacerenderable.cpp | 19 +++--- src/scene/scene.cpp | 44 +++++++------- src/scene/scene_lua.inl | 63 ++++++++++---------- src/scene/scenegraphnode.cpp | 25 ++++---- 8 files changed, 88 insertions(+), 89 deletions(-) diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 1db90523fe..54e7a07532 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -383,7 +383,6 @@ protected: /// The callback function that will be invoked whenever the encapsulated value changes std::function _onChangeCallback; - }; } // namespace properties diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index 8795fbffc7..4fdec7bb12 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -212,7 +212,7 @@ public: * trying to find a match for a desired batch operation on Properties. * \return Pointer to vector of string tags that were assigned to the Property */ - const std::vector tags() const; + std::vector tags() const; /** * Adds a tag to the Property's list of assigned tags. Tags are useful for creating diff --git a/src/properties/propertyowner.cpp b/src/properties/propertyowner.cpp index fe27cc0503..2e57409394 100644 --- a/src/properties/propertyowner.cpp +++ b/src/properties/propertyowner.cpp @@ -324,12 +324,12 @@ const std::string& PropertyOwner::name() const { return _name; } -const std::vector PropertyOwner::tags() const { +std::vector PropertyOwner::tags() const { return _tags; } void PropertyOwner::addTag(std::string tag) { - _tags.push_back(tag); + _tags.push_back(std::move(tag)); } } // namespace properties diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 6b67fc9ef0..7091917d7c 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -113,19 +113,18 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) dictionary.getValue(keyStart, _startTime); dictionary.getValue(keyEnd, _endTime); - std::string tagName; - ghoul::Dictionary tagNames; if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagName); - if (! tagName.empty()) - addTag(tagName); + std::string tagName = dictionary.value(KeyTag); + if (!tagName.empty()) + addTag(std::move(tagName)); } else if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagNames); + ghoul::Dictionary tagNames = dictionary.value(KeyTag); std::vector keys = tagNames.keys(); - for (const std::string key : keys) { - tagNames.getValue(key, tagName); - if (! tagName.empty()) - addTag(tagName); + std::string tagName; + for (const std::string& key : keys) { + tagName = tagNames.value(key); + if (!tagName.empty()) + addTag(std::move(tagName)); } } diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index 7fb525bfe0..7d9d841cd7 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -146,19 +146,18 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary dictionary.getValue(KeyDepth, _depth); dictionary.getValue(KeyAlpha, _alpha); - std::string tagName; - ghoul::Dictionary tagNames; if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagName); - if (! tagName.empty()) - addTag(tagName); + std::string tagName = dictionary.value(KeyTag); + if (!tagName.empty()) + addTag(std::move(tagName)); } else if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagNames); + ghoul::Dictionary tagNames = dictionary.value(KeyTag); std::vector keys = tagNames.keys(); - for (const std::string key : keys) { - tagNames.getValue(key, tagName); - if (! tagName.empty()) - addTag(tagName); + std::string tagName; + for (const std::string& key : keys) { + tagName = tagNames.value(key); + if (!tagName.empty()) + addTag(std::move(tagName)); } } diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index f010b75987..4fcef9214f 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -651,38 +651,38 @@ scripting::LuaLibrary Scene::luaLibrary() { "setPropertyValue", &luascriptfunctions::property_setValue, "string, *", - "Sets all property(s) identified by the URI (with potential wildcards) " - "in the first argument. The second argument can be any type, but it has " - "to match the type that the property (or properties) expect. If the " - "first term (separated by '.') in the uri is bracketed with { }, then " - "this term is treated as a group tag name, and the function will " - "search through all property owners to find those that are tagged with " - "this group name, and set their property values accordingly." + "Sets all property(s) identified by the URI (with potential wildcards) " + "in the first argument. The second argument can be any type, but it has " + "to match the type that the property (or properties) expect. If the " + "first term (separated by '.') in the uri is bracketed with { }, then " + "this term is treated as a group tag name, and the function will " + "search through all property owners to find those that are tagged with " + "this group name, and set their property values accordingly." }, { "setPropertyValueRegex", &luascriptfunctions::property_setValueRegex, "string, *", - "Sets all property(s) that pass the regular expression in the first " - "argument. The second argument can be any type, but it has to match " - "the type of the properties that matched the regular expression. " - "The regular expression has to be of the ECMAScript grammar. If the " - "first term (separated by '.') in the uri is bracketed with { }, then " - "this term is treated as a group tag name, and the function will search " - "through all property owners to find those that are tagged with this " - "group name, and set their property values accordingly." + "Sets all property(s) that pass the regular expression in the first " + "argument. The second argument can be any type, but it has to match " + "the type of the properties that matched the regular expression. " + "The regular expression has to be of the ECMAScript grammar. If the " + "first term (separated by '.') in the uri is bracketed with { }, then " + "this term is treated as a group tag name, and the function will search " + "through all property owners to find those that are tagged with this " + "group name, and set their property values accordingly." }, { "setPropertyValueSingle", &luascriptfunctions::property_setValueSingle, "string, *", - "Sets all property(s) identified by the URI in the first argument to the " - "value passed in the second argument. The type of the second argument is " - "arbitrary, but it must agree with the type the denoted Property expects. " - "If the first term (separated by '.') in the uri is bracketed with { }, " - " then this term is treated as a group tag name, and the function will " - "search through all property owners to find those that are tagged with " - "this group name, and set their property values accordingly." + "Sets all property(s) identified by the URI in the first argument to the " + "value passed in the second argument. The type of the second argument is " + "arbitrary, but it must agree with the type the denoted Property expects." + " If the first term (separated by '.') in the uri is bracketed with { }, " + " then this term is treated as a group tag name, and the function will " + "search through all property owners to find those that are tagged with " + "this group name, and set their property values accordingly." }, { "getPropertyValue", diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 81635f7c67..b89eb561c7 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -41,13 +41,14 @@ void executePropertySet(properties::Property* prop, lua_State* L) { template properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, -const std::string tagToMatch) { + const std::string& tagToMatch) +{ properties::PropertyOwner* tagMatchOwner = nullptr; properties::PropertyOwner* owner = prop->owner(); - if (owner != nullptr) { - std::vector tags = (std::vector)owner->tags(); - for (std::string currTag : tags) { + if (owner) { + std::vector tags = owner->tags(); + for (std::string& currTag : tags) { if (tagToMatch.compare(currTag) == 0) { tagMatchOwner = owner; break; @@ -64,10 +65,11 @@ const std::string tagToMatch) { void applyRegularExpression(lua_State* L, std::regex regex, std::vector properties, int type, - std::string groupName = "") { + std::string groupName = "") +{ using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; - bool isGroupMode = (groupName.empty()) ? false : true; + bool isGroupMode = !groupName.empty(); for (properties::Property* prop : properties) { // Check the regular expression for all properties @@ -77,10 +79,14 @@ void applyRegularExpression(lua_State* L, std::regex regex, // If the fully qualified id matches the regular expression, we queue the // value change if the types agree if (isGroupMode) { - properties::PropertyOwner* matchingTaggedOwner = findPropertyOwnerWithMatchingGroupTag(prop, - groupName); - if (matchingTaggedOwner == nullptr) + properties::PropertyOwner* matchingTaggedOwner = + findPropertyOwnerWithMatchingGroupTag( + prop, + groupName + ); + if (!matchingTaggedOwner) { continue; + } } if (type != prop->typeLua()) { @@ -97,24 +103,19 @@ void applyRegularExpression(lua_State* L, std::regex regex, } } -bool doesUriContainGroupTag(const std::string command) { +//Checks to see if URI contains a group tag (with { } around the first term). If so, +// returns true and sets groupName with the tag +bool doesUriContainGroupTag(const std::string& command, std::string& groupName) { std::string name = command.substr(0, command.find_first_of(".")); - if (name.front() == '{' && name.back() == '}') + if (name.front() == '{' && name.back() == '}') { + groupName = name.substr(1, name.length() - 2); return true; - else - return false; -} - -std::string extractGroupNameFromUri(const std::string command) { - if (doesUriContainGroupTag(command)) { - std::string name = command.substr(0, command.find_first_of(".")); - return name.substr(1, name.length() - 2); } else { - return command; + return false; } } -std::string replaceUriGroupNameWith(std::string uri, std::string ownerName) { +std::string replaceUriWithGroupName(std::string uri, std::string ownerName) { size_t pos = uri.find_first_of("."); return ownerName + "." + uri.substr(pos); } @@ -123,13 +124,15 @@ std::string extractUriWithoutGroupName(std::string uri) { size_t pos = uri.find_first_of("."); return uri.substr(pos); } + } namespace luascriptfunctions { int setPropertyCall_single(properties::Property* prop, std::string uri, lua_State* L, - const int type) { + const int type) +{ using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; @@ -169,9 +172,9 @@ int property_setValueSingle(lua_State* L) { std::string uri = luaL_checkstring(L, -2); const int type = lua_type(L, -1); + std::string tagToMatch; - if (doesUriContainGroupTag(uri)) { - std::string tagToMatch = extractGroupNameFromUri(uri); + if (doesUriContainGroupTag(uri, tagToMatch)) { std::string pathRemainderToMatch = extractUriWithoutGroupName(uri); for (properties::Property* prop : allProperties()) { std::string propFullId = prop->fullyQualifiedIdentifier(); @@ -184,7 +187,7 @@ int property_setValueSingle(lua_State* L) { if (pathRemainderToMatch.compare(thisPropMatchId) == 0) { properties::PropertyOwner* matchingTaggedOwner = findPropertyOwnerWithMatchingGroupTag(prop, tagToMatch); - if (matchingTaggedOwner != nullptr) { + if (matchingTaggedOwner) { setPropertyCall_single(prop, uri, L, type); } } @@ -232,11 +235,10 @@ int property_setValue(lua_State* L) { startPos = regex.find("*", startPos); } - if (doesUriContainGroupTag(regex)) { - groupName = extractGroupNameFromUri(regex); + if (doesUriContainGroupTag(regex, groupName)) { std::string pathRemainderToMatch = extractUriWithoutGroupName(regex); //Remove group name from start of regex and replace with '.*' - regex = replaceUriGroupNameWith(regex, ".*"); + regex = replaceUriWithGroupName(regex, ".*"); } applyRegularExpression( @@ -270,11 +272,10 @@ int property_setValueRegex(lua_State* L) { std::string regex = luaL_checkstring(L, -2); std::string groupName; - if (doesUriContainGroupTag(regex)) { - groupName = extractGroupNameFromUri(regex); + if (doesUriContainGroupTag(regex, groupName)) { std::string pathRemainderToMatch = extractUriWithoutGroupName(regex); //Remove group name from start of regex and replace with '.*' - regex = replaceUriGroupNameWith(regex, ".*"); + regex = replaceUriWithGroupName(regex, ".*"); } try { diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 741c3d86c5..a1c9d21297 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -141,20 +141,21 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di } if (dictionary.hasKey(KeyTag)) { - std::string tagName; - ghoul::Dictionary tagNames; if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagName); - if (! tagName.empty()) - result->addTag(tagName); + std::string tagName = dictionary.value(KeyTag); + if (!tagName.empty()) { + result->addTag(std::move(tagName)); + } } else if (dictionary.hasKeyAndValue(KeyTag)) { - dictionary.getValue(KeyTag, tagNames); - std::vector keys = tagNames.keys(); - for (const std::string key : keys) { - tagNames.getValue(key, tagName); - if (! tagName.empty()) - result->addTag(tagName); - } + ghoul::Dictionary tagNames = dictionary.value(KeyTag); + std::vector keys = tagNames.keys(); + std::string tagName; + for (const std::string& key : keys) { + tagName = tagNames.value(key); + if (!tagName.empty()) { + result->addTag(std::move(tagName)); + } + } } } From 5589de995b475521a980f81d9e289a6e102c9633 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Thu, 13 Apr 2017 23:16:00 +0200 Subject: [PATCH 13/34] Feature/domecasting (#288) * Improve dome casting feature. Add basic GUI for domecasting. * Reenable remote scripting from Lua console. Add more settings and debug information for domecasting. * Do not try to reconnect to parallel connection forever * Fix interpolation bug for dome casting with globe browsing interaction mode * Show parallel connection properties in correct GUI * Fix bug for dome casting with globe browsing interaction mode. Add property for time tolerance. * Update header file * Clean up dome casting code * Remove obsolete lua functions from ParallelConnection. --- .../interaction/interactionhandler.h | 5 + .../openspace/interaction/interactionmode.h | 7 + include/openspace/interaction/luaconsole.h | 2 +- include/openspace/network/messagestructures.h | 62 ++-- .../openspace/network/parallelconnection.h | 39 ++- include/openspace/scene/scenegraphnode.h | 5 + include/openspace/util/timemanager.h | 3 + modules/onscreengui/CMakeLists.txt | 2 + modules/onscreengui/include/gui.h | 2 + .../include/guiparallelcomponent.h | 51 ++++ modules/onscreengui/onscreenguimodule.cpp | 4 +- modules/onscreengui/src/gui.cpp | 13 +- .../onscreengui/src/guiparallelcomponent.cpp | 191 ++++++++++++ src/engine/openspaceengine.cpp | 10 +- src/interaction/interactionhandler.cpp | 23 +- src/interaction/interactionmode.cpp | 66 +++- src/interaction/luaconsole.cpp | 25 +- src/network/parallelconnection.cpp | 287 +++++++++--------- src/network/parallelconnection_lua.inl | 138 +-------- src/scene/scenegraphnode.cpp | 20 +- src/util/timemanager.cpp | 24 +- 21 files changed, 637 insertions(+), 342 deletions(-) create mode 100644 modules/onscreengui/include/guiparallelcomponent.h create mode 100644 modules/onscreengui/src/guiparallelcomponent.cpp diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 34c398186c..81845fff2c 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -65,6 +65,7 @@ public: // Interaction mode setters void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict); void setInteractionMode(const std::string& interactionModeKey); + InteractionMode* interactionMode(); void goToChunk(int x, int y, int level); void goToGeo(double latitude, double longitude); @@ -72,7 +73,9 @@ public: void resetKeyBindings(); void addKeyframe(const datamessagestructures::CameraKeyframe &kf); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); + const std::vector& keyframes() const; void bindKeyLocal( Key key, @@ -96,6 +99,8 @@ public: // Accessors ghoul::Dictionary getCameraStateDictionary(); SceneGraphNode* const focusNode() const; + glm::dvec3 focusNodeToCameraVector() const; + glm::quat focusNodeToCameraRotation() const; Camera* const camera() const; const InputState& inputState() const; diff --git a/include/openspace/interaction/interactionmode.h b/include/openspace/interaction/interactionmode.h index ae9efa3be2..0698e2992e 100644 --- a/include/openspace/interaction/interactionmode.h +++ b/include/openspace/interaction/interactionmode.h @@ -82,9 +82,12 @@ namespace interaction { // Mutators void addKeyframe(const datamessagestructures::CameraKeyframe &kf); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); void clearOldKeyframes(); + static bool compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b); + // Accessors const std::list >& getPressedKeys() const; const std::list& getPressedMouseButtons() const; @@ -119,6 +122,7 @@ public: // Accessors SceneGraphNode* focusNode(); Interpolator& rotateToFocusNodeInterpolator(); + virtual bool followingNodeRotation() const = 0; virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime) = 0; virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime) = 0; @@ -195,6 +199,7 @@ public: virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; private: std::vector _keyframes; @@ -245,6 +250,7 @@ public: virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; protected: //void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); @@ -260,6 +266,7 @@ public: virtual void setFocusNode(SceneGraphNode* focusNode); //virtual void update(Camera& camera, const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED void goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection); diff --git a/include/openspace/interaction/luaconsole.h b/include/openspace/interaction/luaconsole.h index 119134e7e3..77beaf3109 100644 --- a/include/openspace/interaction/luaconsole.h +++ b/include/openspace/interaction/luaconsole.h @@ -53,7 +53,7 @@ private: void addToCommand(std::string c); properties::BoolProperty _isVisible; - bool _remoteScripting; + properties::BoolProperty _remoteScripting; size_t _inputPosition; std::vector _commandsHistory; diff --git a/include/openspace/network/messagestructures.h b/include/openspace/network/messagestructures.h index 5f85c57bcb..ee2ffc71a9 100644 --- a/include/openspace/network/messagestructures.h +++ b/include/openspace/network/messagestructures.h @@ -51,16 +51,28 @@ struct CameraKeyframe { glm::dvec3 _position; glm::dquat _rotation; + bool _followNodeRotation; + std::string _focusNode; + double _timestamp; void serialize(std::vector &buffer){ - //add position + // Add position buffer.insert(buffer.end(), reinterpret_cast(&_position), reinterpret_cast(&_position) + sizeof(_position)); - //add orientation + // Add orientation buffer.insert(buffer.end(), reinterpret_cast(&_rotation), reinterpret_cast(&_rotation) + sizeof(_rotation)); - - //add timestamp + + // Follow focus node rotation? + buffer.insert(buffer.end(), reinterpret_cast(&_followNodeRotation), reinterpret_cast(&_followNodeRotation) + sizeof(_followNodeRotation)); + + int nodeNameLength = _focusNode.size(); + + // Add focus node + buffer.insert(buffer.end(), reinterpret_cast(&nodeNameLength), reinterpret_cast(&nodeNameLength) + sizeof(nodeNameLength)); + buffer.insert(buffer.end(), _focusNode.data(), _focusNode.data() + nodeNameLength); + + // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; @@ -68,17 +80,31 @@ struct CameraKeyframe { int offset = 0; int size = 0; - //position + // Position size = sizeof(_position); memcpy(&_position, buffer.data() + offset, size); offset += size; - - //orientation + + // Orientation size = sizeof(_rotation); memcpy(&_rotation, buffer.data() + offset, size); offset += size; + + // Follow focus node rotation? + size = sizeof(_followNodeRotation); + memcpy(&_followNodeRotation, buffer.data() + offset, size); + offset += size; + + // Focus node + int nodeNameLength; + size = sizeof(int); + memcpy(&nodeNameLength, buffer.data() + offset, size); + offset += size; + size = nodeNameLength; + _focusNode = std::string(buffer.data() + offset, buffer.data() + offset + size); + offset += size; - //timestamp + // Timestamp size = sizeof(_timestamp); memcpy(&_timestamp, buffer.data() + offset, size); }; @@ -97,19 +123,19 @@ struct TimeKeyframe { double _timestamp; void serialize(std::vector &buffer){ - //add current time + // Add current time buffer.insert(buffer.end(), reinterpret_cast(&_time), reinterpret_cast(&_time) + sizeof(_time)); - //add delta time + // Add delta time buffer.insert(buffer.end(), reinterpret_cast(&_dt), reinterpret_cast(&_dt) + sizeof(_dt)); - //add wether time is paused or not + // Add whether time is paused or not buffer.insert(buffer.end(), reinterpret_cast(&_paused), reinterpret_cast(&_paused) + sizeof(_paused)); - //add wether a time jump is necessary (recompute paths etc) + // Add whether a time jump is necessary (recompute paths etc) buffer.insert(buffer.end(), reinterpret_cast(&_requiresTimeJump), reinterpret_cast(&_requiresTimeJump) + sizeof(_requiresTimeJump)); - //add timestamp + // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; @@ -117,27 +143,27 @@ struct TimeKeyframe { int offset = 0; int size = 0; - //current time + // Current time size = sizeof(_time); memcpy(&_time, buffer.data() + offset, size); offset += size; - //delta time + // Delta time size = sizeof(_dt); memcpy(&_dt, buffer.data() + offset, size); offset += size; - //is time paused? + // Is time paused? size = sizeof(_paused); memcpy(&_paused, buffer.data() + offset, size); offset += sizeof(_paused); - //is a time jump required? + // Is a time jump required? size = sizeof(_requiresTimeJump); memcpy(&_requiresTimeJump, buffer.data() + offset, size); offset += size; - // timestamp + // Timestamp size = sizeof(_timestamp); memcpy(&_timestamp, buffer.data() + offset, size); offset += size; diff --git a/include/openspace/network/parallelconnection.h b/include/openspace/network/parallelconnection.h index 8b43662206..db3d000413 100644 --- a/include/openspace/network/parallelconnection.h +++ b/include/openspace/network/parallelconnection.h @@ -27,6 +27,9 @@ //openspace includes #include +#include +#include +#include //glm includes #include @@ -57,7 +60,7 @@ struct addrinfo; namespace openspace { -class ParallelConnection { +class ParallelConnection : public properties::PropertyOwner { public: enum class Status : uint32_t { Disconnected = 0, @@ -99,17 +102,21 @@ class ParallelConnection { ParallelConnection(); ~ParallelConnection(); void clientConnect(); - void setPort(const std::string &port); - void setAddress(const std::string &address); - void setName(const std::string& name); + void setPort(std::string port); + void setAddress(std::string address); + void setName(std::string name); bool isHost(); const std::string& hostName(); - void requestHostship(const std::string &password); + void requestHostship(); void resignHostship(); - void setPassword(const std::string &password); + void setPassword(std::string password); + void setHostPassword(std::string hostPassword); void signalDisconnect(); void preSynchronization(); - void sendScript(const std::string& script); + void sendScript(std::string script); + void resetTimeOffset(); + double latencyStandardDeviation() const; + double timeTolerance() const; /** * Returns the Lua library that contains all Lua functions available to affect the @@ -145,7 +152,6 @@ private: void connectionStatusMessageReceived(const std::vector& messageContent); void nConnectionsMessageReceived(const std::vector& messageContent); - void broadcast(); void sendCameraKeyframe(); void sendTimeKeyframe(); @@ -158,10 +164,18 @@ private: double calculateBufferedKeyframeTime(double originalTime); - uint32_t _passCode; - std::string _port; - std::string _address; - std::string _name; + properties::StringProperty _password; + properties::StringProperty _hostPassword; + properties::StringProperty _port; + properties::StringProperty _address; + properties::StringProperty _name; + properties::FloatProperty _bufferTime; + properties::FloatProperty _timeKeyframeInterval; + properties::FloatProperty _cameraKeyframeInterval; + properties::FloatProperty _timeTolerance; + + double _lastTimeKeyframeTimestamp; + double _lastCameraKeyframeTimestamp; _SOCKET _clientSocket; @@ -191,7 +205,6 @@ private: double _initialTimeDiff; std::unique_ptr _connectionThread; - std::unique_ptr _broadcastThread; std::unique_ptr _sendThread; std::unique_ptr _listenThread; std::unique_ptr _handlerThread; diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index 071ae7403f..66ffd8738b 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -99,6 +99,8 @@ public: glm::dvec3 worldPosition() const; const glm::dmat3& worldRotationMatrix() const; + glm::dmat4 modelTransform() const; + glm::dmat4 inverseModelTransform() const; double worldScale() const; SceneGraphNode* parent() const; @@ -147,6 +149,9 @@ private: glm::dvec3 _worldPositionCached; glm::dmat3 _worldRotationCached; double _worldScaleCached; + + glm::dmat4 _modelTransformCached; + glm::dmat4 _inverseModelTransformCached; }; } // namespace openspace diff --git a/include/openspace/util/timemanager.h b/include/openspace/util/timemanager.h index 376e8d35e5..018765fbf6 100644 --- a/include/openspace/util/timemanager.h +++ b/include/openspace/util/timemanager.h @@ -25,6 +25,7 @@ #ifndef __OPENSPACE_CORE___TIMEMANAGER___H__ #define __OPENSPACE_CORE___TIMEMANAGER___H__ +#include #include #include @@ -35,7 +36,9 @@ public: void preSynchronization(double dt); void addKeyframe(const datamessagestructures::TimeKeyframe& kf); void removeKeyframesBefore(double timestamp); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); + const std::deque& keyframes() const; private: void consumeKeyframes(double dt); std::deque _keyframes; diff --git a/modules/onscreengui/CMakeLists.txt b/modules/onscreengui/CMakeLists.txt index b6a8bfb9ac..eead578fc5 100644 --- a/modules/onscreengui/CMakeLists.txt +++ b/modules/onscreengui/CMakeLists.txt @@ -30,6 +30,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/guihelpcomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guiorigincomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guiperformancecomponent.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/guiparallelcomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guipropertycomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guitimecomponent.h ${CMAKE_CURRENT_SOURCE_DIR}/include/guiiswacomponent.h @@ -44,6 +45,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/guihelpcomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guiorigincomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guiperformancecomponent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guiparallelcomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guipropertycomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guitimecomponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guiiswacomponent.cpp diff --git a/modules/onscreengui/include/gui.h b/modules/onscreengui/include/gui.h index 36401a7f8d..04d3056b16 100644 --- a/modules/onscreengui/include/gui.h +++ b/modules/onscreengui/include/gui.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,7 @@ public: GuiPropertyComponent _virtualProperty; GuiTimeComponent _time; GuiIswaComponent _iswa; + GuiParallelComponent _parallel; private: void renderAndUpdatePropertyVisibility(); diff --git a/modules/onscreengui/include/guiparallelcomponent.h b/modules/onscreengui/include/guiparallelcomponent.h new file mode 100644 index 0000000000..09d37ffd3c --- /dev/null +++ b/modules/onscreengui/include/guiparallelcomponent.h @@ -0,0 +1,51 @@ +/***************************************************************************************** + * * + * 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_ONSCREENGUI___GUIPARALLELCOMPONENT___H__ +#define __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__ + +#include +#include + +#include + +namespace openspace { +namespace gui { + +class GuiParallelComponent : public GuiPropertyComponent { +public: + GuiParallelComponent(); + void render() override; +private: + void renderDisconnected(); + void renderClientWithHost(); + void renderClientWithoutHost(); + void renderClientCommon(); + void renderHost(); +}; + +} // namespace gui +} // namespace openspace + +#endif // __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__ diff --git a/modules/onscreengui/onscreenguimodule.cpp b/modules/onscreengui/onscreenguimodule.cpp index 7698ae7a1e..fc2e1015db 100644 --- a/modules/onscreengui/onscreenguimodule.cpp +++ b/modules/onscreengui/onscreenguimodule.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,8 @@ OnScreenGUIModule::OnScreenGUIModule() &(OsEng.windowWrapper()), &(OsEng.settingsEngine()), &(OsEng.interactionHandler()), - &(OsEng.renderEngine()) + &(OsEng.renderEngine()), + &(OsEng.parallelConnection()) }; return res; } diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index 325375639a..514af92742 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -322,6 +322,7 @@ void GUI::initialize() { _virtualProperty.initialize(); _performance.initialize(); _help.initialize(); + _parallel.initialize(); _iswa.initialize(); } @@ -329,6 +330,7 @@ void GUI::deinitialize() { ImGui::Shutdown(); _iswa.deinitialize(); + _parallel.deinitialize(); _help.deinitialize(); _performance.deinitialize(); _globalProperty.deinitialize(); @@ -408,6 +410,7 @@ void GUI::initializeGL() { _globalProperty.initializeGL(); _performance.initializeGL(); _help.initializeGL(); + _parallel.initializeGL(); _iswa.initializeGL(); } @@ -426,6 +429,7 @@ void GUI::deinitializeGL() { } _iswa.deinitializeGL(); + _parallel.deinitializeGL(); _help.deinitializeGL(); _performance.deinitializeGL(); _globalProperty.deinitializeGL(); @@ -471,14 +475,15 @@ void GUI::endFrame() { if (_screenSpaceProperty.isEnabled()) { _screenSpaceProperty.render(); } - if (_virtualProperty.isEnabled()) { _virtualProperty.render(); } - if (_help.isEnabled()) { _help.render(); } + if (_parallel.isEnabled()) { + _parallel.render(); + } if (_iswa.isEnabled()) { _iswa.render(); } @@ -570,6 +575,10 @@ void GUI::render() { ImGui::Checkbox("Global Properties", &globalProperty); _globalProperty.setEnabled(globalProperty); + bool parallel = _parallel.isEnabled(); + ImGui::Checkbox("Parallel Connection", ¶llel); + _parallel.setEnabled(parallel); + bool virtualProperty = _virtualProperty.isEnabled(); ImGui::Checkbox("Virtual Properties", &virtualProperty); _virtualProperty.setEnabled(virtualProperty); diff --git a/modules/onscreengui/src/guiparallelcomponent.cpp b/modules/onscreengui/src/guiparallelcomponent.cpp new file mode 100644 index 0000000000..a918ef0fe6 --- /dev/null +++ b/modules/onscreengui/src/guiparallelcomponent.cpp @@ -0,0 +1,191 @@ +/***************************************************************************************** + * * + * 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 +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace { + const std::string _loggerCat = "GuiParallelComponent"; +} + +namespace openspace { +namespace gui { + +GuiParallelComponent::GuiParallelComponent() + : GuiPropertyComponent("GuiParallelComponent") +{ + setVisibility(properties::Property::Visibility::All); +} + +void GuiParallelComponent::renderDisconnected() { + ImGui::Text("Not connected"); + + const bool connect = ImGui::Button("Connect"); + + if (connect) { + OsEng.parallelConnection().clientConnect(); + } +} + +void GuiParallelComponent::renderClientWithHost() { + + ParallelConnection& parallel = OsEng.parallelConnection(); + + std::string connectionInfo = "Session hosted by \"" + parallel.hostName() + "\"\n"; + size_t nConnections = parallel.nConnections(); + size_t nClients = nConnections - 1; + + if (nClients > 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more clients are connected"; + } + else if (nClients == 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more client are connected"; + } + else if (nClients == 1) { + connectionInfo += "You are the only client"; + } + + ImGui::Text(connectionInfo.c_str()); + renderClientCommon(); + + const std::deque timeKeyframes = OsEng.timeManager().keyframes(); + const std::vector cameraKeyframes = OsEng.interactionHandler().keyframes(); + + std::string timeKeyframeInfo = "TimeKeyframes : " + std::to_string(timeKeyframes.size()); + std::string cameraKeyframeInfo = "CameraKeyframes : " + std::to_string(cameraKeyframes.size()); + std::string latencyStandardDeviation = "Latency standard deviation: " + std::to_string(parallel.latencyStandardDeviation()) + " s"; + + const bool resetTimeOffset = ImGui::Button("Reset time offset"); + + if (resetTimeOffset) { + parallel.resetTimeOffset(); + } + + ImGui::Text(timeKeyframeInfo.c_str()); + ImGui::Text(cameraKeyframeInfo.c_str()); + ImGui::Text(latencyStandardDeviation.c_str()); +} + +void GuiParallelComponent::renderClientWithoutHost() { + ParallelConnection& parallel = OsEng.parallelConnection(); + + std::string connectionInfo = "Connected to parallel session with no host\n"; + size_t nConnections = parallel.nConnections(); + + if (nConnections > 2) { + std::string c = std::to_string(nConnections - 1); + connectionInfo += "You and " + c + " more users are connected"; + } + else if (nConnections == 2) { + std::string c = std::to_string(nConnections - 1); + connectionInfo += "You and " + c + " more users are connected"; + } + else if (nConnections == 1) { + connectionInfo += "You are the only one here"; + } + + ImGui::Text(connectionInfo.c_str()); + + renderClientCommon(); + +} + +void GuiParallelComponent::renderClientCommon() { + ParallelConnection& parallel = OsEng.parallelConnection(); + + bool requestHostship = ImGui::Button("Request hostship"); + const bool disconnect = ImGui::Button("Disconnect"); + + if (requestHostship) { + parallel.requestHostship(); + } + + if (disconnect) { + parallel.signalDisconnect(); + } +} + +void GuiParallelComponent::renderHost() { + ParallelConnection& parallel = OsEng.parallelConnection(); + size_t nConnections = parallel.nConnections(); + + std::string connectionInfo = ""; + size_t nClients = nConnections - 1; + if (nClients == 1) { + connectionInfo = "Hosting session with 1 client"; + } else { + connectionInfo = + "Hosting session with " + std::to_string(nClients) + " clients"; + } + + ImGui::Text(connectionInfo.c_str()); + + const bool resignHostship = ImGui::Button("Resign hostship"); + if (resignHostship) { + parallel.resignHostship(); + } +} + + +void GuiParallelComponent::render() { + bool v = _isEnabled; + ImGui::Begin("Parallel Connection", &v); + _isEnabled = v; + + ParallelConnection::Status status = OsEng.parallelConnection().status(); + + switch (status) { + case ParallelConnection::Status::Disconnected: + renderDisconnected(); + break; + case ParallelConnection::Status::ClientWithHost: + renderClientWithHost(); + break; + case ParallelConnection::Status::ClientWithoutHost: + renderClientWithoutHost(); + break; + case ParallelConnection::Status::Host: + renderHost(); + break; + } + + GuiPropertyComponent::renderPropertyOwner(&OsEng.parallelConnection()); + ImGui::End(); +} + +} // namespace gui +} // namespace openspace diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 03158a20e6..43a410ff1f 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -133,7 +134,7 @@ OpenSpaceEngine::OpenSpaceEngine( , _settingsEngine(new SettingsEngine) , _timeManager(new TimeManager) , _downloadManager(nullptr) - , _parallelConnection(new ParallelConnection) + , _parallelConnection(std::make_unique()) , _windowWrapper(std::move(windowWrapper)) , _globalPropertyNamespace(new properties::PropertyOwner("")) , _virtualPropertyManager(new VirtualPropertyManager) @@ -150,7 +151,8 @@ OpenSpaceEngine::OpenSpaceEngine( _globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_renderEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_windowWrapper.get()); - + _globalPropertyNamespace->addPropertySubOwner(_parallelConnection.get()); + FactoryManager::initialize(); FactoryManager::ref().addFactory( std::make_unique>(), @@ -369,6 +371,10 @@ void OpenSpaceEngine::create(int argc, char** argv, } void OpenSpaceEngine::destroy() { + if (_engine->parallelConnection().status() != ParallelConnection::Status::Disconnected) { + _engine->parallelConnection().signalDisconnect(); + } + LTRACE("OpenSpaceEngine::destroy(begin)"); for (const auto& func : _engine->_moduleCallbacks.deinitializeGL) { func(); diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 1ab20e2221..b39fc4eed6 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -39,8 +39,8 @@ #include #include - #include +#include #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED #include @@ -188,6 +188,10 @@ void InteractionHandler::setInteractionMode(std::shared_ptr int _currentInteractionMode->setFocusNode(focusNode); } +InteractionMode * InteractionHandler::interactionMode() { + return _currentInteractionMode.get(); +} + void InteractionHandler::setInteractionMode(const std::string& interactionModeKey) { if (_interactionModes.find(interactionModeKey) != _interactionModes.end()) { setInteractionMode(_interactionModes[interactionModeKey]); @@ -265,6 +269,15 @@ SceneGraphNode* const InteractionHandler::focusNode() const { return _currentInteractionMode->focusNode(); } +glm::dvec3 InteractionHandler::focusNodeToCameraVector() const { + return _camera->positionVec3() - focusNode()->worldPosition(); +} + +glm::quat InteractionHandler::focusNodeToCameraRotation() const { + glm::dmat4 invWorldRotation = glm::inverse(focusNode()->worldRotationMatrix()); + return glm::quat(invWorldRotation) * glm::quat(_camera->rotationQuaternion()); +} + Camera* const InteractionHandler::camera() const { return _camera; } @@ -621,9 +634,17 @@ void InteractionHandler::addKeyframe(const datamessagestructures::CameraKeyframe _inputState->addKeyframe(kf); } +void InteractionHandler::removeKeyframesAfter(double timestamp) { + _inputState->removeKeyframesAfter(timestamp); +} + void InteractionHandler::clearKeyframes() { _inputState->clearKeyframes(); } +const std::vector& InteractionHandler::keyframes() const { + return _inputState->keyframes(); +} + } // namespace interaction } // namespace openspace diff --git a/src/interaction/interactionmode.cpp b/src/interaction/interactionmode.cpp index 44cbfa23bf..37015985eb 100644 --- a/src/interaction/interactionmode.cpp +++ b/src/interaction/interactionmode.cpp @@ -65,16 +65,21 @@ namespace interaction { void InputState::addKeyframe(const datamessagestructures::CameraKeyframe &kf) { clearOldKeyframes(); + if (kf._timestamp < OsEng.runTime()) { + return; + } + _keyframes.insert(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), kf); + } - auto compareTimestamps = [](const datamessagestructures::CameraKeyframe a, - datamessagestructures::CameraKeyframe b) { - return a._timestamp < b._timestamp; - }; - + void InputState::removeKeyframesAfter(double timestamp) { + datamessagestructures::CameraKeyframe kf; + kf._timestamp = timestamp; // Remove keyframes after the inserted keyframe. - _keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, compareTimestamps), _keyframes.end()); + _keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), _keyframes.end()); + } - _keyframes.push_back(kf); + bool InputState::compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b) { + return a._timestamp < b._timestamp; } void InputState::clearOldKeyframes() { @@ -169,9 +174,6 @@ namespace interaction { - - - InteractionMode::InteractionMode() : _rotateToFocusNodeInterpolator(Interpolator([](double t){ return pow(t, 2); @@ -241,8 +243,40 @@ void KeyframeInteractionMode::updateCameraStateFromMouseStates(Camera& camera, d double t = (now - prevTime) / (nextTime - prevTime); - camera.setPositionVec3(prevKeyframe->_position * (1 - t) + nextKeyframe->_position * t); - camera.setRotation(glm::slerp(prevKeyframe->_rotation, nextKeyframe->_rotation, t)); + Scene* scene = camera.parent()->scene(); + SceneGraphNode* prevFocusNode = scene->sceneGraphNode(prevKeyframe->_focusNode); + SceneGraphNode* nextFocusNode = scene->sceneGraphNode(nextKeyframe->_focusNode); + + if (!prevFocusNode || !nextFocusNode) { + return; + } + + glm::dvec3 prevKeyframeCameraPosition = prevKeyframe->_position; + glm::dvec3 nextKeyframeCameraPosition = nextKeyframe->_position; + glm::dquat prevKeyframeCameraRotation = prevKeyframe->_rotation; + glm::dquat nextKeyframeCameraRotation = nextKeyframe->_rotation; + + // Transform position and rotation based on focus node rotation (if following rotation) + if (prevKeyframe->_followNodeRotation) { + prevKeyframeCameraRotation = prevFocusNode->worldRotationMatrix() * glm::dmat3(prevKeyframe->_rotation); + prevKeyframeCameraPosition = prevFocusNode->worldRotationMatrix() * prevKeyframeCameraPosition; + } + if (nextKeyframe->_followNodeRotation) { + nextKeyframeCameraRotation = nextFocusNode->worldRotationMatrix() * glm::dmat3(nextKeyframe->_rotation); + nextKeyframeCameraPosition = nextFocusNode->worldRotationMatrix() * nextKeyframeCameraPosition; + } + + // Transform position based on focus node position + prevKeyframeCameraPosition += prevFocusNode->worldPosition(); + nextKeyframeCameraPosition += nextFocusNode->worldPosition(); + + // Linear interpolation + camera.setPositionVec3(prevKeyframeCameraPosition * (1 - t) + nextKeyframeCameraPosition * t); + camera.setRotation(glm::slerp(prevKeyframeCameraRotation, nextKeyframeCameraRotation, t)); +} + +bool KeyframeInteractionMode::followingNodeRotation() const { + return false; } // OrbitalInteractionMode @@ -486,6 +520,10 @@ void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera, do } } +bool OrbitalInteractionMode::followingNodeRotation() const { + return false; +} + void OrbitalInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double deltaTime) { _mouseStates->updateMouseStatesFromInput(inputState, deltaTime); } @@ -687,6 +725,10 @@ void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& came #endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED } +bool GlobeBrowsingInteractionMode::followingNodeRotation() const { + return true; +} + #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED void GlobeBrowsingInteractionMode::goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection) { diff --git a/src/interaction/luaconsole.cpp b/src/interaction/luaconsole.cpp index 65824f46bd..37ea62df08 100644 --- a/src/interaction/luaconsole.cpp +++ b/src/interaction/luaconsole.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -57,19 +58,13 @@ namespace openspace { LuaConsole::LuaConsole() : properties::PropertyOwner("LuaConsole") , _isVisible("isVisible", "Is Visible", false) - , _remoteScripting(true) + , _remoteScripting("remoteScripting", "Remote scripting", false) , _inputPosition(0) , _activeCommand(0) , _autoCompleteInfo({NoAutoComplete, false, ""}) { - _isVisible.onChange([this](){ - if (_isVisible) { - _remoteScripting = false; - } else { - _remoteScripting = OsEng.parallelConnection().isHost(); - } - }); addProperty(_isVisible); + addProperty(_remoteScripting); } void LuaConsole::initialize() { @@ -164,7 +159,19 @@ bool LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio if (key == CommandInputButton) { // Button left of 1 and above TAB // How to deal with different keyboard languages? ---abock - _isVisible = !_isVisible; + if (_isVisible) { + if (_remoteScripting) { + _remoteScripting = false; + } else { + _isVisible = false; + } + } else { + _isVisible = true; + if (OsEng.parallelConnection().status() == ParallelConnection::Status::Host) { + _remoteScripting = true; + } + } + return true; } diff --git a/src/network/parallelconnection.cpp b/src/network/parallelconnection.cpp index dc95269c01..38e8525611 100644 --- a/src/network/parallelconnection.cpp +++ b/src/network/parallelconnection.cpp @@ -61,14 +61,17 @@ #include #endif -//openspace includes #include #include #include #include +#include +#include #include #include #include +#include + #include //lua functions @@ -77,22 +80,26 @@ namespace { const uint32_t ProtocolVersion = 2; const size_t MaxLatencyDiffs = 64; - const double BroadcastIntervalMilliseconds = 100; const std::string _loggerCat = "ParallelConnection"; - const int nFrametimesBuffer = 4; - const int nBroadcastIntervalsBuffer = 2; } namespace openspace { ParallelConnection::ParallelConnection() - : _passCode(0) - , _port("20501") - , _address("127.0.0.1") - , _name("Local Connection") + : properties::PropertyOwner("ParallelConnection") + , _password("password", "Password") + , _hostPassword("hostPassword", "Host Password") + , _port("port", "Port", "20501") + , _address("address", "Address", "localhost") + , _name("name", "Connection name", "Anonymous") + , _bufferTime("bufferTime", "Buffer Time", 1, 0.5, 10) + , _timeKeyframeInterval("timeKeyframeInterval", "Time keyframe interval", 0.1, 0, 1) + , _cameraKeyframeInterval("cameraKeyframeInterval", "Camera Keyframe interval", 0.1, 0, 1) + , _timeTolerance("timeTolerance", "Time tolerance", 1, 0.5, 5) + , _lastTimeKeyframeTimestamp(0) + , _lastCameraKeyframeTimestamp(0) , _clientSocket(INVALID_SOCKET) , _connectionThread(nullptr) - , _broadcastThread(nullptr) , _sendThread(nullptr) , _listenThread(nullptr) , _handlerThread(nullptr) @@ -105,6 +112,19 @@ ParallelConnection::ParallelConnection() , _disconnect(false) , _initializationTimejumpRequired(false) { + addProperty(_name); + + addProperty(_port); + addProperty(_address); + addProperty(_bufferTime); + + addProperty(_password); + addProperty(_hostPassword); + + addProperty(_timeKeyframeInterval); + addProperty(_cameraKeyframeInterval); + addProperty(_timeTolerance); + _connectionEvent = std::make_shared>(); _handlerThread = std::make_unique(&ParallelConnection::threadManagement, this); } @@ -186,8 +206,7 @@ void ParallelConnection::disconnect(){ //tell send thread to stop sending and listen thread to stop listenin _isConnected.store(false); - - //tell broadcast thread to stop broadcasting (we're no longer host) + setStatus(Status::Disconnected); //join connection thread and delete it @@ -207,13 +226,7 @@ void ParallelConnection::disconnect(){ _listenThread->join(); _listenThread = nullptr; } - - //join broadcast thread and delete it - if(_broadcastThread != nullptr){ - _broadcastThread->join(); - _broadcastThread = nullptr; - } - + // disconnect and cleanup completed _disconnect = false; } @@ -241,7 +254,7 @@ void ParallelConnection::clientConnect(){ hints.ai_flags = AI_PASSIVE; // Resolve the local address and port to be used by the server - int result = getaddrinfo(_address.c_str(), _port.c_str(), &hints, &addresult); + int result = getaddrinfo(_address.value().c_str(), _port.value().c_str(), &hints, &addresult); if (result != 0) { LERROR("Failed to parse hints for Parallel Connection"); @@ -308,57 +321,39 @@ void ParallelConnection::establishConnection(addrinfo *info){ LERROR("Failed to set socket option 'keep alive'. Error code: " << _ERRNO); - //while the connection thread is still running - while (_tryConnect.load()){ - LINFO("Attempting to connect to server "<< _address << " on port " << _port); + LINFO("Attempting to connect to server "<< _address << " on port " << _port); - //try to connect - result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen); + //try to connect + result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen); - //if the connection was successfull - if (result != SOCKET_ERROR) - { + //if the connection was successfull + if (result != SOCKET_ERROR) + { - LINFO("Connection established with server at ip: "<< _address); + LINFO("Connection established with server at ip: "<< _address); - //we're connected - _isConnected.store(true); + //we're connected + _isConnected.store(true); - //start sending messages - _sendThread = std::make_unique(&ParallelConnection::sendFunc, this); + //start sending messages + _sendThread = std::make_unique(&ParallelConnection::sendFunc, this); - //start listening for communication - _listenThread = std::make_unique(&ParallelConnection::listenCommunication, this); + //start listening for communication + _listenThread = std::make_unique(&ParallelConnection::listenCommunication, this); - //we no longer need to try to establish connection - _tryConnect.store(false); + //we no longer need to try to establish connection + _tryConnect.store(false); - _sendBufferMutex.lock(); - _sendBuffer.clear(); - _sendBufferMutex.unlock(); + _sendBufferMutex.lock(); + _sendBuffer.clear(); + _sendBufferMutex.unlock(); - //send authentication - sendAuthentication(); - } else { - LINFO("Connection attempt failed."); - } - -#ifdef WIN32 - //on windows: try to connect once per second - std::this_thread::sleep_for(std::chrono::seconds(1)); -#else - if(!_isConnected.load()){ - //on unix disconnect and display error message if we're not connected - LERROR("Failed to establish a connection with server "<< _address << " on port " << _port<<", terminating connection."); - - //signal disconnect - signalDisconnect(); - - //stop loop - break; - } -#endif + //send authentication + sendAuthentication(); + } else { + LINFO("Connection attempt failed."); + signalDisconnect(); } //cleanup @@ -366,8 +361,10 @@ void ParallelConnection::establishConnection(addrinfo *info){ } void ParallelConnection::sendAuthentication() { + + std::string name = _name.value(); //length of this nodes name - uint32_t nameLength = static_cast(_name.length()); + uint32_t nameLength = static_cast(name.length()); //total size of the buffer: (passcode + namelength + name) size_t size = 2 * sizeof(uint32_t) + nameLength; @@ -376,14 +373,16 @@ void ParallelConnection::sendAuthentication() { std::vector buffer; buffer.reserve(size); + uint32_t passCode = hash(_password.value()); + //write passcode to buffer - buffer.insert(buffer.end(), reinterpret_cast(&_passCode), reinterpret_cast(&_passCode) + sizeof(uint32_t)); + buffer.insert(buffer.end(), reinterpret_cast(&passCode), reinterpret_cast(&passCode) + sizeof(uint32_t)); //write the length of the nodes name to buffer buffer.insert(buffer.end(), reinterpret_cast(&nameLength), reinterpret_cast(&nameLength) + sizeof(uint32_t)); //write this node's name to buffer - buffer.insert(buffer.end(), _name.begin(), _name.end()); + buffer.insert(buffer.end(), name.begin(), name.end()); //send buffer queueOutMessage(Message(MessageType::Authentication, buffer)); @@ -505,6 +504,10 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) { } _latencyDiffs.push_back(latencyDiff); + return originalTime + timeDiff + latencyDiff + _bufferTime; +} + +double ParallelConnection::latencyStandardDeviation() const { double accumulatedLatencyDiffSquared = 0; double accumulatedLatencyDiff = 0; for (double diff : _latencyDiffs) { @@ -516,16 +519,14 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) { // V(X) = E(x^2) - E(x)^2 double latencyVariance = expectedLatencyDiffSquared - expectedLatencyDiff*expectedLatencyDiff; - double latencyStandardDeviation = std::sqrt(latencyVariance); - - double frametime = OsEng.windowWrapper().averageDeltaTime(); - - double latencyCompensation = std::max(expectedLatencyDiff + 2 * latencyStandardDeviation, latencyDiff); - - return originalTime + timeDiff + nBroadcastIntervalsBuffer * BroadcastIntervalMilliseconds / 1000 + latencyCompensation + nFrametimesBuffer * frametime; - + return std::sqrt(latencyVariance); } +double ParallelConnection::timeTolerance() const { + return _timeTolerance; +} + + void ParallelConnection::dataMessageReceived(const std::vector& messageContent) { //the type of data message received @@ -534,26 +535,26 @@ void ParallelConnection::dataMessageReceived(const std::vector& messageCon switch(static_cast(type)) { case datamessagestructures::Type::CameraData: { - datamessagestructures::CameraKeyframe kf(buffer); kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp); + OsEng.interactionHandler().removeKeyframesAfter(kf._timestamp); OsEng.interactionHandler().addKeyframe(kf); break; } case datamessagestructures::Type::TimeData: { - datamessagestructures::TimeKeyframe kf(buffer); kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp); + OsEng.timeManager().removeKeyframesAfter(kf._timestamp); OsEng.timeManager().addKeyframe(kf); break; } case datamessagestructures::Type::ScriptData: { datamessagestructures::ScriptMessage sm; sm.deserialize(buffer); - OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No); - + + OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No); break; } default:{ @@ -691,17 +692,6 @@ void ParallelConnection::connectionStatusMessageReceived(const std::vector setStatus(status); - if (status == Status::Host) { // assigned as host - _broadcastThread = std::make_unique(&ParallelConnection::broadcast, this); - } else { // assigned as client - - // delete broadcasting thread - // (the thread is allowed to terminate once the status is set to non-host.) - if (_broadcastThread != nullptr) { - _broadcastThread->join(); - _broadcastThread = nullptr; - } - } OsEng.interactionHandler().clearKeyframes(); OsEng.timeManager().clearKeyframes(); @@ -879,22 +869,22 @@ int ParallelConnection::receiveData(_SOCKET & socket, std::vector &buffer, return result; } -void ParallelConnection::setPort(const std::string &port){ - _port = port; +void ParallelConnection::setPort(std::string port){ + _port = std::move(port); } -void ParallelConnection::setAddress(const std::string &address){ - _address = address; +void ParallelConnection::setAddress(std::string address){ + _address = std::move(address); } -void ParallelConnection::setName(const std::string& name){ - _name = name; +void ParallelConnection::setName(std::string name){ + _name = std::move(name); } -void ParallelConnection::requestHostship(const std::string &password){ +void ParallelConnection::requestHostship(){ std::vector buffer; - uint32_t passcode = hash(password); + uint32_t passcode = hash(_hostPassword); buffer.insert(buffer.end(), reinterpret_cast(&passcode), reinterpret_cast(&passcode) + sizeof(uint32_t)); queueOutMessage(Message(MessageType::HostshipRequest, buffer)); } @@ -904,8 +894,12 @@ void ParallelConnection::resignHostship() { queueOutMessage(Message(MessageType::HostshipResignation, buffer)); } -void ParallelConnection::setPassword(const std::string& pwd){ - _passCode = hash(pwd); +void ParallelConnection::setPassword(std::string pwd){ + _password = std::move(pwd); +} + +void ParallelConnection::setHostPassword(std::string pwd) { + _hostPassword = std::move(pwd); } bool ParallelConnection::initNetworkAPI(){ @@ -934,11 +928,11 @@ bool ParallelConnection::initNetworkAPI(){ return true; } -void ParallelConnection::sendScript(const std::string& script) { +void ParallelConnection::sendScript(std::string script) { if (!isHost()) return; datamessagestructures::ScriptMessage sm; - sm._script = script; + sm._script = std::move(script); std::vector buffer; sm.serialize(buffer); @@ -946,6 +940,13 @@ void ParallelConnection::sendScript(const std::string& script) { queueOutDataMessage(DataMessage(datamessagestructures::Type::ScriptData, buffer)); } +void ParallelConnection::resetTimeOffset() { + OsEng.interactionHandler().clearKeyframes(); + OsEng.timeManager().clearKeyframes(); + std::lock_guard latencyLock(_latencyMutex); + _latencyDiffs.clear(); +} + void ParallelConnection::preSynchronization(){ std::unique_lock unqlock(_receiveBufferMutex); @@ -959,12 +960,23 @@ void ParallelConnection::preSynchronization(){ if (Time::ref().timeJumped()) { _timeJumped = true; } + double now = OsEng.runTime(); + + if (_lastCameraKeyframeTimestamp + _cameraKeyframeInterval < now) { + sendCameraKeyframe(); + _lastCameraKeyframeTimestamp = now; + } + if (_lastTimeKeyframeTimestamp + _timeKeyframeInterval < now) { + sendTimeKeyframe(); + _lastTimeKeyframeTimestamp = now; + } } } void ParallelConnection::setStatus(Status status) { if (_status != status) { _status = status; + _timeJumped = true; _connectionEvent->publish("statusChanged"); } } @@ -1000,26 +1012,40 @@ const std::string& ParallelConnection::hostName() { } void ParallelConnection::sendCameraKeyframe() { - //create a keyframe with current position and orientation of camera - datamessagestructures::CameraKeyframe kf; - kf._position = OsEng.interactionHandler().camera()->positionVec3(); - kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion(); + SceneGraphNode* focusNode = OsEng.interactionHandler().focusNode(); + if (!focusNode) { + return; + } - //timestamp as current runtime of OpenSpace instance + // Create a keyframe with current position and orientation of camera + datamessagestructures::CameraKeyframe kf; + kf._position = OsEng.interactionHandler().focusNodeToCameraVector(); + + kf._followNodeRotation = OsEng.interactionHandler().interactionMode()->followingNodeRotation(); + if (kf._followNodeRotation) { + kf._position = glm::inverse(focusNode->worldRotationMatrix()) * kf._position; + kf._rotation = OsEng.interactionHandler().focusNodeToCameraRotation(); + } else { + kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion(); + } + + kf._focusNode = focusNode->name(); + + // Timestamp as current runtime of OpenSpace instance kf._timestamp = OsEng.runTime(); - //create a buffer for the keyframe + // Create a buffer for the keyframe std::vector buffer; - //fill the keyframe buffer + // Fill the keyframe buffer kf.serialize(buffer); - //send message + // Send message queueOutDataMessage(DataMessage(datamessagestructures::Type::CameraData, buffer)); } void ParallelConnection::sendTimeKeyframe() { - //create a keyframe with current position and orientation of camera + // Create a keyframe with current position and orientation of camera datamessagestructures::TimeKeyframe kf; kf._dt = Time::ref().deltaTime(); @@ -1027,33 +1053,20 @@ void ParallelConnection::sendTimeKeyframe() { kf._requiresTimeJump = _timeJumped; kf._time = Time::ref().j2000Seconds(); - //timestamp as current runtime of OpenSpace instance + // Timestamp as current runtime of OpenSpace instance kf._timestamp = OsEng.runTime(); - //create a buffer for the keyframe + // Create a buffer for the keyframe std::vector buffer; - //fill the keyframe buffer + // Fill the keyframe buffer kf.serialize(buffer); - //send message + // Send message queueOutDataMessage(DataMessage(datamessagestructures::Type::TimeData, buffer)); _timeJumped = false; } - -void ParallelConnection::broadcast(){ - _timeJumped = true; - //while we're still connected and we're the host - while (_isConnected && isHost()) { - sendCameraKeyframe(); - sendTimeKeyframe(); - - //100 ms sleep - send keyframes 10 times per second - std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(BroadcastIntervalMilliseconds))); - } -} - uint32_t ParallelConnection::hash(const std::string &val) { uint32_t hashVal = 0, i; size_t len = val.length(); @@ -1080,30 +1093,6 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() { return { "parallel", { - { - "setPort", - &luascriptfunctions::setPort, - "number", - "Set the port for the parallel connection" - }, - { - "setAddress", - &luascriptfunctions::setAddress, - "string", - "Set the address for the parallel connection" - }, - { - "setPassword", - &luascriptfunctions::setPassword, - "string", - "Set the password for the parallel connection" - }, - { - "setDisplayName", - &luascriptfunctions::setDisplayName, - "string", - "Set your display name for the parallel connection" - }, { "connect", &luascriptfunctions::connect, @@ -1119,7 +1108,7 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() { { "requestHostship", &luascriptfunctions::requestHostship, - "string", + "", "Request to be the host for this session" }, { diff --git a/src/network/parallelconnection_lua.inl b/src/network/parallelconnection_lua.inl index 538f0180cc..09547ea7c7 100644 --- a/src/network/parallelconnection_lua.inl +++ b/src/network/parallelconnection_lua.inl @@ -26,109 +26,10 @@ namespace openspace { namespace luascriptfunctions { -/** - * \ingroup LuaScripts - * setPort(): - * Set the port for parallel connection - */ -int setPort(lua_State* L) { - bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - bool isNumber = (lua_isnumber(L, -1) != 0); - if (isNumber) { - int value = static_cast(lua_tonumber(L, -1)); - std::string port = std::to_string(value); - if (OsEng.windowWrapper().isMaster()) { - OsEng.parallelConnection().setPort(port); - } - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } -} - -int setAddress(lua_State* L) { - bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - int type = lua_type(L, -1); - if (type == LUA_TSTRING) { - std::string address = luaL_checkstring(L, -1); - if (OsEng.windowWrapper().isMaster()) { - OsEng.parallelConnection().setAddress(address); - } - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } -} - -int setPassword(lua_State* L) { - bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - int type = lua_type(L, -1); - if (type == LUA_TSTRING) { - std::string pwd = luaL_checkstring(L, -1); - if (OsEng.windowWrapper().isMaster()) { - OsEng.parallelConnection().setPassword(pwd); - } - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } -} - -int setDisplayName(lua_State* L) { - bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - int type = lua_type(L, -1); - if (type == LUA_TSTRING) { - std::string name = luaL_checkstring(L, -1); - if (OsEng.windowWrapper().isMaster()) { - OsEng.parallelConnection().setName(name); - } - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } -} - int connect(lua_State* L) { int nArguments = lua_gettop(L); - if (nArguments != 0) { - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - } + SCRIPT_CHECK_ARGUMENTS("connect", L, 0, nArguments); + if (OsEng.windowWrapper().isMaster()) { OsEng.parallelConnection().clientConnect(); } @@ -137,9 +38,8 @@ int connect(lua_State* L) { int disconnect(lua_State* L) { int nArguments = lua_gettop(L); - if (nArguments != 0) { - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - } + SCRIPT_CHECK_ARGUMENTS("disconnect", L, 0, nArguments); + if (OsEng.windowWrapper().isMaster()) { OsEng.parallelConnection().signalDisconnect(); } @@ -147,33 +47,19 @@ int disconnect(lua_State* L) { } int requestHostship(lua_State* L) { - bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - int type = lua_type(L, -1); - if (type == LUA_TSTRING) { - std::string pwd = luaL_checkstring(L, -1); - if (OsEng.windowWrapper().isMaster()) { - OsEng.parallelConnection().requestHostship(pwd); - } - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); + int nArguments = lua_gettop(L); + SCRIPT_CHECK_ARGUMENTS("requestHostship", L, 0, nArguments); + + if (OsEng.windowWrapper().isMaster()) { + OsEng.parallelConnection().requestHostship(); } + return 0; } int resignHostship(lua_State* L) { int nArguments = lua_gettop(L); - if (nArguments != 0) { - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - } + SCRIPT_CHECK_ARGUMENTS("resignHostship", L, 0, nArguments); + if (OsEng.windowWrapper().isMaster()) { OsEng.parallelConnection().resignHostship(); } diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index ed89771ca0..863bb961dd 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -288,7 +288,17 @@ void SceneGraphNode::update(const UpdateData& data) { newUpdateData.modelTransform.translation = worldPosition(); newUpdateData.modelTransform.rotation = worldRotationMatrix(); - newUpdateData.modelTransform .scale = worldScale(); + newUpdateData.modelTransform.scale = worldScale(); + + glm::dmat4 translation = + glm::translate(glm::dmat4(1.0), newUpdateData.modelTransform.translation); + glm::dmat4 rotation = glm::dmat4(newUpdateData.modelTransform.rotation); + glm::dmat4 scaling = + glm::scale(glm::dmat4(1.0), glm::dvec3(newUpdateData.modelTransform.scale, + newUpdateData.modelTransform.scale, newUpdateData.modelTransform.scale)); + + _modelTransformCached = translation * rotation * scaling; + _inverseModelTransformCached = glm::inverse(_modelTransformCached); if (_renderable && _renderable->isReady()) { if (data.doPerformanceMeasurement) { @@ -541,6 +551,14 @@ const glm::dmat3& SceneGraphNode::worldRotationMatrix() const return _worldRotationCached; } +glm::dmat4 SceneGraphNode::modelTransform() const { + return _modelTransformCached; +} + +glm::dmat4 SceneGraphNode::inverseModelTransform() const { + return _inverseModelTransformCached; +} + double SceneGraphNode::worldScale() const { return _worldScaleCached; diff --git a/src/util/timemanager.cpp b/src/util/timemanager.cpp index d99aed73f7..61502b221f 100644 --- a/src/util/timemanager.cpp +++ b/src/util/timemanager.cpp @@ -25,10 +25,7 @@ #include #include #include - -namespace { - double SecondsOffTolerance = 0.1; -} +#include namespace openspace { @@ -96,8 +93,10 @@ void TimeManager::consumeKeyframes(double dt) { return; } + const double secondsOffTolerance = OsEng.parallelConnection().timeTolerance(); + double predictedTime = time.j2000Seconds() + time.deltaTime() * (next._timestamp - now); - bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * SecondsOffTolerance); + bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * secondsOffTolerance); if (next._dt == time.deltaTime() && withinTolerance) { Time::ref().advanceTime(dt); @@ -121,6 +120,7 @@ void TimeManager::consumeKeyframes(double dt) { time.setDeltaTime(y1Prime); time.setTime(y1, false); + // std::cout << "Correcting time to " << y1 << ", dt=" << y1Prime << "." << std::endl; } } @@ -133,6 +133,13 @@ void TimeManager::addKeyframe(const TimeKeyframe& kf) { _keyframes.insert(iter, kf); } +void TimeManager::removeKeyframesAfter(double timestamp) { + datamessagestructures::TimeKeyframe kf; + kf._timestamp = timestamp; + auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes); + _keyframes.erase(iter, _keyframes.end()); +} + void TimeManager::removeKeyframesBefore(double timestamp) { datamessagestructures::TimeKeyframe kf; @@ -145,8 +152,11 @@ void TimeManager::clearKeyframes() { _keyframes.clear(); } -bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b) -{ +const std::deque& TimeManager::keyframes() const { + return _keyframes; +} + +bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b) { return a._timestamp < b._timestamp; } From d90a51297d25b998306077852edea33f690ff678 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Tue, 29 Nov 2016 16:18:12 +0100 Subject: [PATCH 14/34] Cherry pick commit by Erik Broberg --- modules/globebrowsing/CMakeLists.txt | 3 + modules/globebrowsing/globebrowsingmodule.cpp | 4 + .../presentationslideprovider.cpp | 116 ++++++++++++++++++ .../tileprovider/presentationslideprovider.h | 72 +++++++++++ 4 files changed, 195 insertions(+) create mode 100644 modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp create mode 100644 modules/globebrowsing/tile/tileprovider/presentationslideprovider.h diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index 8145f2cd30..beb70af6ec 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -101,6 +101,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/loadjob.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h @@ -166,6 +167,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilediskcache.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.cpp @@ -174,6 +176,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/diskcachedtileloadjob.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 02facd9382..2b8cb05eff 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -119,6 +120,9 @@ void GlobeBrowsingModule::internalInitialize() { fTileProvider->registerClass("ByLevel"); fTileProvider->registerClass("ByIndex"); + fTileProvider->registerClass("ByLevel"); + fTileProvider->registerClass("ByIndex"); + fTileProvider->registerClass("PresentationSlides"); FactoryManager::ref().addFactory(std::move(fTileProvider)); } diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp new file mode 100644 index 0000000000..e4cbaff471 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp @@ -0,0 +1,116 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 +#include + +#include +#include +#include + +#include + +namespace { + const std::string _loggerCat = "PresentationSlideProvider"; + + const std::string KeyDefaultProvider = "DefaultProvider"; + const std::string KeySlideProviders = "SlideProviders"; + const std::string KeyTileIndex = "TileIndex"; + const std::string KeyTileProvider = "TileProvider"; +} + +namespace openspace { +namespace globebrowsing { + + PresentationSlideProvider::PresentationSlideProvider(const ghoul::Dictionary& dictionary) { + setName("SlideProvider"); + ghoul::Dictionary defaultProviderDict = dictionary.value(KeyDefaultProvider); + TileProvider* defaultProvider = TileProvider::createFromDictionary(defaultProviderDict); + _defaultProvider = std::unique_ptr(defaultProvider); + + ghoul::Dictionary tileIndexDict = dictionary.value(KeyTileIndex); + _tileIndex = TileIndex(tileIndexDict); + + ghoul::Dictionary slideProvidersDict = dictionary.value(KeySlideProviders); + _slideProviders.resize(slideProvidersDict.size()); + for (size_t i = 0; i < slideProvidersDict.size(); i++) { + std::string dictKey = std::to_string(i + 1); + ghoul::Dictionary providerDict = slideProvidersDict.value(dictKey); + TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict); + _slideProviders[i].reset(tileProvider); + } + + + _slideIndex = std::make_unique("slideIndex", "slideIndex", 0, 0, _slideProviders.size()-1); + addProperty(_slideIndex.get()); + } + + Tile PresentationSlideProvider::getTile(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTile(tileIndex); + } + return Tile::TileUnavailable; + + } + + Tile PresentationSlideProvider::getDefaultTile() { + return _defaultProvider->getDefaultTile(); + } + + Tile::Status PresentationSlideProvider::getTileStatus(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTileStatus(tileIndex); + } + return Tile::Status::Unavailable; + } + + TileDepthTransform PresentationSlideProvider::depthTransform() { + slideProvider()->depthTransform(); + } + + void PresentationSlideProvider::update() { + slideProvider()->update(); + _defaultProvider->update(); + } + + void PresentationSlideProvider::reset() { + for(auto& tp : _slideProviders){ + tp->reset(); + } + _defaultProvider->reset(); + } + + int PresentationSlideProvider::maxLevel() { + return _defaultProvider->maxLevel(); + } + + TileProvider* PresentationSlideProvider::slideProvider(){ + int maxIndex = (int)_slideProviders.size() - 1; + return _slideProviders[std::max(0, std::min(_slideIndex->value(), maxIndex))].get(); + } + + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h new file mode 100644 index 0000000000..1d159b3689 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h @@ -0,0 +1,72 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* 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 __PRESENTATION_SLIDE_PROVIDER__ +#define __PRESENTATION_SLIDE_PROVIDER__ + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace openspace { +namespace globebrowsing { + + using namespace ghoul::opengl; + + class PresentationSlideProvider : public TileProvider { + public: + + PresentationSlideProvider(const ghoul::Dictionary& dictionary); + PresentationSlideProvider(const std::string& imagePath); + virtual ~PresentationSlideProvider() { } + + virtual Tile getTile(const TileIndex& tileIndex); + virtual Tile getDefaultTile(); + virtual Tile::Status getTileStatus(const TileIndex& index); + virtual TileDepthTransform depthTransform(); + virtual void update(); + virtual void reset(); + virtual int maxLevel(); + + private: + TileProvider* slideProvider(); + + + TileIndex _tileIndex; + std::unique_ptr _slideIndex; + std::vector> _slideProviders; + std::unique_ptr _defaultProvider; + }; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __PRESENTATION_SLIDE_PROVIDER__ From 889545bd45c2da0499d43102e712a95db6c83151 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 14 Apr 2017 18:06:46 -0400 Subject: [PATCH 15/34] Compile fixes for PresentationSlideProvider --- .../presentationslideprovider.cpp | 108 +++++++++--------- .../tileprovider/presentationslideprovider.h | 44 ++++--- .../tile/tileprovider/tileprovider.cpp | 15 +-- 3 files changed, 79 insertions(+), 88 deletions(-) diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp index e4cbaff471..bc38a37fff 100644 --- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp @@ -43,74 +43,74 @@ namespace { namespace openspace { namespace globebrowsing { +namespace tileprovider { - PresentationSlideProvider::PresentationSlideProvider(const ghoul::Dictionary& dictionary) { - setName("SlideProvider"); - ghoul::Dictionary defaultProviderDict = dictionary.value(KeyDefaultProvider); - TileProvider* defaultProvider = TileProvider::createFromDictionary(defaultProviderDict); - _defaultProvider = std::unique_ptr(defaultProvider); +PresentationSlideProvider::PresentationSlideProvider(const ghoul::Dictionary& dictionary) + : _slideIndex("slideIndex", "slideIndex", 0, 0, _slideProviders.size() - 1) +{ + setName("SlideProvider"); + ghoul::Dictionary defaultProviderDict = dictionary.value(KeyDefaultProvider); + _defaultProvider = TileProvider::createFromDictionary(defaultProviderDict); - ghoul::Dictionary tileIndexDict = dictionary.value(KeyTileIndex); - _tileIndex = TileIndex(tileIndexDict); + ghoul::Dictionary tileIndexDict = dictionary.value(KeyTileIndex); + _tileIndex = TileIndex(tileIndexDict); - ghoul::Dictionary slideProvidersDict = dictionary.value(KeySlideProviders); - _slideProviders.resize(slideProvidersDict.size()); - for (size_t i = 0; i < slideProvidersDict.size(); i++) { - std::string dictKey = std::to_string(i + 1); - ghoul::Dictionary providerDict = slideProvidersDict.value(dictKey); - TileProvider* tileProvider = TileProvider::createFromDictionary(providerDict); - _slideProviders[i].reset(tileProvider); - } + ghoul::Dictionary slideProvidersDict = dictionary.value(KeySlideProviders); + _slideProviders.resize(slideProvidersDict.size()); + for (size_t i = 0; i < slideProvidersDict.size(); i++) { + std::string dictKey = std::to_string(i + 1); + ghoul::Dictionary providerDict = slideProvidersDict.value(dictKey); + _slideProviders[i] = TileProvider::createFromDictionary(providerDict); + } + _slideIndex.setMaxValue(_slideProviders.size() - 1); + addProperty(_slideIndex); +} + +Tile PresentationSlideProvider::getTile(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTile(tileIndex); + } + return Tile::TileUnavailable; - _slideIndex = std::make_unique("slideIndex", "slideIndex", 0, 0, _slideProviders.size()-1); - addProperty(_slideIndex.get()); - } +} - Tile PresentationSlideProvider::getTile(const TileIndex& tileIndex) { - if(tileIndex == _tileIndex){ - return slideProvider()->getTile(tileIndex); - } - return Tile::TileUnavailable; - - } +Tile PresentationSlideProvider::getDefaultTile() { + return _defaultProvider->getDefaultTile(); +} - Tile PresentationSlideProvider::getDefaultTile() { - return _defaultProvider->getDefaultTile(); +Tile::Status PresentationSlideProvider::getTileStatus(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTileStatus(tileIndex); } + return Tile::Status::Unavailable; +} - Tile::Status PresentationSlideProvider::getTileStatus(const TileIndex& tileIndex) { - if(tileIndex == _tileIndex){ - return slideProvider()->getTileStatus(tileIndex); - } - return Tile::Status::Unavailable; - } +TileDepthTransform PresentationSlideProvider::depthTransform() { + return slideProvider()->depthTransform(); +} - TileDepthTransform PresentationSlideProvider::depthTransform() { - slideProvider()->depthTransform(); - } +void PresentationSlideProvider::update() { + slideProvider()->update(); + _defaultProvider->update(); +} - void PresentationSlideProvider::update() { - slideProvider()->update(); - _defaultProvider->update(); +void PresentationSlideProvider::reset() { + for(auto& tp : _slideProviders){ + tp->reset(); } + _defaultProvider->reset(); +} - void PresentationSlideProvider::reset() { - for(auto& tp : _slideProviders){ - tp->reset(); - } - _defaultProvider->reset(); - } +int PresentationSlideProvider::maxLevel() { + return _defaultProvider->maxLevel(); +} - int PresentationSlideProvider::maxLevel() { - return _defaultProvider->maxLevel(); - } - - TileProvider* PresentationSlideProvider::slideProvider(){ - int maxIndex = (int)_slideProviders.size() - 1; - return _slideProviders[std::max(0, std::min(_slideIndex->value(), maxIndex))].get(); - } +TileProvider* PresentationSlideProvider::slideProvider(){ + int maxIndex = (int)_slideProviders.size() - 1; + return _slideProviders[std::max(0, std::min(_slideIndex.value(), maxIndex))].get(); +} - +} // namespace tileprovider } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h index 1d159b3689..0695501839 100644 --- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h @@ -38,34 +38,32 @@ namespace openspace { namespace globebrowsing { +namespace tileprovider { - using namespace ghoul::opengl; +class PresentationSlideProvider : public TileProvider { +public: + PresentationSlideProvider(const ghoul::Dictionary& dictionary); + PresentationSlideProvider(const std::string& imagePath); + virtual ~PresentationSlideProvider() { } - class PresentationSlideProvider : public TileProvider { - public: - - PresentationSlideProvider(const ghoul::Dictionary& dictionary); - PresentationSlideProvider(const std::string& imagePath); - virtual ~PresentationSlideProvider() { } + virtual Tile getTile(const TileIndex& tileIndex); + virtual Tile getDefaultTile(); + virtual Tile::Status getTileStatus(const TileIndex& index); + virtual TileDepthTransform depthTransform(); + virtual void update(); + virtual void reset(); + virtual int maxLevel(); - virtual Tile getTile(const TileIndex& tileIndex); - virtual Tile getDefaultTile(); - virtual Tile::Status getTileStatus(const TileIndex& index); - virtual TileDepthTransform depthTransform(); - virtual void update(); - virtual void reset(); - virtual int maxLevel(); +private: + TileProvider* slideProvider(); - private: - TileProvider* slideProvider(); - - - TileIndex _tileIndex; - std::unique_ptr _slideIndex; - std::vector> _slideProviders; - std::unique_ptr _defaultProvider; - }; + TileIndex _tileIndex; + properties::IntProperty _slideIndex; + std::vector> _slideProviders; + std::unique_ptr _defaultProvider; +}; +} // namespace tileprovider } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp index 42e1fd9455..272b8ec93a 100644 --- a/modules/globebrowsing/tile/tileprovider/tileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/tileprovider.cpp @@ -34,8 +34,6 @@ #include namespace { - const std::string _loggerCat = "TileProvider"; - const char* KeyType = "Type"; } @@ -50,18 +48,13 @@ std::unique_ptr TileProvider::createFromDictionary(const ghoul::Di dictionary.getValue(KeyType, type); auto factory = FactoryManager::ref().factory(); std::unique_ptr result = factory->create(type, dictionary); - - if (result == nullptr) { - LERROR("Failed creating TileProvider of type '" << type << "'"); - return nullptr; - } - return result; } -TileProvider::TileProvider() : - properties::PropertyOwner("tileProvider"), - _initialized(false) { +TileProvider::TileProvider() + : properties::PropertyOwner("tileProvider") + , _initialized(false) +{ initialize(); } From 42d3de6fce1bc3c0d54f5fec52c8612674c3178b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 14 Apr 2017 18:07:32 -0400 Subject: [PATCH 16/34] Cherry pick commit by Erik Broberg --- .../tile/tileprovider/presentationslideprovider.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp index bc38a37fff..3055d1b5bb 100644 --- a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp @@ -106,9 +106,11 @@ int PresentationSlideProvider::maxLevel() { return _defaultProvider->maxLevel(); } -TileProvider* PresentationSlideProvider::slideProvider(){ +TileProvider* PresentationSlideProvider::slideProvider() { int maxIndex = (int)_slideProviders.size() - 1; - return _slideProviders[std::max(0, std::min(_slideIndex.value(), maxIndex))].get(); + int clampedIndex = std::max(0, std::min(_slideIndex.value(), maxIndex)); + _slideIndex.setValue(clampedIndex); + return _slideProviders[clampedIndex].get(); } } // namespace tileprovider From e350033dbd5f6a7f0bcb07a74797f1d4611ee7ee Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 15 Apr 2017 14:54:49 -0400 Subject: [PATCH 17/34] Fix crash with multiply registered classes --- modules/globebrowsing/globebrowsingmodule.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 2b8cb05eff..71dc2c07c6 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -90,7 +90,7 @@ void GlobeBrowsingModule::internalInitialize() { CpuCap.installedMainMemory() * 0.25 * 1024 * 1024); // 25% of total RAM addPropertySubOwner(GdalWrapper::ref()); #endif // GLOBEBROWSING_USE_GDAL - }); + }); OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Deinitialize, [&]{ cache::MemoryAwareTileCache::ref().clear(); @@ -117,9 +117,6 @@ void GlobeBrowsingModule::internalInitialize() { fTileProvider->registerClass("SizeReference"); // Combining Tile Providers - fTileProvider->registerClass("ByLevel"); - fTileProvider->registerClass("ByIndex"); - fTileProvider->registerClass("ByLevel"); fTileProvider->registerClass("ByIndex"); fTileProvider->registerClass("PresentationSlides"); From c53bbf14beaf103255d2914682668fd80746eeb7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 10:55:37 -0400 Subject: [PATCH 18/34] Add property and configuration option to disable the scene tag on a master node (closing #247) --- apps/OpenSpace/main.cpp | 12 +++++----- .../openspace/engine/configurationmanager.h | 2 ++ include/openspace/engine/openspaceengine.h | 3 ++- include/openspace/rendering/renderengine.h | 4 +++- openspace.cfg | 1 + src/engine/configurationmanager.cpp | 1 + src/engine/configurationmanager_doc.inl | 10 +++++++++ src/engine/openspaceengine.cpp | 5 +++-- src/rendering/renderengine.cpp | 22 ++++++++++++++++--- 9 files changed, 46 insertions(+), 14 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index e6beaef342..5c31a05fde 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -175,13 +175,11 @@ void mainRenderFunc() { } #endif - if (SgctEngine->isMaster()) { - OsEng.render(viewMatrix, projectionMatrix); - } - else { - glm::mat4 sceneMatrix = SgctEngine->getModelMatrix(); - OsEng.render(viewMatrix * sceneMatrix, projectionMatrix); - } + OsEng.render( + SgctEngine->getModelMatrix(), + viewMatrix, + projectionMatrix + ); LTRACE("main::mainRenderFunc(end)"); } diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index f67b55bc6e..906704219b 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -104,6 +104,8 @@ public: /// The key that stores whether the master node should perform rendering just function /// as a pure manager static const std::string KeyDisableMasterRendering; + /// The key that stores whether the master node should apply the scene transformation + static const std::string KeyDisableSceneOnMaster; /// The key that sets the request URL that is used to request additional data to be /// downloaded static const std::string KeyDownloadRequestURL; diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index b13bc94b6e..dfc04f409b 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -88,7 +88,8 @@ public: void deinitialize(); void preSynchronization(); void postSynchronizationPreDraw(); - void render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix); + void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix); void postDraw(); void keyboardCallback(Key key, KeyModifier mod, KeyAction action); void charCallback(unsigned int codepoint, KeyModifier mod); diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index ca93e45031..bbd88093b8 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -98,7 +98,8 @@ public: void updateFade(); void updateRenderer(); void updateScreenSpaceRenderables(); - void render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix); + void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix); void renderScreenLog(); void renderShutdownInformation(float timer, float fullTime); @@ -211,6 +212,7 @@ private: properties::BoolProperty _applyWarping; properties::BoolProperty _showFrameNumber; properties::BoolProperty _disableMasterRendering; + properties::BoolProperty _disableSceneOnMaster; float _globalBlackOutFactor; float _fadeDuration; diff --git a/openspace.cfg b/openspace.cfg index 70735f840f..971434804f 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -88,6 +88,7 @@ return { -- OnScreenTextScaling = "framebuffer", -- PerSceneCache = true, -- DisableRenderingOnMaster = true, + KeyDisableSceneOnMaster = true, DownloadRequestURL = "http://data.openspaceproject.com/request.cgi", RenderingMethod = "Framebuffer" --RenderingMethod = "ABuffer" -- alternative: "Framebuffer" diff --git a/src/engine/configurationmanager.cpp b/src/engine/configurationmanager.cpp index dc532650d7..2c4d466603 100644 --- a/src/engine/configurationmanager.cpp +++ b/src/engine/configurationmanager.cpp @@ -73,6 +73,7 @@ const string ConfigurationManager::KeyCapabilitiesVerbosity = const string ConfigurationManager::KeyShutdownCountdown = "ShutdownCountdown"; const string ConfigurationManager::KeyDisableMasterRendering = "DisableRenderingOnMaster"; +const string ConfigurationManager::KeyDisableSceneOnMaster = "DisableSceneOnMaster"; const string ConfigurationManager::KeyDownloadRequestURL = "DownloadRequestURL"; const string ConfigurationManager::KeyPerSceneCache = "PerSceneCache"; const string ConfigurationManager::KeyRenderingMethod = "RenderingMethod"; diff --git a/src/engine/configurationmanager_doc.inl b/src/engine/configurationmanager_doc.inl index c00eb44b83..193299bd08 100644 --- a/src/engine/configurationmanager_doc.inl +++ b/src/engine/configurationmanager_doc.inl @@ -338,6 +338,16 @@ documentation::Documentation ConfigurationManager::Documentation() { "the master computer does not have the resources to render a scene.", Optional::Yes }, + { + ConfigurationManager::KeyDisableSceneOnMaster, + new BoolVerifier, + "Toggles whether a potential scene transformation matrix, for example as " + "specified in an SGCT configuration file, should apply to the master node. " + "With some configurations, applying such a transformation complicates the " + "interaction and it is thus desired to disable the transformation. The " + "default is false.", + Optional::Yes + }, { ConfigurationManager::KeyHttpProxy, new TableVerifier({ diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 43a410ff1f..c6d7147bba 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1028,11 +1028,12 @@ void OpenSpaceEngine::postSynchronizationPreDraw() { LTRACE("OpenSpaceEngine::postSynchronizationPreDraw(end)"); } -void OpenSpaceEngine::render(const glm::mat4& viewMatrix, +void OpenSpaceEngine::render(const glm::mat4& sceneMatrix, + const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) { LTRACE("OpenSpaceEngine::render(begin)"); - _renderEngine->render(viewMatrix, projectionMatrix); + _renderEngine->render(sceneMatrix, viewMatrix, projectionMatrix); for (const auto& func : _moduleCallbacks.render) { func(); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index d1cd2e6456..c8fda8c90e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -108,6 +108,7 @@ RenderEngine::RenderEngine() , _takeScreenshot("takeScreenshot", "Take Screenshot") , _showFrameNumber("showFrameNumber", "Show Frame Number", false) , _disableMasterRendering("disableMasterRendering", "Disable Master Rendering", false) + , _disableSceneOnMaster("disableSceneOnMaster", "Disable Scene on Master", false) , _shouldTakeScreenshot(false) , _renderer(nullptr) , _rendererImplementation(RendererImplementation::Invalid) @@ -165,6 +166,7 @@ RenderEngine::RenderEngine() addProperty(_showFrameNumber); addProperty(_disableMasterRendering); + addProperty(_disableSceneOnMaster); } void RenderEngine::setRendererFromString(const std::string& renderingMethod) { @@ -211,6 +213,12 @@ void RenderEngine::initialize() { ); } + if (confManager.hasKey(ConfigurationManager::KeyDisableSceneOnMaster)) { + _disableSceneOnMaster = confManager.value( + ConfigurationManager::KeyDisableSceneOnMaster + ); + } + _raycasterManager = std::make_unique(); _nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples(); @@ -385,12 +393,20 @@ void RenderEngine::updateFade() { -void RenderEngine::render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) { +void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix) +{ LTRACE("RenderEngine::render(begin)"); - _camera->sgctInternal.setViewMatrix(viewMatrix); + WindowWrapper& wrapper = OsEng.windowWrapper(); + + if (_disableSceneOnMaster && wrapper.isMaster()) { + _camera->sgctInternal.setViewMatrix(viewMatrix); + } + else { + _camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix); + } _camera->sgctInternal.setProjectionMatrix(projectionMatrix); - WindowWrapper& wrapper = OsEng.windowWrapper(); if (!(wrapper.isMaster() && _disableMasterRendering) && !wrapper.isGuiWindow()) { _renderer->render(_globalBlackOutFactor, _performanceManager != nullptr); From e12bb3ac7011cfaefb50c647f176fc6dfdd8420b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 13:39:11 -0400 Subject: [PATCH 19/34] Create MiniDump file on Windows in the case of a crash --- apps/OpenSpace/CMakeLists.txt | 2 +- apps/OpenSpace/main.cpp | 87 +++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/apps/OpenSpace/CMakeLists.txt b/apps/OpenSpace/CMakeLists.txt index 1e3deb9801..b0dd03eac9 100644 --- a/apps/OpenSpace/CMakeLists.txt +++ b/apps/OpenSpace/CMakeLists.txt @@ -69,7 +69,7 @@ add_executable(${APPLICATION_NAME} ${RESOURCE_FILE} ) target_include_directories(${APPLICATION_NAME} PUBLIC ${OPENSPACE_BASE_DIR}/include ${OPENVR_INCLUDE_DIRS} ${SGCT_OPENVR_INCLUDE_DIRECTORY}) -target_link_libraries(${APPLICATION_NAME} libOpenSpace ${OPENVR_LIBRARY}) +target_link_libraries(${APPLICATION_NAME} libOpenSpace ${OPENVR_LIBRARY} Dbghelp.lib) target_compile_definitions(${APPLICATION_NAME} PUBLIC ${SGCT_OPENVR_DEFINITIONS}) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 5c31a05fde..7768373196 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -32,6 +32,22 @@ #include +#ifdef WIN32 + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#endif // WIN32 + #ifdef OPENVR_SUPPORT #include #endif // OPENVR_SUPPORT @@ -43,6 +59,73 @@ namespace { const char* _loggerCat = "main"; sgct::Engine* SgctEngine; + +#ifdef WIN32 + +LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) { + SYSTEMTIME stLocalTime; + GetLocalTime(&stLocalTime); + + + LFATAL("Printing Stack Trace that lead to the crash:"); + std::vector stackTrace = ghoul::stackTrace(); + for (const std::string& s : stackTrace) { + LINFO(s); + } + + std::string dumpFile = fmt::format( + "OpenSpace_{}_{}_{}-{}-{}-{}-{}-{}-{}--{}--{}.dmp", + openspace::OPENSPACE_VERSION_MAJOR, + openspace::OPENSPACE_VERSION_MINOR, + openspace::OPENSPACE_VERSION_PATCH, + stLocalTime.wYear, + stLocalTime.wMonth, + stLocalTime.wDay, + stLocalTime.wHour, + stLocalTime.wMinute, + stLocalTime.wSecond, + GetCurrentProcessId(), + GetCurrentThreadId() + ); + + LINFO("Creating dump file: " << dumpFile); + + HANDLE hDumpFile = CreateFile( + dumpFile.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, + 0, + CREATE_ALWAYS, + 0, + 0 + ); + + MINIDUMP_EXCEPTION_INFORMATION exceptionParameter; + exceptionParameter.ThreadId = GetCurrentThreadId(); + exceptionParameter.ExceptionPointers = exceptionPointers; + exceptionParameter.ClientPointers = TRUE; + + BOOL success = MiniDumpWriteDump( + GetCurrentProcess(), + GetCurrentProcessId(), + hDumpFile, + MiniDumpWithDataSegs, + &exceptionParameter, + nullptr, + nullptr + ); + + if (success) { + LINFO("Created successfully"); + } + else { + LERROR("Dumpfile created unsuccessfully"); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +#endif // WIN32 #ifdef OPENVR_SUPPORT sgct::SGCTWindow* FirstOpenVRWindow = nullptr; @@ -395,6 +478,10 @@ int main_main(int argc, char** argv) { } // namespace int main(int argc, char** argv) { +#ifdef WIN32 + SetUnhandledExceptionFilter(generateMiniDump); +#endif // WIN32 + // If we are working as a developer, we don't want to catch the exceptions in order to // find the locations where the exceptions are raised. // If we are not in developer mode, we want to catch and at least log the error before From 79aad3e2453a6a87d55fb8ae5cf2c1945c20edb8 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 13:53:45 -0400 Subject: [PATCH 20/34] Only link against Dbghelp library in Visual Studio --- apps/OpenSpace/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/OpenSpace/CMakeLists.txt b/apps/OpenSpace/CMakeLists.txt index b0dd03eac9..8e0328a87d 100644 --- a/apps/OpenSpace/CMakeLists.txt +++ b/apps/OpenSpace/CMakeLists.txt @@ -69,11 +69,12 @@ add_executable(${APPLICATION_NAME} ${RESOURCE_FILE} ) target_include_directories(${APPLICATION_NAME} PUBLIC ${OPENSPACE_BASE_DIR}/include ${OPENVR_INCLUDE_DIRS} ${SGCT_OPENVR_INCLUDE_DIRECTORY}) -target_link_libraries(${APPLICATION_NAME} libOpenSpace ${OPENVR_LIBRARY} Dbghelp.lib) +target_link_libraries(${APPLICATION_NAME} libOpenSpace ${OPENVR_LIBRARY}) target_compile_definitions(${APPLICATION_NAME} PUBLIC ${SGCT_OPENVR_DEFINITIONS}) if (MSVC) + target_link_libraries(${APPLICATION_NAME} Dbghelp.lib) set_target_properties(${APPLICATION_NAME} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMTD.lib /NODEFAULTLIB:LIBCMT.lib" ) From acde7d2ff5aec2b39f11d8339ec1285354a32127 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 14:22:09 -0400 Subject: [PATCH 21/34] Update Ghoul repository (close #245) --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 200401261c..9007aabff2 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 200401261cba513fb1faa4b7e92bd213435625ad +Subproject commit 9007aabff2c5229a6ecf01251c87a43006474f0d From 87aa34f83e8f6ef2072fc6632b7fce340f5e61fc Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 14:45:14 -0400 Subject: [PATCH 22/34] Update Ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 9007aabff2..9788308e69 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 9007aabff2c5229a6ecf01251c87a43006474f0d +Subproject commit 9788308e69e69d9d4bf46cdb13e00e98c1686623 From dd32a812e1438a3956935029b80e4d9ecefe7418 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 15:00:15 -0400 Subject: [PATCH 23/34] Change tabs to spaces --- include/openspace/util/distanceconstants.h | 8 +-- .../cache/memoryawarecacheable.h | 18 ++--- .../cache/memoryawaretilecache.h | 2 +- .../globebrowsing/rendering/chunkrenderer.cpp | 22 +++--- .../rendering/layer/layerrendersettings.cpp | 22 +++--- .../rendering/layer/layerrendersettings.h | 2 +- modules/globebrowsing/tile/chunktile.h | 10 +-- .../tile/loadjob/tileloadjob.cpp | 4 +- .../rawtiledatareader/rawtiledatareader.cpp | 4 +- modules/globebrowsing/tile/tile.h | 70 +++++++++---------- .../tile/tileprovider/cachingtileprovider.cpp | 2 +- .../tileprovider/projectiontileprovider.cpp | 2 +- .../tile/tileprovider/singleimageprovider.cpp | 4 +- .../sizereferencetileprovider.cpp | 8 +-- .../tileprovider/temporaltileprovider.cpp | 41 ++++------- modules/globebrowsing/tile/tileselector.h | 6 +- .../tasks/kameleondocumentationtask.cpp | 2 +- src/rendering/renderable.cpp | 4 +- src/rendering/screenspacerenderable.cpp | 4 +- 19 files changed, 111 insertions(+), 124 deletions(-) diff --git a/include/openspace/util/distanceconstants.h b/include/openspace/util/distanceconstants.h index a7a368f7ba..daa2a1bba1 100644 --- a/include/openspace/util/distanceconstants.h +++ b/include/openspace/util/distanceconstants.h @@ -28,10 +28,10 @@ namespace openspace { namespace distanceconstants { - const float EarthRadius = 6371; - const float LightYear = 9.4607304725808E15; - const float AstronomicalUnit = 1.495978707E11; - const float Parsec = 3.0856776E16; + const float EarthRadius = 6371; + const float LightYear = 9.4607304725808E15; + const float AstronomicalUnit = 1.495978707E11; + const float Parsec = 3.0856776E16; } } diff --git a/modules/globebrowsing/cache/memoryawarecacheable.h b/modules/globebrowsing/cache/memoryawarecacheable.h index 6d97c5f2dd..ccd2c253c7 100644 --- a/modules/globebrowsing/cache/memoryawarecacheable.h +++ b/modules/globebrowsing/cache/memoryawarecacheable.h @@ -38,17 +38,17 @@ namespace cache { */ class MemoryAwareCacheable { public: - /** - * \param memoryImpact is the memory impact of the object. Can for example be given - * in kilobytes. - */ - MemoryAwareCacheable(size_t memoryImpact) : _memoryImpact(memoryImpact) {}; - ~MemoryAwareCacheable() {}; + /** + * \param memoryImpact is the memory impact of the object. Can for example be given + * in kilobytes. + */ + MemoryAwareCacheable(size_t memoryImpact) : _memoryImpact(memoryImpact) {}; + ~MemoryAwareCacheable() {}; - size_t memoryImpact() { return _memoryImpact; }; - + size_t memoryImpact() { return _memoryImpact; }; + protected: - size_t _memoryImpact; + size_t _memoryImpact; }; } // namespace cache diff --git a/modules/globebrowsing/cache/memoryawaretilecache.h b/modules/globebrowsing/cache/memoryawaretilecache.h index dadbcfd873..114be6f69b 100644 --- a/modules/globebrowsing/cache/memoryawaretilecache.h +++ b/modules/globebrowsing/cache/memoryawaretilecache.h @@ -103,7 +103,7 @@ private: static MemoryAwareTileCache* _singleton; MemoryAwareLRUCache _tileCache; - static std::mutex _mutexLock; + static std::mutex _mutexLock; }; } // namespace cache diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 77d12a1dbe..7c9b075bd8 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -107,18 +107,18 @@ ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData( std::to_string(debugProps.showHeightResolution)); pairs.emplace_back("showHeightIntensities", std::to_string(debugProps.showHeightIntensities)); - pairs.emplace_back("defaultHeight", std::to_string(Chunk::DEFAULT_HEIGHT)); + pairs.emplace_back("defaultHeight", std::to_string(Chunk::DEFAULT_HEIGHT)); - pairs.emplace_back("tilePaddingStart", - "ivec2(" + - std::to_string(RawTileDataReader::padding.start.x) + "," + - std::to_string(RawTileDataReader::padding.start.y) + ")" - ); - pairs.emplace_back("tilePaddingSizeDiff", - "ivec2(" + - std::to_string(RawTileDataReader::padding.numPixels.x) + "," + - std::to_string(RawTileDataReader::padding.numPixels.y) + ")" - ); + pairs.emplace_back("tilePaddingStart", + "ivec2(" + + std::to_string(RawTileDataReader::padding.start.x) + "," + + std::to_string(RawTileDataReader::padding.start.y) + ")" + ); + pairs.emplace_back("tilePaddingSizeDiff", + "ivec2(" + + std::to_string(RawTileDataReader::padding.numPixels.x) + "," + + std::to_string(RawTileDataReader::padding.numPixels.y) + ")" + ); // Now the shader program can be accessed ghoul::opengl::ProgramObject* programObject = diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp index 382618b454..19c7c9d62f 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp @@ -39,23 +39,23 @@ LayerRenderSettings::LayerRenderSettings() } float LayerRenderSettings::performLayerSettings(float currentValue) const { - float newValue = currentValue; + float newValue = currentValue; - newValue = glm::sign(newValue) * glm::pow(glm::abs(newValue), gamma); - newValue = newValue * multiplier; - newValue = newValue * opacity; + newValue = glm::sign(newValue) * glm::pow(glm::abs(newValue), gamma); + newValue = newValue * multiplier; + newValue = newValue * opacity; - return newValue; + return newValue; } glm::vec4 LayerRenderSettings::performLayerSettings(glm::vec4 currentValue) const { - glm::vec4 newValue = glm::vec4( - performLayerSettings(currentValue.r), - performLayerSettings(currentValue.g), - performLayerSettings(currentValue.b), - performLayerSettings(currentValue.a)); + glm::vec4 newValue = glm::vec4( + performLayerSettings(currentValue.r), + performLayerSettings(currentValue.g), + performLayerSettings(currentValue.b), + performLayerSettings(currentValue.a)); - return newValue; + return newValue; } } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.h b/modules/globebrowsing/rendering/layer/layerrendersettings.h index e880292c5d..a737f19b90 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.h +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.h @@ -41,7 +41,7 @@ struct LayerRenderSettings : public properties::PropertyOwner { /// This function matches the function with the same name in the /// shader code float performLayerSettings(float currentValue) const; - /// This function matches the function with the same name in the + /// This function matches the function with the same name in the /// shader code glm::vec4 performLayerSettings(glm::vec4 currentValue) const; }; diff --git a/modules/globebrowsing/tile/chunktile.h b/modules/globebrowsing/tile/chunktile.h index 82d5257642..3fa3bcde07 100644 --- a/modules/globebrowsing/tile/chunktile.h +++ b/modules/globebrowsing/tile/chunktile.h @@ -34,11 +34,11 @@ namespace openspace { namespace globebrowsing { struct ChunkTile { - ChunkTile() : tile(Tile::TileUnavailable) {}; - ChunkTile(Tile tile, TileUvTransform uvTransform, TileDepthTransform depthTransform) : - tile(tile), - uvTransform(uvTransform), - depthTransform(depthTransform) {}; + ChunkTile() : tile(Tile::TileUnavailable) {}; + ChunkTile(Tile tile, TileUvTransform uvTransform, TileDepthTransform depthTransform) : + tile(tile), + uvTransform(uvTransform), + depthTransform(depthTransform) {}; Tile tile; TileUvTransform uvTransform; diff --git a/modules/globebrowsing/tile/loadjob/tileloadjob.cpp b/modules/globebrowsing/tile/loadjob/tileloadjob.cpp index d4c2481e53..47c2e6030b 100644 --- a/modules/globebrowsing/tile/loadjob/tileloadjob.cpp +++ b/modules/globebrowsing/tile/loadjob/tileloadjob.cpp @@ -31,8 +31,8 @@ namespace globebrowsing { TileLoadJob::TileLoadJob(std::shared_ptr rawTileDataReader, const TileIndex& tileIndex) - : _rawTileDataReader(rawTileDataReader) - , _chunkIndex(tileIndex) {} + : _rawTileDataReader(rawTileDataReader) + , _chunkIndex(tileIndex) {} void TileLoadJob::execute() { _rawTile = _rawTileDataReader->readTileData(_chunkIndex); diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp index 60a65d8e11..79fe4d7c49 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp @@ -132,9 +132,9 @@ TileDepthTransform RawTileDataReader::getDepthTransform() const { std::array RawTileDataReader::getGeoTransform() const { std::array padfTransform; - + GeodeticPatch globalCoverage(Geodetic2(0,0), Geodetic2(M_PI / 2.0, M_PI)); - padfTransform[1] = Angle::fromRadians( + padfTransform[1] = Angle::fromRadians( globalCoverage.size().lon).asDegrees() / rasterXSize(); padfTransform[5] = -Angle::fromRadians( globalCoverage.size().lat).asDegrees() / rasterYSize(); diff --git a/modules/globebrowsing/tile/tile.h b/modules/globebrowsing/tile/tile.h index a5de61528e..211c11d9c1 100644 --- a/modules/globebrowsing/tile/tile.h +++ b/modules/globebrowsing/tile/tile.h @@ -51,42 +51,42 @@ public: * Describe if this Tile is good for usage (OK) or otherwise * the reason why it is not. */ - enum class Status { - /** - * E.g when texture data is not currently in memory. - * texture and tileMetaData are both null - */ - Unavailable, + enum class Status { + /** + * E.g when texture data is not currently in memory. + * texture and tileMetaData are both null + */ + Unavailable, - /** - * Can be set by TileProviders if the requested - * TileIndex is undefined for that particular - * provider. - * texture and metaData are both null - */ - OutOfRange, + /** + * Can be set by TileProviders if the requested + * TileIndex is undefined for that particular + * provider. + * texture and metaData are both null + */ + OutOfRange, - /** - * An IO Error happend - * texture and metaData are both null - */ - IOError, + /** + * An IO Error happend + * texture and metaData are both null + */ + IOError, - /** - * The Texture is uploaded to the GPU and good for usage. - * texture is defined. metaData may be defined. - */ - OK - }; + /** + * The Texture is uploaded to the GPU and good for usage. + * texture is defined. metaData may be defined. + */ + OK + }; Tile(std::shared_ptr texture, std::shared_ptr metaData, Status status); ~Tile() = default; - std::shared_ptr metaData() const { return _metaData; }; - Status status() const { return _status; }; - std::shared_ptr texture() const { return _texture; }; + std::shared_ptr metaData() const { return _metaData; }; + Status status() const { return _status; }; + std::shared_ptr texture() const { return _texture; }; /** * Instantiates a new tile with a single color. @@ -102,16 +102,16 @@ public: glm::vec2 sizeDiff, glm::uvec2 resolution, glm::vec2 tileUV); static glm::vec2 TileUvToTextureSamplePosition(const TileUvTransform& uvTransform, glm::vec2 tileUV, glm::uvec2 resolution); - /** - * A tile with status unavailable that any user can return to - * indicate that a tile was unavailable. - */ - static const Tile TileUnavailable; + /** + * A tile with status unavailable that any user can return to + * indicate that a tile was unavailable. + */ + static const Tile TileUnavailable; private: - std::shared_ptr _texture; - std::shared_ptr _metaData; - Status _status; + std::shared_ptr _texture; + std::shared_ptr _metaData; + Status _status; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp index 5ee9203cf6..11a9709c23 100644 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp @@ -50,7 +50,7 @@ namespace tileprovider { CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) : TileProvider(dictionary) , _framesSinceLastRequestFlush(0) - , _defaultTile(Tile::TileUnavailable) + , _defaultTile(Tile::TileUnavailable) { std::string name = "Name unspecified"; dictionary.getValue("Name", name); diff --git a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp index fb5063f7f6..944c4594ed 100644 --- a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp @@ -112,7 +112,7 @@ documentation::Documentation ProjectionTileProvider::Documentation() { ProjectionTileProvider::ProjectionTileProvider(const ghoul::Dictionary& dictionary) : _fboProgramObject(nullptr) , _capture(false) - , _defaultTile(Tile::TileUnavailable) + , _defaultTile(Tile::TileUnavailable) { ghoul::Dictionary geometryDictionary; diff --git a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp index 0f27c4e190..7b9a95ec7c 100644 --- a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp @@ -49,7 +49,7 @@ SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary) SingleImageProvider::SingleImageProvider(const std::string& imagePath) : _imagePath(imagePath) - , _tile(nullptr, nullptr, Tile::Status::Unavailable) + , _tile(nullptr, nullptr, Tile::Status::Unavailable) { reset(); } @@ -87,7 +87,7 @@ void SingleImageProvider::reset() { tileTexture->uploadTexture(); tileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - _tile = Tile(tileTexture, tileMetaData, tileStatus); + _tile = Tile(tileTexture, tileMetaData, tileStatus); } int SingleImageProvider::maxLevel() { diff --git a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp index 4adeb9fdca..552b9c9a11 100644 --- a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp @@ -46,7 +46,7 @@ namespace { } SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary) - : _backgroundTile(Tile::TileUnavailable) + : _backgroundTile(Tile::TileUnavailable) { _fontSize = 50; _font = OsEng.fontManager().font("Mono", _fontSize); @@ -58,9 +58,9 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di _ellipsoid = Ellipsoid(radii); auto backgroundTileStatus = Tile::Status::Unavailable; - std::shared_ptr backgroundTileTexture; + std::shared_ptr backgroundTileTexture; - std::string backgroundImagePath; + std::string backgroundImagePath; if (dictionary.getValue(KeyBackgroundImagePath, backgroundImagePath)) { using namespace ghoul::io; std::string imgAbsPath = absPath(backgroundImagePath); @@ -69,7 +69,7 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di backgroundTileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); backgroundTileStatus = Tile::Status::OK; } - _backgroundTile = Tile(backgroundTileTexture, nullptr, backgroundTileStatus); + _backgroundTile = Tile(backgroundTileTexture, nullptr, backgroundTileStatus); } void SizeReferenceTileProvider::renderText(const ghoul::fontrendering::FontRenderer& diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index c98c2b7ad8..256d4190d1 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -166,7 +166,7 @@ Tile TemporalTileProvider::getTile(const TileIndex& tileIndex) { } Tile TemporalTileProvider::getDefaultTile() { - return getTileProvider()->getDefaultTile(); + return getTileProvider()->getDefaultTile(); } int TemporalTileProvider::maxLevel() { @@ -228,33 +228,20 @@ std::shared_ptr TemporalTileProvider::getTileProvider(TimeKey time } std::shared_ptr TemporalTileProvider::initTileProvider(TimeKey timekey) { + static const std::vector AllowedToken = { + // From: http://www.gdal.org/frmt_wms.html + // @FRAGILE: What happens if a user specifies one of these as path tokens? + // ---abock + "${x}", + "${y}", + "${z}", + "${version}", + "${format}", + "${layer}" + }; + std::string gdalDatasetXml = getGdalDatasetXML(timekey); - try { - gdalDatasetXml = absPath(gdalDatasetXml); - } - catch (ghoul::filesystem::FileSystem::ResolveTokenException& e) { - const std::vector AllowedToken = { - // From: http://www.gdal.org/frmt_wms.html - // @FRAGILE: What happens if a user specifies one of these as path tokens? - // ---abock - "${x}", - "${y}", - "${z}", - "${version}", - "${format}", - "${layer}" - }; - - auto it = std::find(AllowedToken.begin(), AllowedToken.end(), e.token); - if (it == AllowedToken.end()) { - throw; - } - LINFOC( - "TemporalTileProvider", - fmt::format("Ignoring '{}' in absolute path resolve", e.token) - ); - } - + FileSys.expandPathTokens(gdalDatasetXml, AllowedToken); _initDict.setValue(KeyFilePath, gdalDatasetXml); auto tileProvider = std::make_shared(_initDict); diff --git a/modules/globebrowsing/tile/tileselector.h b/modules/globebrowsing/tile/tileselector.h index 9fe066deea..9c8cc49fe5 100644 --- a/modules/globebrowsing/tile/tileselector.h +++ b/modules/globebrowsing/tile/tileselector.h @@ -41,10 +41,10 @@ namespace tileselector { ChunkTile getHighestResolutionTile(const LayerGroup& layerGroup, const TileIndex& tileIndex); std::vector getTilesSortedByHighestResolution(const LayerGroup& layerGroup, - const TileIndex& tileIndex); + const TileIndex& tileIndex); std::vector > - getTilesAndSettingsSortedByHighestResolution(const LayerGroup& layerGroup, - const TileIndex& tileIndex); + getTilesAndSettingsSortedByHighestResolution(const LayerGroup& layerGroup, + const TileIndex& tileIndex); void ascendToParent(TileIndex& tileIndex, TileUvTransform& uv); diff --git a/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp index 3d0901b5f1..4cdad60f49 100644 --- a/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp @@ -109,7 +109,7 @@ void KameleonDocumentationTask::perform(const Task::ProgressCallback & progressC file.exceptions(~std::ofstream::goodbit); file.open(_outputPath); - std::stringstream html; + std::stringstream html; html << "\n" << "\n" << "\t\n" diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 7091917d7c..2d63892119 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -119,13 +119,13 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) addTag(std::move(tagName)); } else if (dictionary.hasKeyAndValue(KeyTag)) { ghoul::Dictionary tagNames = dictionary.value(KeyTag); - std::vector keys = tagNames.keys(); + std::vector keys = tagNames.keys(); std::string tagName; for (const std::string& key : keys) { tagName = tagNames.value(key); if (!tagName.empty()) addTag(std::move(tagName)); - } + } } if (_startTime != "" && _endTime != "") { diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index 18a2d4d8f1..f04461bf0b 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -152,13 +152,13 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary addTag(std::move(tagName)); } else if (dictionary.hasKeyAndValue(KeyTag)) { ghoul::Dictionary tagNames = dictionary.value(KeyTag); - std::vector keys = tagNames.keys(); + std::vector keys = tagNames.keys(); std::string tagName; for (const std::string& key : keys) { tagName = tagNames.value(key); if (!tagName.empty()) addTag(std::move(tagName)); - } + } } // Setting spherical/euclidean onchange handler From d5307faf3169fbac7432e5c3606a9171c02e888d Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 18:35:37 -0400 Subject: [PATCH 24/34] Clean earth.mod Add Sea Ice concentration --- data/scene/lodglobes/earth/earth.mod | 11 ++++---- ...al_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index c85eae9bd9..5660cff113 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -72,10 +72,6 @@ return { }, Enabled = true, }, - { - Name = "ESRI Imagery World 2D", - FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms", - }, { Name = "ESRI Imagery World", FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms" @@ -90,6 +86,11 @@ return { Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature", FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml", }, + { + Type = "Temporal", + Name = "Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration", + FilePath = "map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml", + }, -- { -- Type = "SingleImage", -- Name = "Debug Tiles", @@ -116,7 +117,7 @@ return { { Type = "Temporal", Name = "Temporal Earth at Night", - FilePath = "map_service_configs/GIBS/Temporal_VIIRS_CityLights.xml" + FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml" } }, WaterMasks = { diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml new file mode 100644 index 0000000000..c838cf1667 --- /dev/null +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml @@ -0,0 +1,28 @@ + + 2012-05-08 + + 1d + YYYY-MM-DD + + + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/AMSR2_Sea_Ice_Concentration_12km/default/${OpenSpaceTimeId}/2km/${z}/${y}/${x}.png + + + -180.0 + 90 + 396.0 + -198 + 8 + 2 + 1 + top + + EPSG:4326 + 512 + 512 + 3 + true + 400 + true + + From a0d30b80e5345d83c7da9a329625373122d8073b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 18:36:10 -0400 Subject: [PATCH 25/34] Add YYYYMMDD_hhmmss time format --- .../tile/tileprovider/temporaltileprovider.cpp | 14 +++++++++++++- .../tile/tileprovider/temporaltileprovider.h | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index 256d4190d1..dcd6893a82 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -269,6 +269,16 @@ std::string YYYY_MM_DD::stringify(const Time& t) const { return t.ISO8601().substr(0, 10); } +std::string YYYYMMDD_hhmmss::stringify(const Time& t) const { + std::string ts = t.ISO8601().substr(0, 19); + + // YYYY_MM_DDThh_mm_ss -> YYYYMMDD_hhmmss + ts.erase(std::remove(ts.begin(), ts.end(), '-'), ts.end()); + ts.erase(std::remove(ts.begin(), ts.end(), ':'), ts.end()); + replace(ts.begin(), ts.end(), 'T', '_'); + return ts; +} + std::string YYYY_MM_DDThhColonmmColonssZ::stringify(const Time& t) const { return t.ISO8601().substr(0, 19) + "Z"; } @@ -292,10 +302,12 @@ void TimeIdProviderFactory::init() { _timeIdProviderMap.insert(std::pair>( { "YYYY-MM-DDThh:mm:ssZ", std::make_unique() } )); - initialized = true; _timeIdProviderMap.insert(std::pair>( { "YYYY-MM-DDThh_mm_ssZ", std::make_unique() } )); + _timeIdProviderMap.insert(std::pair>( + { "YYYYMMDD_hhmmss", std::make_unique() } + )); initialized = true; } diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h index 410eb8912b..5b03c6306a 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.h @@ -66,6 +66,14 @@ struct YYYY_MM_DD : public TimeFormat { virtual std::string stringify(const Time& t) const; }; +/** +* Stringifies OpenSpace to the format "YYYYMMDD_hhmmss" +* Example: 20160908_230505 +*/ +struct YYYYMMDD_hhmmss : public TimeFormat { + virtual std::string stringify(const Time& t) const; +}; + /** * Stringifies OpenSpace to the format "YYYY-MM-DDThh:mm:ssZ" * Example: 2016-09-08T23:05:05Z From 78c109012a628444f6a8f368566f16438dbf87ca Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 18:36:29 -0400 Subject: [PATCH 26/34] Fix shader compiler error with screenspace renderable --- modules/base/shaders/screenspace_fs.glsl | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/base/shaders/screenspace_fs.glsl b/modules/base/shaders/screenspace_fs.glsl index 11aae2042f..22b09a4987 100644 --- a/modules/base/shaders/screenspace_fs.glsl +++ b/modules/base/shaders/screenspace_fs.glsl @@ -22,8 +22,6 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#version __CONTEXT__ - uniform sampler2D texture1; uniform float OcclusionDepth; uniform float Alpha; From 26e4354c40f4c9999fbad36281ada58fcacc20fb Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 18:36:50 -0400 Subject: [PATCH 27/34] Add cache to Moon textures --- .../lodglobes/moon/map_service_configs/OnMoonColor.xml | 6 ++++++ .../lodglobes/moon/map_service_configs/OnMoonHeight.xml | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml index 5ba619a141..6eae17b3cf 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml @@ -62,4 +62,10 @@ 512 512 + + + ./GDAL_Cache/OnMoonColor + 4 + .png + \ No newline at end of file diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml index 9fe0516d15..cdfd4114e1 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml @@ -16,4 +16,9 @@ 1 top + + ./GDAL_Cache/OnMoonHeight + 4 + .png + \ No newline at end of file From 0db98afe6e5c5996b7398394240a845ff6dcdba8 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 17 Apr 2017 18:38:36 -0400 Subject: [PATCH 28/34] - Enable caching of TileProviders at startup time - Enable path tokens in filename for temporal tile providers - Add support for relative paths in temporal tile providers - Set the GDAL temp dir to the BASE_PATH - --- .../gdalrawtiledatareader.cpp | 12 +++-- .../rawtiledatareader/gdalrawtiledatareader.h | 4 +- .../tile/rawtiledatareader/gdalwrapper.cpp | 4 ++ .../tile/tileprovider/cachingtileprovider.cpp | 19 ++++++- .../tileprovider/temporaltileprovider.cpp | 49 +++++++++++++++++++ .../tile/tileprovider/temporaltileprovider.h | 9 ++++ 6 files changed, 91 insertions(+), 6 deletions(-) diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp index ca1876576f..35a05f9f73 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp @@ -54,13 +54,16 @@ std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { ", " << pr.numPixels.y; } -GdalRawTileDataReader::GdalRawTileDataReader( - const std::string& filePath, const Configuration& config) +GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath, + const Configuration& config, + const std::string& baseDirectory) : RawTileDataReader(config) , _dataset(nullptr) { - _initData = { "", filePath, config.tilePixelSize, config.dataType }; - _initData.initDirectory = CPLGetCurrentDir(); + + std::string initDir = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory; + + _initData = { initDir, filePath, config.tilePixelSize, config.dataType }; ensureInitialized(); } @@ -303,6 +306,7 @@ GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath) std::string correctedPath = FileSystem::ref().pathByAppendingComponent( _initData.initDirectory, filePath ); + dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly); if (!dataset) { throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath); diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h index f44f410c79..338f3f5a90 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h @@ -60,8 +60,10 @@ public: * * \param filePath, a path to a specific file GDAL can read * \param config, Configuration used for initialization + * \param baseDirectory, the base directory to use in future loading operations */ - GdalRawTileDataReader(const std::string& filePath, const Configuration& config); + GdalRawTileDataReader(const std::string& filePath, const Configuration& config, + const std::string& baseDirectory = ""); virtual ~GdalRawTileDataReader() override; diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp index 570307eb8a..952dbb93f8 100644 --- a/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp @@ -105,6 +105,10 @@ GdalWrapper::GdalWrapper(size_t maximumCacheSize, "GDAL_DATA", absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str() ); + CPLSetConfigOption( + "CPL_TMPDIR", + absPath("${BASE_PATH}").c_str() + ); setGdalProxyConfiguration(); CPLSetErrorHandler(gdalErrorHandler); diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp index 11a9709c23..89638470ac 100644 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp @@ -40,7 +40,9 @@ namespace { const char* KeyDoPreProcessing = "DoPreProcessing"; const char* KeyTilePixelSize = "TilePixelSize"; const char* KeyFilePath = "FilePath"; + const char* KeyBasePath = "BasePath"; const char* KeyFlushInterval = "FlushInterval"; + const char* KeyPreCacheLevel = "PreCacheLevel"; } namespace openspace { @@ -84,9 +86,12 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) framesUntilRequestFlush); } + std::string basePath; + dictionary.getValue(KeyBasePath, basePath); + // Initialize instance variables #ifdef GLOBEBROWSING_USE_GDAL - auto tileDataset = std::make_shared(filePath, config); + auto tileDataset = std::make_shared(filePath, config, basePath); #else // GLOBEBROWSING_USE_GDAL auto tileDataset = std::make_shared(filePath, config); #endif // GLOBEBROWSING_USE_GDAL @@ -99,6 +104,18 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) _asyncTextureDataProvider = std::make_shared( tileDataset, threadPool); _framesUntilRequestFlush = framesUntilRequestFlush; + + if (dictionary.hasKeyAndValue(KeyPreCacheLevel)) { + int preCacheLevel = static_cast(dictionary.value(KeyPreCacheLevel)); + LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'"); + for (int level = 0; level <= preCacheLevel; ++level) { + for (int x = 0; x <= level * 2; ++x) { + for (int y = 0; y <= level; ++y) { + _asyncTextureDataProvider->enqueueTileIO({ x, y, level }); + } + } + } + } } CachingTileProvider::CachingTileProvider( diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index dcd6893a82..4e8fbb2d28 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -41,8 +41,11 @@ namespace { const char* KeyDoPreProcessing = "DoPreProcessing"; const char* KeyMinimumPixelSize = "MinimumPixelSize"; const char* KeyFilePath = "FilePath"; + const char* KeyBasePath = "BasePath"; const char* KeyCacheSize = "CacheSize"; const char* KeyFlushInterval = "FlushInterval"; + const char* KeyPreCacheStartTime = "PreCacheStartTime"; + const char* KeyPreCacheEndTime = "PreCacheEndTime"; } namespace openspace { @@ -64,6 +67,8 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); } + _datasetFile = absPath(_datasetFile); + std::ifstream in(_datasetFile.c_str()); if (!in.is_open()) { throw ghoul::FileNotFoundError(_datasetFile); @@ -74,7 +79,29 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) std::istreambuf_iterator(in), (std::istreambuf_iterator()) ); + + _initDict.setValue( + KeyBasePath, + ghoul::filesystem::File(_datasetFile).directoryName() + ); + _gdalXmlTemplate = consumeTemporalMetaData(xml); + + const bool hasStart = dictionary.hasKeyAndValue(KeyPreCacheStartTime); + const bool hasEnd = dictionary.hasKeyAndValue(KeyPreCacheEndTime); + if (hasStart && hasEnd) { + const std::string start = dictionary.value(KeyPreCacheStartTime); + const std::string end = dictionary.value(KeyPreCacheEndTime); + std::vector