void InteractionHandler::setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict) { bool readSuccessful = true; std::string focus; glm::dvec3 cameraPosition; glm::dvec4 cameraRotation; // Need to read the quaternion as a vector first. readSuccessful &= cameraDict.getValue(KeyFocus, focus); readSuccessful &= cameraDict.getValue(KeyPosition, cameraPosition); readSuccessful &= cameraDict.getValue(KeyRotation, cameraRotation); if (!readSuccessful) { throw ghoul::RuntimeError( "Position, Rotation and Focus need to be defined for camera dictionary."); } SceneGraphNode* node = sceneGraphNode(focus); if (!node) { throw ghoul::RuntimeError( "Could not find a node in scenegraph called '" + focus + "'"); } // Set state setFocusNode(node); _camera->setPositionVec3(cameraPosition); _camera->setRotation(glm::dquat( cameraRotation.x, cameraRotation.y, cameraRotation.z, cameraRotation.w)); }
InteractionHandler::InteractionHandler() : properties::PropertyOwner() , _camera(nullptr) , _focusNode(nullptr) , _deltaTime(0.0) //, _validKeyLua(false) , _controllerSensitivity(1.f) , _invertRoll(true) , _invertRotation(false) , _keyboardController(nullptr) , _mouseController(nullptr) , _origin("origin", "Origin", "") , _coordinateSystem("coordinateSystem", "Coordinate System", "") , _currentKeyframeTime(-1.0) { setName("Interaction"); _origin.onChange([this](){ SceneGraphNode* node = sceneGraphNode(_origin.value()); if (!node) { LWARNING("Could not find a node in scenegraph called '" << _origin.value() <<"'"); return; } setFocusNode(node); }); addProperty(_origin); _coordinateSystem.onChange([this](){ OsEng.renderEngine().changeViewPoint(_coordinateSystem.value()); }); addProperty(_coordinateSystem); }
properties::Property* property(const std::string& uri) { properties::Property* globalProp = OsEng.globalPropertyOwner().property(uri); if (globalProp) { return globalProp; } else { // The URI consists of the following form at this stage: // <node name>.{<property owner>.}^(0..n)<property id> const size_t nameSeparator = uri.find(properties::PropertyOwner::URISeparator); if (nameSeparator == std::string::npos) { LERROR("Malformed URI '" << uri << "': At least one '" << nameSeparator << "' separator must be present."); return nullptr; } const std::string nameUri = uri.substr(0, nameSeparator); const std::string remainingUri = uri.substr(nameSeparator + 1); SceneGraphNode* node = sceneGraphNode(nameUri); if (node) { properties::Property* property = node->property(remainingUri); return property; } std::shared_ptr<ScreenSpaceRenderable> ssr = OsEng.renderEngine().screenSpaceRenderable(nameUri); if(ssr){ properties::Property* property = ssr->property(remainingUri); return property; } #ifdef OPENSPACE_MODULE_ISWA_ENABLED std::shared_ptr<IswaBaseGroup> group = IswaManager::ref().iswaGroup(nameUri); if(group){ properties::Property* property = group->property(remainingUri); return property; } #endif LERROR("Node or ScreenSpaceRenderable' " << nameUri << "' did not exist"); return nullptr; } }
bool SceneGraph::loadFromFile(const std::string& sceneDescription) { clear(); // Move this to a later stage to retain a proper scenegraph when the loading fails ---abock std::string absSceneFile = absPath(sceneDescription); // See if scene file exists if (!FileSys.fileExists(absSceneFile, true)) { LERROR("Could not load scene file '" << absSceneFile << "'. " << "File not found"); return false; } LINFO("Loading SceneGraph from file '" << absSceneFile << "'"); // Load dictionary ghoul::Dictionary sceneDictionary; try { ghoul::lua::loadDictionaryFromFile(absSceneFile, sceneDictionary); } catch (...) { return false; } std::string sceneDescriptionDirectory = ghoul::filesystem::File(absSceneFile, true).directoryName(); std::string sceneDirectory("."); sceneDictionary.getValue(KeyPathScene, sceneDirectory); // The scene path could either be an absolute or relative path to the description // paths directory std::string relativeCandidate = sceneDescriptionDirectory + ghoul::filesystem::FileSystem::PathSeparator + sceneDirectory; std::string absoluteCandidate = absPath(sceneDirectory); if (FileSys.directoryExists(relativeCandidate)) sceneDirectory = relativeCandidate; else if (FileSys.directoryExists(absoluteCandidate)) sceneDirectory = absoluteCandidate; else { LERROR("The '" << KeyPathScene << "' pointed to a " "path '" << sceneDirectory << "' that did not exist"); return false; } ghoul::Dictionary moduleDictionary; bool success = sceneDictionary.getValue(KeyModules, moduleDictionary); if (!success) // There are no modules that are loaded return true; lua_State* state = ghoul::lua::createNewLuaState(); OsEng.scriptEngine().initializeLuaState(state); // Get the common directory bool commonFolderSpecified = sceneDictionary.hasKey(KeyCommonFolder); bool commonFolderCorrectType = sceneDictionary.hasKeyAndValue<std::string>(KeyCommonFolder); if (commonFolderSpecified) { if (commonFolderCorrectType) { std::string commonFolder = sceneDictionary.value<std::string>(KeyCommonFolder); std::string fullCommonFolder = FileSys.pathByAppendingComponent( sceneDirectory, commonFolder ); if (!FileSys.directoryExists(fullCommonFolder)) LERROR("Specified common folder '" << fullCommonFolder << "' did not exist"); else { if (!commonFolder.empty()) { FileSys.registerPathToken(_commonModuleToken, commonFolder); size_t nKeys = moduleDictionary.size(); moduleDictionary.setValue(std::to_string(nKeys + 1), commonFolder); } } } else LERROR("Specification for 'common' folder has invalid type"); } std::vector<std::string> keys = moduleDictionary.keys(); std::map<std::string, std::vector<std::string>> dependencies; std::map<std::string, std::string> parents; _rootNode = new SceneGraphNode; _rootNode->setName(SceneGraphNode::RootNodeName); SceneGraphNodeInternal* internalRoot = new SceneGraphNodeInternal; internalRoot->node = _rootNode; _nodes.push_back(internalRoot); std::sort(keys.begin(), keys.end()); ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory(); for (const std::string& key : keys) { std::string moduleName = moduleDictionary.value<std::string>(key); std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, moduleName); if (!FileSys.directoryExists(modulePath)) { LERROR("Could not load module '" << moduleName << "'. Directory did not exist"); continue; } std::string moduleFile = FileSys.pathByAppendingComponent( modulePath, moduleName + _moduleExtension ); if (!FileSys.fileExists(moduleFile)) { LERROR("Could not load module file '" << moduleFile << "'. File did not exist"); continue; } ghoul::Dictionary moduleDictionary; try { ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); } catch (...) { continue; } std::vector<std::string> keys = moduleDictionary.keys(); for (const std::string& key : keys) { if (!moduleDictionary.hasValue<ghoul::Dictionary>(key)) { LERROR("SceneGraphNode '" << key << "' is not a table in module '" << moduleFile << "'"); continue; } ghoul::Dictionary element; std::string nodeName; std::string parentName; moduleDictionary.getValue(key, element); element.setValue(KeyPathModule, modulePath); element.getValue(SceneGraphNode::KeyName, nodeName); element.getValue(SceneGraphNode::KeyParentName, parentName); FileSys.setCurrentDirectory(modulePath); SceneGraphNode* node = SceneGraphNode::createFromDictionary(element); if (node == nullptr) { LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'"); continue; //clear(); //return false; } dependencies[nodeName].push_back(parentName); parents[nodeName] = parentName; // Also include loaded dependencies if (element.hasKey(SceneGraphNode::KeyDependencies)) { if (element.hasValue<ghoul::Dictionary>(SceneGraphNode::KeyDependencies)) { ghoul::Dictionary nodeDependencies; element.getValue(SceneGraphNode::KeyDependencies, nodeDependencies); std::vector<std::string> keys = nodeDependencies.keys(); for (const std::string& key : keys) { std::string value = nodeDependencies.value<std::string>(key); dependencies[nodeName].push_back(value); } } else { LERROR("Dependencies did not have the corrent type"); } } SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal; internalNode->node = node; _nodes.push_back(internalNode); } } ghoul::lua::destroyLuaState(state); FileSys.setCurrentDirectory(oldDirectory); for (SceneGraphNodeInternal* node : _nodes) { if (node->node == _rootNode) continue; std::string parent = parents[node->node->name()]; SceneGraphNode* parentNode = sceneGraphNode(parent); if (parentNode == nullptr) { LERROR("Could not find parent '" << parent << "' for '" << node->node->name() << "'"); } node->node->setParent(parentNode); } // Setup dependencies for (SceneGraphNodeInternal* node : _nodes) { std::vector<std::string> nodeDependencies = dependencies[node->node->name()]; for (const std::string& dep : nodeDependencies) { SceneGraphNodeInternal* n = nodeByName(dep); if (n == nullptr) { LERROR("Dependent node '" << dep << "' was not loaded for '" <<node->node->name() << "'"); continue; } node->outgoingEdges.push_back(n); n->incomingEdges.push_back(node); } } std::vector<SceneGraphNodeInternal*> nodesToDelete; for (SceneGraphNodeInternal* node : _nodes) { if (!nodeIsDependentOnRoot(node)) { LERROR("Node '" << node->node->name() << "' has no direct connection to Root."); nodesToDelete.push_back(node); } } for (SceneGraphNodeInternal* node : nodesToDelete) { _nodes.erase(std::find(_nodes.begin(), _nodes.end(), node)); delete node; } bool s = sortTopologically(); if (!s) { LERROR("Topological sort failed"); return false; } return true; }
Renderable* renderable(const std::string& name) { SceneGraphNode* node = sceneGraphNode(name); return node->renderable(); }
// InteractionHandler InteractionHandler::InteractionHandler() : _origin("origin", "Origin", "") , _coordinateSystem("coordinateSystem", "Coordinate System", "") , _rotationalFriction("rotationalFriction", "Rotational Friction", true) , _horizontalFriction("horizontalFriction", "Horizontal Friction", true) , _verticalFriction("verticalFriction", "Vertical Friction", true) , _sensitivity("sensitivity", "Sensitivity", 0.002, 0.0001, 0.02) , _rapidness("rapidness", "Rapidness", 1, 0.1, 60) { setName("Interaction"); _origin.onChange([this]() { SceneGraphNode* node = sceneGraphNode(_origin.value()); if (!node) { LWARNING("Could not find a node in scenegraph called '" << _origin.value() << "'"); return; } setFocusNode(node); resetCameraDirection(); }); _coordinateSystem.onChange([this]() { OsEng.renderEngine().changeViewPoint(_coordinateSystem.value()); }); // Create the interactionModes _inputState = std::make_unique<InputState>(); // Inject the same mouse states to both orbital and global interaction mode _mouseStates = std::make_unique<OrbitalInteractionMode::MouseStates>(0.002, 1); _interactionModes.insert( std::pair<std::string, std::shared_ptr<InteractionMode>>( "Orbital", std::make_shared<OrbitalInteractionMode>(_mouseStates) )); _interactionModes.insert( std::pair<std::string, std::shared_ptr<InteractionMode>>( "GlobeBrowsing", std::make_shared<GlobeBrowsingInteractionMode>(_mouseStates) )); // Set the interactionMode _currentInteractionMode = _interactionModes["Orbital"]; // Define lambda functions for changed properties _rotationalFriction.onChange([&]() { _mouseStates->setRotationalFriction(_rotationalFriction); }); _horizontalFriction.onChange([&]() { _mouseStates->setHorizontalFriction(_horizontalFriction); }); _verticalFriction.onChange([&]() { _mouseStates->setVerticalFriction(_verticalFriction); }); _sensitivity.onChange([&]() { _mouseStates->setSensitivity(_sensitivity); }); _rapidness.onChange([&]() { _mouseStates->setVelocityScaleFactor(_rapidness); }); // Add the properties addProperty(_origin); addProperty(_coordinateSystem); addProperty(_rotationalFriction); addProperty(_horizontalFriction); addProperty(_verticalFriction); addProperty(_sensitivity); addProperty(_rapidness); }