SceneGraphNode* SceneGraphNode::getLeftSibling(SceneGraphNode *root, SceneGraphNode *target) { if (root == NULL || target == NULL) return NULL; SceneGraphNode *previous = NULL; std::queue<SceneGraphNode *> queue; queue.push(root); root->_marked = true; while (!queue.empty()) { SceneGraphNode *t = queue.front(); queue.pop(); if (t->isEqual(target)) { break; } else { previous = t; } std::vector<SceneGraphNode *>::iterator itr; for (itr = t->children.begin(); itr != t->children.end(); ++itr) { if (!(*itr)->_marked) { (*itr)->_marked = true; queue.push(*itr); } } } _clearMarked(root); return previous; }
SceneGraphNode* SceneGraphNode::getRightSibling(SceneGraphNode *root, SceneGraphNode *target) { if (root == NULL || target == NULL) return NULL; SceneGraphNode *result = NULL; bool foundSelf = false; std::queue<SceneGraphNode *> queue; queue.push(root); root->_marked = true; while (!queue.empty()) { SceneGraphNode *t = queue.front(); queue.pop(); if (foundSelf) { result = t; break; } if (t->isEqual(target)) { foundSelf = true; } std::vector<SceneGraphNode *>::iterator itr; for (itr = t->children.begin(); itr != t->children.end(); ++itr) { if (!(*itr)->_marked) { (*itr)->_marked = true; queue.push(*itr); } } } _clearMarked(root); return result; }
void SceneGraphEditor::updateNode(SceneGraphNode* pnode, int uid, int xpos, int ypos) { feather::status e; unsigned int nid = feather::qml::command::get_node_id(uid,e); // if the node is already in the draw list, don't add a new one SceneGraphNode *node = getNode(uid); if(!node){ std::cout << "ADDING NODE TO SG EDITOR\n"; node = new SceneGraphNode(uid,nid,this); m_nodes.push_back(node); // setup the node qt connections connect(node,SIGNAL(ConnClicked(Qt::MouseButton,SceneGraphConnection::Connection,int,int)),this,SLOT(ConnOption(Qt::MouseButton,SceneGraphConnection::Connection,int,int))); connect(node,SIGNAL(nodePressed(Qt::MouseButton,int,int)),this,SLOT(nodePressed(Qt::MouseButton,int,int))); // place the node in the scenegraph node->setX(xpos); node->setY(ypos); // get the connected nodes std::vector<int> cuids; feather::qml::command::get_node_connected_uids(uid,cuids); // add a link for each connection between the two nodes int ystep=0; for(auto c : cuids) { // add the child node to draw list and get it's links updateNode(node, c, xpos+200, ypos+ystep); ystep+=node->height()+40; } }
void annihilate(SceneGraphNode* root, bool deleteMeshes) { vector<SceneGraphNode*> victims; stack<SceneGraphNode*> nodeStack; stack<int> counterStack; victims.clear(); nodeStack.push(root); counterStack.push(-1); enlist(root, victims, deleteMeshes); while (nodeStack.size()>0) { SceneGraphNode * node = nodeStack.top(); int childIndex = counterStack.top(); vector<SceneGraphNode*>* children = node->getChildren(); int childCount = children->size(); if (childIndex < (childCount - 1)) { childIndex++; //counterStack.set(counterStack.size() - 1, childIndex); counterStack.pop(); counterStack.push(childIndex); SceneGraphNode * child = node->getChildren()->at(childIndex); nodeStack.push(child); counterStack.push(-1); enlist(child, victims, deleteMeshes); } else { nodeStack.pop(); counterStack.pop(); } } for (int i=0; i<victims.size(); i++) { SceneGraphNode* victim = victims.at(i); //Why do we need this? Because Objective-/C/C++ was not designed properly, that's why! if (typeid(*victim)==typeid(TransformNode)) { delete (TransformNode*) victim; } else if (typeid(*victim)==typeid(LightNode)) { delete (LightNode*) victim; } else if (typeid(*victim)==typeid(MeshNode)) { delete (MeshNode*) victim; } else { delete victim; } } }
/// After we loaded our mesh, we need to add submeshes as children nodes void Mesh::postLoad(SceneGraphNode& sgn) { static const U32 normalMask = to_base(ComponentType::NAVIGATION) | to_base(ComponentType::TRANSFORM) | to_base(ComponentType::BOUNDS) | to_base(ComponentType::RENDERING) | to_base(ComponentType::NAVIGATION); static const U32 skinnedMask = normalMask | to_base(ComponentType::ANIMATION) | to_base(ComponentType::INVERSE_KINEMATICS) | to_base(ComponentType::RAGDOLL); SceneGraphNodeDescriptor subMeshDescriptor; subMeshDescriptor._usageContext = sgn.usageContext(); subMeshDescriptor._instanceCount = sgn.instanceCount(); for (const SubMesh_ptr& submesh : _subMeshList) { subMeshDescriptor._node = submesh; subMeshDescriptor._componentMask = submesh->getObjectFlag(ObjectFlag::OBJECT_FLAG_SKINNED) ? skinnedMask : normalMask; if (sgn.get<RigidBodyComponent>() != nullptr) { subMeshDescriptor._componentMask |= to_base(ComponentType::RIGID_BODY); } subMeshDescriptor._name = Util::StringFormat("%s_%d", sgn.name().c_str(), submesh->getID()); SceneGraphNode* subSGN = sgn.addNode(subMeshDescriptor); if (BitCompare(subMeshDescriptor._componentMask, ComponentType::RIGID_BODY)) { subSGN->get<RigidBodyComponent>()->physicsGroup(sgn.get<RigidBodyComponent>()->physicsGroup()); } RenderingComponent* rComp = sgn.get<RenderingComponent>(); if (rComp != nullptr) { RenderingComponent* subRComp = subSGN->get<RenderingComponent>(); for (auto it : rComp->getShaderBuffers()) { subRComp->addShaderBuffer(it); } } } sgn.get<BoundsComponent>()->ignoreTransform(true); Object3D::postLoad(sgn); }
/// Called from SceneGraph "sceneUpdate" void Mesh::sceneUpdate(const U64 deltaTimeUS, SceneGraphNode& sgn, SceneState& sceneState) { if (getObjectFlag(ObjectFlag::OBJECT_FLAG_SKINNED)) { sgn.forEachChild([deltaTimeUS](const SceneGraphNode& child) { AnimationComponent* animComp = child.get<AnimationComponent>(); // Not all submeshes are necessarily animated. (e.g. flag on the back of a character) if (animComp) { animComp->incParentTimeStamp(deltaTimeUS); } }); } Object3D::sceneUpdate(deltaTimeUS, sgn, sceneState); }
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; } }
void SubMesh::buildDrawCommands(SceneGraphNode& sgn, RenderStagePass renderStagePass, RenderPackage& pkgInOut) { GenericDrawCommand cmd = {}; cmd._primitiveType = PrimitiveType::TRIANGLES, cmd._cmd.firstIndex = getGeometryVB()->getPartitionOffset(_geometryPartitionID); cmd._cmd.indexCount = getGeometryVB()->getPartitionIndexCount(_geometryPartitionID); cmd._cmd.primCount = sgn.instanceCount(); cmd._sourceBuffer = _parentMesh->getGeometryVB(); cmd._bufferIndex = renderStagePass.index(); enableOption(cmd, CmdRenderOptions::RENDER_INDIRECT); GFX::DrawCommand drawCommand; drawCommand._drawCommands.push_back(cmd); pkgInOut.addDrawCommand(drawCommand); Object3D::buildDrawCommands(sgn, renderStagePass, pkgInOut); }
void RenderablePlaneProjection::updatePlane(const Image img, double currentTime) { std::string frame; std::vector<glm::dvec3> bounds; glm::dvec3 boresight; std::string target = _defaultTarget; // Turned on if the plane should be attached to the closest target, // rather than the target specified in img //if (!_moving) { // target = findClosestTarget(currentTime); //} if (img.path != "") target = img.target; setTarget(target); try { SpiceManager::FieldOfViewResult res = SpiceManager::ref().fieldOfView(_instrument); frame = std::move(res.frameName); bounds = std::move(res.bounds); boresight = std::move(res.boresightVector); } catch (const SpiceManager::SpiceException& e) { LERROR(e.what()); } double lt; psc projection[4]; glm::dvec3 vecToTarget = SpiceManager::ref().targetPosition( _target.body, _spacecraft, GalacticFrame, { SpiceManager::AberrationCorrection::Type::ConvergedNewtonianStellar, SpiceManager::AberrationCorrection::Direction::Reception }, currentTime, lt ); // The apparent position, CN+S, makes image align best with target for (int j = 0; j < bounds.size(); ++j) { bounds[j] = SpiceManager::ref().frameTransformationMatrix(frame, GalacticFrame, currentTime) * bounds[j]; glm::dvec3 cornerPosition = glm::proj(vecToTarget, bounds[j]); if (!_moving) { cornerPosition -= vecToTarget; } cornerPosition = SpiceManager::ref().frameTransformationMatrix(GalacticFrame, _target.frame, currentTime) * cornerPosition; projection[j] = PowerScaledCoordinate::CreatePowerScaledCoordinate(cornerPosition[0], cornerPosition[1], cornerPosition[2]); projection[j][3] += 3; } if (!_moving) { SceneGraphNode* thisNode = OsEng.renderEngine().scene()->sceneGraphNode(_name); SceneGraphNode* newParent = OsEng.renderEngine().scene()->sceneGraphNode(_target.node); if (thisNode != nullptr && newParent != nullptr) thisNode->setParent(newParent); } const GLfloat vertex_data[] = { // square of two triangles drawn within fov in target coordinates // x y z w s t projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 1 projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper right 2 projection[2][0], projection[2][1], projection[2][2], projection[2][3], 0, 0, // Upper left 3 projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 4 = 1 projection[0][0], projection[0][1], projection[0][2], projection[0][3], 1, 1, // Lower right 5 projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper left 6 = 2 }; glBindVertexArray(_quad); // bind array glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(0)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(sizeof(GLfloat) * 4)); if (!_moving && img.path != "") { _texturePath = img.path; loadTexture(); } }
void PropertyWindow::drawInternal() { bool hasSelections = !selections().empty(); Camera* selectedCamera = Attorney::EditorPropertyWindow::getSelectedCamera(_parent); if (selectedCamera != nullptr) { if (ImGui::CollapsingHeader(selectedCamera->resourceName().c_str())) { vec3<F32> eye = selectedCamera->getEye(); if (ImGui::InputFloat3("Eye", eye._v)) { selectedCamera->setEye(eye); } vec3<F32> euler = selectedCamera->getEuler(); if (ImGui::InputFloat3("Euler", euler._v)) { selectedCamera->setEuler(euler); } F32 aspect = selectedCamera->getAspectRatio(); if (ImGui::InputFloat("Aspect", &aspect)) { selectedCamera->setAspectRatio(aspect); } F32 horizontalFoV = selectedCamera->getHorizontalFoV(); if (ImGui::InputFloat("FoV (horizontal)", &horizontalFoV)) { selectedCamera->setHorizontalFoV(horizontalFoV); } vec2<F32> zPlanes = selectedCamera->getZPlanes(); if (ImGui::InputFloat2("zPlanes", zPlanes._v)) { if (selectedCamera->isOrthoProjected()) { selectedCamera->setProjection(selectedCamera->orthoRect(), zPlanes); } else { selectedCamera->setProjection(selectedCamera->getAspectRatio(), selectedCamera->getVerticalFoV(), zPlanes); } } if (selectedCamera->isOrthoProjected()) { vec4<F32> orthoRect = selectedCamera->orthoRect(); if (ImGui::InputFloat4("Ortho", orthoRect._v)) { selectedCamera->setProjection(orthoRect, selectedCamera->getZPlanes()); } } ImGui::Text("View Matrix"); ImGui::Spacing(); mat4<F32> viewMatrix = selectedCamera->getViewMatrix(); EditorComponentField worldMatrixField = { GFX::PushConstantType::MAT4, EditorComponentFieldType::PUSH_TYPE, true, "View Matrix", &viewMatrix }; processBasicField(worldMatrixField); ImGui::Text("Projection Matrix"); ImGui::Spacing(); mat4<F32> projMatrix = selectedCamera->getProjectionMatrix(); EditorComponentField projMatrixField = { GFX::PushConstantType::MAT4, EditorComponentFieldType::PUSH_TYPE, true, "Projection Matrix", &projMatrix }; processBasicField(projMatrixField); } } else if (hasSelections) { const F32 smallButtonWidth = 60.0f; F32 xOffset = ImGui::GetWindowSize().x * 0.5f - smallButtonWidth; const vector<I64>& crtSelections = selections(); static bool closed = false; for (I64 nodeGUID : crtSelections) { SceneGraphNode* sgnNode = node(nodeGUID); if (sgnNode != nullptr) { bool enabled = sgnNode->isActive(); if (ImGui::Checkbox(sgnNode->name().c_str(), &enabled)) { sgnNode->setActive(enabled); } ImGui::Separator(); vectorFast<EditorComponent*>& editorComp = Attorney::SceneGraphNodeEditor::editorComponents(*sgnNode); for (EditorComponent* comp : editorComp) { if (ImGui::CollapsingHeader(comp->name().c_str(), ImGuiTreeNodeFlags_OpenOnArrow)) { //const I32 RV = ImGui::AppendTreeNodeHeaderButtons(comp->name().c_str(), ImGui::GetCursorPosX(), 1, &closed, "Remove", NULL, 0); ImGui::NewLine(); ImGui::SameLine(xOffset); if (ImGui::Button("INSPECT", ImVec2(smallButtonWidth, 20))) { Attorney::EditorGeneralWidget::inspectMemory(_context.editor(), std::make_pair(comp, sizeof(EditorComponent))); } ImGui::SameLine(); if (ImGui::Button("REMOVE", ImVec2(smallButtonWidth, 20))) { Attorney::EditorGeneralWidget::inspectMemory(_context.editor(), std::make_pair(nullptr, 0)); } ImGui::Separator(); vector<EditorComponentField>& fields = Attorney::EditorComponentEditor::fields(*comp); for (EditorComponentField& field : fields) { ImGui::Text(field._name.c_str()); ImGui::Spacing(); if (processField(field) && !field._readOnly) { Attorney::EditorComponentEditor::onChanged(*comp, field); } } } } } } } if (hasSelections) { const F32 buttonWidth = 80.0f; F32 xOffset = ImGui::GetWindowSize().x - buttonWidth - 20.0f; ImGui::NewLine(); ImGui::Separator(); ImGui::NewLine(); ImGui::SameLine(xOffset); if (ImGui::Button("ADD NEW", ImVec2(buttonWidth, 15))) { ImGui::OpenPopup("COMP_SELECTION_GROUP"); } static ComponentType selectedType = ComponentType::COUNT; if (ImGui::BeginPopup("COMP_SELECTION_GROUP")) { for (ComponentType type : ComponentType::_values()) { if (type._to_integral() == ComponentType::COUNT) { continue; } if (ImGui::Selectable(type._to_string())) { selectedType = type; } } ImGui::EndPopup(); } if (selectedType._to_integral() != ComponentType::COUNT) { ImGui::OpenPopup("Add new component"); } if (ImGui::BeginPopupModal("Add new component", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("Add new %s component?", selectedType._to_string()); ImGui::Separator(); if (ImGui::Button("OK", ImVec2(120, 0))) { selectedType = ComponentType::COUNT; ImGui::CloseCurrentPopup(); } ImGui::SetItemDefaultFocus(); ImGui::SameLine(); if (ImGui::Button("Cancel", ImVec2(120, 0))) { selectedType = ComponentType::COUNT; ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } } }
Renderable* renderable(const std::string& name) { SceneGraphNode* node = sceneGraphNode(name); return node->renderable(); }
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){ openspace::documentation::testSpecificationAndThrow( SceneGraphNode::Documentation(), dictionary, "SceneGraphNode" ); SceneGraphNode* result = new SceneGraphNode; if (!dictionary.hasValue<std::string>(KeyName)) { LERROR("SceneGraphNode did not contain a '" << KeyName << "' key"); delete result; return nullptr; } std::string name; dictionary.getValue(KeyName, name); result->setName(name); if (dictionary.hasValue<ghoul::Dictionary>(KeyRenderable)) { ghoul::Dictionary renderableDictionary; dictionary.getValue(KeyRenderable, renderableDictionary); renderableDictionary.setValue(KeyName, name); result->_renderable = Renderable::createFromDictionary(renderableDictionary); if (result->_renderable == nullptr) { LERROR("Failed to create renderable for SceneGraphNode '" << result->name() << "'"); delete result; return nullptr; } result->addPropertySubOwner(result->_renderable); LDEBUG("Successfully created renderable for '" << result->name() << "'"); } if (dictionary.hasKey(keyTransformTranslation)) { ghoul::Dictionary translationDictionary; dictionary.getValue(keyTransformTranslation, translationDictionary); result->_ephemeris = (Ephemeris::createFromDictionary(translationDictionary)); if (result->_ephemeris == nullptr) { LERROR("Failed to create ephemeris for SceneGraphNode '" << result->name() << "'"); delete result; return nullptr; } LDEBUG("Successfully created ephemeris for '" << result->name() << "'"); } if (dictionary.hasKey(keyTransformRotation)) { ghoul::Dictionary rotationDictionary; dictionary.getValue(keyTransformRotation, rotationDictionary); result->_rotation = (Rotation::createFromDictionary(rotationDictionary)); if (result->_rotation == nullptr) { LERROR("Failed to create rotation for SceneGraphNode '" << result->name() << "'"); delete result; return nullptr; } LDEBUG("Successfully created rotation for '" << result->name() << "'"); } if (dictionary.hasKey(keyTransformScale)) { ghoul::Dictionary scaleDictionary; dictionary.getValue(keyTransformScale, scaleDictionary); result->_scale = (Scale::createFromDictionary(scaleDictionary)); if (result->_scale == nullptr) { LERROR("Failed to create scale for SceneGraphNode '" << result->name() << "'"); delete result; return nullptr; } LDEBUG("Successfully created scale for '" << result->name() << "'"); } //std::string parentName; //if (!dictionary.getValue(KeyParentName, parentName)) { // LWARNING("Could not find '" << KeyParentName << "' key, using 'Root'."); // parentName = "Root"; //} //SceneGraphNode* parentNode = sceneGraphNode(parentName); //if (parentNode == nullptr) { // LFATAL("Could not find parent named '" // << parentName << "' for '" << result->name() << "'." // << " Check module definition order. Skipping module."); //} //parentNode->addNode(result); LDEBUG("Successfully created SceneGraphNode '" << result->name() << "'"); return result; }