Skip to content

Commit

Permalink
Merge branch '4.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
rburema committed Aug 4, 2020
2 parents 17f41fc + 92f2b98 commit 623435c
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ set(savitar_HDRS
${CMAKE_CURRENT_BINARY_DIR}/src/SavitarExport.h
)

set(SAVITAR_VERSION 0.1.1)
set(SAVITAR_VERSION 0.1.2)
set(SAVITAR_SOVERSION 0)

set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR})
Expand Down
5 changes: 4 additions & 1 deletion python/SceneNode.sip
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public:
std::map<std::string, std::string> getSettings();
void setSetting(std::string key, std::string value);

void addChild(SceneNode* child /Transfer/);
bool addChild(SceneNode* child /Transfer/);

std::string getType();
void setType(std::string type);
};

37 changes: 34 additions & 3 deletions src/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,38 +83,69 @@ SceneNode* Scene::createSceneNodeFromObject(pugi::xml_node root_node, pugi::xml_
pugi::xml_node components = object_node.child("components");
SceneNode* scene_node = new SceneNode();
scene_node->fillByXMLNode(object_node);

std::map<std::string, std::string>::iterator it;
const bool has_mesh_node = scene_node->getSettings().find("mesh_node_objectid") != scene_node->getSettings().end();

std::string mesh_node_object_id = "";

if(has_mesh_node)
{
mesh_node_object_id = scene_node->getSettings()["mesh_node_objectid"];
}

// We have to do the checking for children outside of the SceneNode creation itself, because it only has references.
if(components)
{

SceneNode* mesh_node = nullptr;
for(pugi::xml_node component = components.child("component"); component; component = component.next_sibling("component"))
{
// This node has children. Add them one by one.
pugi::xml_node child_object_node = root_node.child("resources").find_child_by_attribute("object", "id", component.attribute("objectid").value());
if(child_object_node)
{
SceneNode* child_node = createSceneNodeFromObject(root_node, child_object_node);
child_node->setTransformation(component.attribute("transform").as_string());
scene_node->addChild(child_node);
if(has_mesh_node && mesh_node_object_id == component.attribute("objectid").as_string())
{
// Don't add a node with the mesh_node_objectid metadata. Store it until last so we can copy it's mesh to the parent node
mesh_node = child_node;
} else
{
child_node->setTransformation(component.attribute("transform").as_string());
scene_node->addChild(child_node);
}
} else
{
// TODO: ADD proper error handling here.
std::cout << "Child_object_node not found :( " << std::endl;
}
}

if(mesh_node != nullptr)
{
scene_node->setMeshData(mesh_node->getMeshData());
scene_node->removeSetting("mesh_node_objectid"); // No need to keep it. It's job is done!
delete mesh_node;
mesh_node = nullptr;
}
}
return scene_node;
}

std::vector<SceneNode*> Scene::getAllSceneNodes()
{
std::vector<SceneNode*> all_nodes;
all_nodes.insert(all_nodes.end(), scene_nodes.begin(), scene_nodes.end());

for(SceneNode* scene_node: scene_nodes)
{
std::vector<SceneNode*> temp_children = scene_node->getAllChildren();
all_nodes.insert(all_nodes.end(), temp_children.begin(), temp_children.end());
}

// We put them at the end so that the "simplicity" rule of 3MF is kept:
// "In keeping with the use of a simple parser, producers MUST define objects prior to referencing them as components."
all_nodes.insert(all_nodes.end(), scene_nodes.begin(), scene_nodes.end());
return all_nodes;
}

Expand Down
50 changes: 44 additions & 6 deletions src/SceneNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ using namespace Savitar;

SceneNode::SceneNode()
{

transformation = "1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0";
type = "model";
mesh_node = nullptr;
}

SceneNode::~SceneNode()
Expand All @@ -42,19 +44,33 @@ void SceneNode::setTransformation(std::string transformation)
this->transformation = transformation;
}

SceneNode* SceneNode::getMeshNode()
{
return mesh_node;
}

std::vector<SceneNode*> SceneNode::getChildren()
{
return this->children;
}

void SceneNode::addChild(SceneNode* node)
bool SceneNode::addChild(SceneNode* node)
{
if(node == nullptr)
if(node == nullptr) // No node given
{
return false;
}

if(this->mesh_data.getVertices().size() != 0) // This node already has mesh data, so we need to move that data to a child node
{
return;
mesh_node = new SceneNode();
mesh_node->setMeshData(this->mesh_data); // Copy the data to the new child.
mesh_data.clear(); // Clear our own data
this->children.push_back(mesh_node);
}

this->children.push_back(node);
return true;
}

MeshData& SceneNode::getMeshData()
Expand All @@ -67,6 +83,19 @@ void SceneNode::setMeshData(MeshData mesh_data)
this->mesh_data = mesh_data;
}

std::string SceneNode::getType()
{
return this->type;
}

void SceneNode::setType(std::string type)
{
if(type == "model" || type == "solidsupport" || type == "support" || type == "surface" || type == "other")
{
this->type = type;
}
}

void SceneNode::fillByXMLNode(pugi::xml_node xml_node)
{
settings.clear();
Expand Down Expand Up @@ -149,17 +178,26 @@ void SceneNode::setSetting(std::string key, std::string value)
settings[key] = value;
}

void SceneNode::removeSetting(std::string key)
{
settings.erase(key);
}


std::vector< SceneNode*> SceneNode::getAllChildren()
{
std::vector<SceneNode*> all_children;
// Add all direct children to the result to return
all_children.insert(all_children.end(), children.begin(), children.end());

for(SceneNode* scene_node: children)
{
std::vector<SceneNode*> temp_children = scene_node->getAllChildren();
all_children.insert(all_children.end(), temp_children.begin(), temp_children.end());
}

// Add all direct children to the result to return.
// We put them at the end so that the "simplicity" rule of 3MF is kept:
// "In keeping with the use of a simple parser, producers MUST define objects prior to referencing them as components."
all_children.insert(all_children.end(), children.begin(), children.end());
return all_children;
}

18 changes: 17 additions & 1 deletion src/SceneNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace Savitar

std::vector<SceneNode*> getChildren();
std::vector<SceneNode*> getAllChildren();
void addChild(SceneNode* node);
bool addChild(SceneNode* node);

MeshData& getMeshData();
void setMeshData(MeshData mesh_data);
Expand Down Expand Up @@ -75,6 +75,16 @@ namespace Savitar
std::map<std::string, std::string> getSettings();

void setSetting(std::string key, std::string value);
void removeSetting(std::string key);

/**
* Type of the scene node. Can be "model", "solidsupport", "support", "surface", or "other".
* This defaults to "model"
*/
std::string getType();
void setType(std::string type);

SceneNode* getMeshNode();

protected:
std::string transformation;
Expand All @@ -83,6 +93,12 @@ namespace Savitar
std::map<std::string, std::string> settings;
std::string id;
std::string name;
std::string type;

// 3MF does not support having an Object that has a mesh and components.
// This is solved by the concept of the "mesh" node, which is added as a child.
// This then gets a bit of metadata set so we can restore the graph in the way that we expect it.
SceneNode* mesh_node;
};
}

Expand Down
26 changes: 19 additions & 7 deletions src/ThreeMFParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,7 @@ std::string ThreeMFParser::sceneToString(Scene scene)
{
object.append_attribute("name") = scene_node->getName().c_str();
}
object.append_attribute("type") = "model";

if(scene_node->getMeshData().getVertices().size() != 0)
{
pugi::xml_node mesh = object.append_child("mesh");
scene_node->getMeshData().toXmlNode(mesh);
}
object.append_attribute("type") = scene_node->getType().c_str();

std::map<std::string, std::string> per_object_settings = scene_node->getSettings();
if(!per_object_settings.empty())
Expand All @@ -96,6 +90,12 @@ std::string ThreeMFParser::sceneToString(Scene scene)
setting.append_attribute("type") = "xs:string";
}
}

if(scene_node->getMeshData().getVertices().size() != 0)
{
pugi::xml_node mesh = object.append_child("mesh");
scene_node->getMeshData().toXmlNode(mesh);
}

if(scene_node->getChildren().size() != 0)
{
Expand All @@ -107,6 +107,18 @@ std::string ThreeMFParser::sceneToString(Scene scene)
component.append_attribute("transform") = child_scene_node->getTransformation().c_str();
}
}
if(scene_node->getMeshNode() != nullptr)
{
if(object.child("metadatagroup"))
{
object.append_child("metadatagroup");
}
pugi::xml_node mesh_node_setting = object.child("metadatagroup").append_child("metadata");
mesh_node_setting.append_attribute("name") = "mesh_node_objectid";
mesh_node_setting.text().set(scene_node->getMeshNode()->getId().c_str());
mesh_node_setting.append_attribute("preserve") = "true";
mesh_node_setting.append_attribute("type") = "xs:string";
}
}

for(SceneNode* scene_node: scene.getSceneNodes())
Expand Down

0 comments on commit 623435c

Please sign in to comment.