PeriDyno 1.0.0
Loading...
Searching...
No Matches
SceneLoaderXML.cpp
Go to the documentation of this file.
1#include "SceneLoaderXML.h"
2#include <algorithm>
3
4#include <stdlib.h>
5#include <sstream>
6
7namespace dyno
8{
9 std::shared_ptr<SceneGraph> SceneLoaderXML::load(const std::string filename)
10 {
11 tinyxml2::XMLDocument doc;
12 if (doc.LoadFile(filename.c_str()))
13 {
14 doc.PrintError();
15 return nullptr;
16 }
17
18 for (size_t i = 0; i < mConnectionInfo.size(); i++){
19 mConnectionInfo[i].clear();
20 }
21 mConnectionInfo.clear();
22
23 std::shared_ptr<SceneGraph> scn = std::make_shared<SceneGraph>();
24
25 tinyxml2::XMLElement* root = doc.RootElement();
26
27 std::vector<std::shared_ptr<Node>> nodes;
28 tinyxml2::XMLElement* nodeXML = root->FirstChildElement("Node");
29 while (nodeXML)
30 {
31 auto node = processNode(nodeXML);
32 if (node) {
33 scn->addNode(node);
34 nodes.push_back(node);
35 }
36
37 nodeXML = nodeXML->NextSiblingElement("Node");
38 }
39
40 for (size_t i = 0; i < mConnectionInfo.size(); i++)
41 {
42 auto& connections = mConnectionInfo[i];
43 for (size_t j = 0; j < connections.size(); j++)
44 {
45 auto info = connections[j];
46
47 auto expNode = nodes[info.src];
48 auto inpNode = nodes[info.dst];
49
50 auto& outFields = expNode->getOutputFields();
51
52 auto& inPorts = inpNode->getImportNodes();
53 auto& inFields = inpNode->getInputFields();
54
55 if (info.id0 <= 0)
56 {
57 expNode->connect(inPorts[info.id1]);
58 }
59 else {
60 outFields[info.id0 - 1]->connect(inFields[info.id1 - inPorts.size()]);
61 }
62 }
63 }
64
65 return scn;
66 }
67
68 bool SceneLoaderXML::save(std::shared_ptr<SceneGraph> scn, const std::string filename)
69 {
70 tinyxml2::XMLDocument doc;
71
72// const char* declaration = "<?xml version=\"0.6.0\" encoding=\"UTF-8\">";
73// doc.Parse(declaration);
74
75 tinyxml2::XMLElement* root = doc.NewElement("SceneGraph");
76
77 root->SetAttribute("LowerBound", encodeVec3f(scn->getLowerBound()).c_str());
78 root->SetAttribute("UpperBound", encodeVec3f(scn->getUpperBound()).c_str());
79
80 doc.InsertEndChild(root);
81
82 SceneGraph::Iterator itor = scn->begin();
83
84 std::map<ObjectId, uint> indices;
85 int radix = 0;
86 for (; itor != scn->end(); itor++) {
87 auto node = itor.get();
88 indices[node->objectId()] = radix;
89
90 radix++;
91 }
92 for (itor = scn->begin(); itor != scn->end(); itor++)
93 {
94 auto node = itor.get();
95
96 tinyxml2::XMLElement* nodeXml = doc.NewElement("Node");
97 nodeXml->SetAttribute("Class", node->getClassInfo()->getClassName().c_str());
98 nodeXml->SetAttribute("Coordinate", encodeVec2f(Vec2f(node->bx(), node->by())).c_str());
99 root->InsertEndChild(nodeXml);
100
101 tinyxml2::XMLElement* varsXml = doc.NewElement("Variables");
102 nodeXml->InsertEndChild(varsXml);
103
104 //write control variables
105 auto& params = node->getParameters();
106 for (auto var : params)
107 {
108 tinyxml2::XMLElement* field = doc.NewElement("Field");
109 field->SetAttribute("Name", var->getObjectName().c_str());
110
111 tinyxml2::XMLText* val = doc.NewText(var->serialize().c_str());
112 field->InsertEndChild(val);
113
114 varsXml->InsertEndChild(field);
115 }
116
117 //write connections
118 tinyxml2::XMLElement* nodeConnectionsXml = doc.NewElement("Connections");
119 nodeXml->InsertEndChild(nodeConnectionsXml);
120
121 auto ports = node->getImportNodes();
122
123 for (int i = 0; i < ports.size(); i++)
124 {
125 auto NodesSrc = ports[i]->getNodes();
126 bool fieldFound = false;
127 Node* nSrcPar = nullptr;
128 for (auto nSrc : NodesSrc)
129 {
130 auto nSrcExports = nSrc->getExportNodes();
131 for (auto x : nSrcExports)
132 {
133 if (x == ports[i])
134 {
135 fieldFound = true;
136 nSrcPar = nSrc;
137 }
138 }
139 }
140 if (fieldFound&&nSrcPar!=nullptr) {
141
142 tinyxml2::XMLElement* connection = doc.NewElement("Connection");
143 connection->SetAttribute("SourceId", indices[nSrcPar->objectId()]);
144 connection->SetAttribute("From", 0);
145 connection->SetAttribute("TargetId", indices[node->objectId()]);
146 connection->SetAttribute("To", uint(i));
147 nodeConnectionsXml->InsertEndChild(connection);
148 }
149
150 }
151
152 auto fieldInp = node->getInputFields();
153
154 for (int i = 0; i < fieldInp.size(); i++)
155 {
156 auto fieldSrc = fieldInp[i]->getSource();
157 if (fieldSrc != nullptr) {
158 auto parSrc = fieldSrc->parent();
159 if (parSrc != nullptr)
160 {
161 Node* nodeSrc = dynamic_cast<Node*>(parSrc);
162 auto outId = nodeSrc->objectId();
163 auto fieldsOut = nodeSrc->getOutputFields();
164 uint outFieldIndex = 0;
165 bool fieldFound = false;
166
167 for(outFieldIndex=0; outFieldIndex< fieldsOut.size(); outFieldIndex++)
168 {
169 if (fieldsOut[outFieldIndex] == fieldSrc)
170 {
171 fieldFound = true;
172 break;
173 }
174
175 }
176 if (fieldFound) {
177 tinyxml2::XMLElement* connection = doc.NewElement("Connection");
178 connection->SetAttribute("SourceId", indices[parSrc->objectId()]);
179 connection->SetAttribute("From", 1 +outFieldIndex);
180 connection->SetAttribute("TargetId", indices[node->objectId()]);
181 connection->SetAttribute("To", uint(i + ports.size()));
182 nodeConnectionsXml->InsertEndChild(connection);
183 }
184 }
185 }
186 }
187
188
189 auto& fields = node->getAllFields();
190 std::vector<FBase*> fieldsOut;
191 for (auto field : fields)
192 {
193 if (field->getFieldType() == dyno::FieldTypeEnum::State)
194 {
195 fieldsOut.push_back(field);
196 }
197 else if (field->getFieldType() == dyno::FieldTypeEnum::In)
198 {
199 auto fieldSrc = field->getSource();
200 if (fieldSrc != nullptr) {
201
202 auto parSrc = fieldSrc->parent();
203 if (parSrc != nullptr)
204 {
205 Module* src = dynamic_cast<Module*>(parSrc);
206 if (src == nullptr)
207 {
208 Node* srcNode = dynamic_cast<Node*>(parSrc);
209 if (srcNode != nullptr)
210 {
211 fieldsOut.push_back(field);
212 }
213 }
214 }
215 }
216 }
217 }
218 /**/
219 //Insert animation pipeline
220 auto savePipeline = [&](std::shared_ptr<Pipeline> pipeline, const char* tag) {
221 tinyxml2::XMLElement* pipelineXml = doc.NewElement(tag);
222 nodeXml->InsertEndChild(pipelineXml);
223
224 std::map<ObjectId, uint> indices;
225 std::map<ObjectId, std::shared_ptr<Module>> moduleMap;
226 uint radix = 0;
227
228 auto& activeModules = pipeline->activeModules();
229 for (auto m : activeModules){
230 tinyxml2::XMLElement* moduleXml = doc.NewElement("Module");
231 moduleXml->SetAttribute("Class", m->getClassInfo()->getClassName().c_str());
232 moduleXml->SetAttribute("Coordinate", encodeVec2f(Vec2f(m->bx(), m->by())).c_str());
233 pipelineXml->InsertEndChild(moduleXml);
234
235 tinyxml2::XMLElement* varsModuleXml = doc.NewElement("Variables");
236 moduleXml->InsertEndChild(varsModuleXml);
237
238 //write control variables
239 auto& params = m->getParameters();
240 for (auto var : params)
241 {
242 tinyxml2::XMLElement* field = doc.NewElement("Field");
243 field->SetAttribute("Name", var->getObjectName().c_str());
244
245 tinyxml2::XMLText* val = doc.NewText(var->serialize().c_str());
246 field->InsertEndChild(val);
247
248 varsModuleXml->InsertEndChild(field);
249 }
250
251 indices[m->objectId()] = radix;
252 moduleMap[m->objectId()] = m;
253 radix++;
254 }
255 //write connections
256 tinyxml2::XMLElement* moduleConnectionsXml = doc.NewElement("Connections");
257 pipelineXml->InsertEndChild(moduleConnectionsXml);
258
259 for (auto m : activeModules)
260 {
261 auto& fieldIn = m->getInputFields();
262 for (int i = 0; i < fieldIn.size(); i++)
263 {
264 auto fieldSrc = fieldIn[i]->getSource();
265 if (fieldSrc != nullptr) {
266 auto parSrc = fieldSrc->parent();
267 if (parSrc != nullptr)
268 {
269 Module* src = dynamic_cast<Module*>(parSrc);
270 if (src != nullptr)
271 {
272 auto outId = src->objectId();
273 auto srcfieldsOut = src->getOutputFields();
274
275 uint outFieldIndex = 0;
276 bool fieldFound = false;
277 for (auto f : srcfieldsOut)
278 {
279 if (f == fieldSrc)
280 {
281 fieldFound = true;
282 break;
283 }
284 outFieldIndex++;
285 }
286
287 if (fieldFound && moduleMap.find(outId) != moduleMap.end())
288 {
289 auto outBlock = moduleMap[outId];
290
291 tinyxml2::XMLElement* moduleConnectionXml = doc.NewElement("Connection");
292 moduleConnectionXml->SetAttribute("SourceId", indices[outBlock->objectId()]);
293 moduleConnectionXml->SetAttribute("From", outFieldIndex);
294 moduleConnectionXml->SetAttribute("TargetId", indices[m->objectId()]);
295 moduleConnectionXml->SetAttribute("To", uint(i));
296 moduleConnectionsXml->InsertEndChild(moduleConnectionXml);
297 }
298 }
299 else {//每个模块里面第一个
300 Node* src = dynamic_cast<Node*>(parSrc);
301
302 if (src != nullptr)
303 {
304 uint outFieldIndex = 0;
305 bool fieldFound = false;
306 auto n=src->getModuleList().size();
307 for (auto f : fieldsOut)
308 {
309 if (f == fieldSrc)
310 {
311 fieldFound = true;
312 break;
313 }
314 outFieldIndex++;
315 }
316
317 if (fieldFound)
318 {
319 tinyxml2::XMLElement* moduleConnectionXml = doc.NewElement("Connection");
320 moduleConnectionXml->SetAttribute("SourceId", -1);
321 moduleConnectionXml->SetAttribute("From", outFieldIndex);
322 moduleConnectionXml->SetAttribute("TargetId", indices[m->objectId()]);
323 moduleConnectionXml->SetAttribute("To", uint(i));
324 moduleConnectionsXml->InsertEndChild(moduleConnectionXml);
325 }
326 }
327 }
328 }
329 }
330 }
331 }
332
333 indices.clear();
334 };
335
336 savePipeline(node->animationPipeline(), "Simulation");
337
338// //Insert graphics pipeline
339// tinyxml2::XMLElement* graphicsPipelineXml = doc.NewElement("Rendering");
340// nodeXml->InsertEndChild(graphicsPipelineXml);
341//
342// auto graphicsPipeline = node->graphicsPipeline();
343// for each (auto m in graphicsPipeline->activeModules())
344// {
345// tinyxml2::XMLElement* moduleXml = doc.NewElement("Module");
346// moduleXml->SetAttribute("Class", m->getClassInfo()->getClassName().c_str());
347// moduleXml->SetAttribute("Coordinate", encodeVec2f(Vec2f(m->bx(), m->by())).c_str());
348// graphicsPipelineXml->InsertEndChild(moduleXml);
349// }
350
351 savePipeline(node->graphicsPipeline(), "Rendering");
352
353 fieldsOut.clear();
354 }
355
356 doc.SaveFile(filename.c_str());
357
358 indices.clear();
359
360 return true;
361 }
362
363 std::shared_ptr<Node> SceneLoaderXML::processNode(tinyxml2::XMLElement* nodeXML)
364 {
365 const char* name = nodeXML->Attribute("Class");
366 if (!name)
367 return nullptr;
368
369 std::shared_ptr<Node> node(dynamic_cast<Node*>(Object::createObject(name)));
370 if (node == nullptr)
371 {
372 std::cout << name << " does not exist! " << std::endl;
373 return nullptr;
374 }
375
376 const char* coordStr = nodeXML->Attribute("Coordinate");
377
378 Vec2f coord = decodeVec2f(std::string(coordStr));
379
380 node->setBlockCoord(coord.x, coord.y);
381
382 const char* nodeName = nodeXML->Attribute("Name");
383 if (nodeName)
384 node->setName(nodeName);
385
386 std::map<std::string, FBase*> str2Field;
387 auto& params = node->getParameters();
388 for (auto var : params) {
389 str2Field[var->getObjectName()] = var;
390 }
391 tinyxml2::XMLElement* varsXmls = nodeXML->FirstChildElement("Variables");
392 tinyxml2::XMLElement* fieldXml = varsXmls->FirstChildElement("Field");
393 while (fieldXml)
394 {
395 std::string name = fieldXml->Attribute("Name");
396 std::string str = fieldXml->GetText();
397 str2Field[name]->deserialize(str);
398
399 fieldXml = fieldXml->NextSiblingElement("Field");
400 }
401 str2Field.clear();
402
403 std::vector<ConnectionInfo> infoVec;
404
408 tinyxml2::XMLElement* cnnXmls = nodeXML->FirstChildElement("Connections");
409 tinyxml2::XMLElement* connectionXml = cnnXmls->FirstChildElement("Connection");
410
411 while (connectionXml)
412 {
413 ConnectionInfo info;
414
415 info.src = atoi(connectionXml->Attribute("SourceId"));
416 info.dst = atoi(connectionXml->Attribute("TargetId"));
417
418 info.id0 = atoi(connectionXml->Attribute("From"));
419 info.id1 = atoi(connectionXml->Attribute("To"));
420
421 infoVec.push_back(info);
422
423
424 connectionXml = connectionXml->NextSiblingElement("Connection");
425 }
426
427 mConnectionInfo.push_back(infoVec);
428
429 infoVec.clear();
430
431 auto& fields = node->getAllFields();
432 std::vector<FBase*> states;
433 for (auto field : fields)
434 {
435 if (field->getFieldType() == dyno::FieldTypeEnum::State)
436 {
437 states.push_back(field);
438 }
439 else if (field->getFieldType() == dyno::FieldTypeEnum::In )
440 {
441
442 states.push_back(field);
443
444 }
445 }
449 std::vector<Module*> animationModules;
450 node->animationPipeline()->clear();
451 tinyxml2::XMLElement* animationPipelineXml = nodeXML->FirstChildElement("Simulation");
452 tinyxml2::XMLElement* animationModuleXml = animationPipelineXml->FirstChildElement("Module");
453
454 auto processModule = [&](tinyxml2::XMLElement* moduleXml, std::shared_ptr<Pipeline> pipeline, std::vector<Module*>& modules) {
455 const char* name = moduleXml->Attribute("Class");
456 if (name) {
457 std::shared_ptr<Module> module(dynamic_cast<Module*>(Object::createObject(name)));
458 if (module != nullptr) {
459 pipeline->pushModule(module);
460 modules.push_back(module.get());
461
462 std::map<std::string, FBase*> str2Field;
463 auto& params = module->getParameters();
464 for (auto var : params) {
465 str2Field[var->getObjectName()] = var;
466 }
467
468 tinyxml2::XMLElement* varsXml = moduleXml->FirstChildElement("Variables");
469 tinyxml2::XMLElement* varXml = varsXml->FirstChildElement("Field");
470
471 while (varXml)
472 {
473 std::string name = varXml->Attribute("Name");
474 std::string str = varXml->GetText();
475 str2Field[name]->deserialize(str);
476
477 varXml = varXml->NextSiblingElement("Field");
478 }
479
480 str2Field.clear();
481 }
482 }
483 };
484
485 while (animationModuleXml)
486 {
487 processModule(animationModuleXml, node->animationPipeline(), animationModules);
488// const char* name = animationModuleXml->Attribute("Class");
489// if (name) {
490// std::shared_ptr<Module> module(dynamic_cast<Module*>(Object::createObject(name)));
491// if (module != nullptr) {
492// node->animationPipeline()->pushModule(module);
493// animationModules.push_back(module.get());
494// }
495// }
496
497 animationModuleXml = animationModuleXml->NextSiblingElement("Module");
498 }
499 tinyxml2::XMLElement* animationConnectionsXml = animationPipelineXml->FirstChildElement("Connections");
500 tinyxml2::XMLElement* animationConnectionXml = animationConnectionsXml->FirstChildElement("Connection");
501 while (animationConnectionXml)
502 {
503 int src = atoi(animationConnectionXml->Attribute("SourceId"));
504 int dst = atoi(animationConnectionXml->Attribute("TargetId"));
505
506 int id0 = atoi(animationConnectionXml->Attribute("From"));
507 int id1 = atoi(animationConnectionXml->Attribute("To"));
508
509 FBase* fout = src == -1 ? states[id0] : animationModules[src]->getOutputFields()[id0];
510 FBase* fin = animationModules[dst]->getInputFields()[id1];
511
512 fout->connect(fin);
513
514 animationConnectionXml = animationConnectionXml->NextSiblingElement("Connection");
515 }
516 animationModules.clear();
517
521 std::vector<Module*> renderingModules;
522 node->graphicsPipeline()->clear();
523 tinyxml2::XMLElement* renderingPipelineXml = nodeXML->FirstChildElement("Rendering");
524 tinyxml2::XMLElement* renderingModuleXml = renderingPipelineXml->FirstChildElement("Module");
525 while (renderingModuleXml)
526 {
527 processModule(renderingModuleXml, node->graphicsPipeline(), renderingModules);
528// const char* name = renderingModuleXml->Attribute("Class");
529// if (name) {
530// std::shared_ptr<Module> module(dynamic_cast<Module*>(Object::createObject(name)));
531// if (module != nullptr) {
532// node->graphicsPipeline()->pushModule(module);
533// renderingModules.push_back(module.get());
534// }
535// }
536
537 renderingModuleXml = renderingModuleXml->NextSiblingElement("Module");
538 }
539
540 tinyxml2::XMLElement* renderingConnectionsXml = renderingPipelineXml->FirstChildElement("Connections");
541 tinyxml2::XMLElement* renderingConnectionXml = renderingConnectionsXml->FirstChildElement("Connection");
542 while (renderingConnectionXml)
543 {
544 int src = atoi(renderingConnectionXml->Attribute("SourceId"));
545 int dst = atoi(renderingConnectionXml->Attribute("TargetId"));
546
547 int id0 = atoi(renderingConnectionXml->Attribute("From"));
548 int id1 = atoi(renderingConnectionXml->Attribute("To"));
549
550 if (id0 < states.size())
551 {
552 FBase* fout = src == -1 ? states[id0] : renderingModules[src]->getOutputFields()[id0];
553 FBase* fin = renderingModules[dst]->getInputFields()[id1];
554
555 fout->connect(fin);
556 }
557
558
559 renderingConnectionXml = renderingConnectionXml->NextSiblingElement("Connection");
560 }
561 renderingModules.clear();
562
563 return node;
564 }
565
566 std::shared_ptr<Module> SceneLoaderXML::processModule(tinyxml2::XMLElement* moduleXML)
567 {
568 const char* className = moduleXML->Attribute("class");
569 if (!className)
570 return nullptr;
571
572 const char* dataType = moduleXML->Attribute("datatype");
573 std::string templateClass = std::string(className);
574 if (dataType)
575 {
576 templateClass += std::string("<")+std::string(dataType)+ std::string(">");
577 }
578 std::shared_ptr<Module> module(dynamic_cast<Module*>(Object::createObject(templateClass)));
579
580 return module;
581 }
582
583 bool SceneLoaderXML::addModule(std::shared_ptr<Node> node, std::shared_ptr<Module> module)
584 {
585 if (module->getModuleType() == "MechanicalState")
586 {
587 return true;
588 }
589
590 return false;
591 }
592
593 std::vector<std::string> SceneLoaderXML::split(std::string str, std::string pattern)
594 {
595 std::string::size_type pos;
596 std::vector<std::string> result;
597 str += pattern;
598 size_t size = (uint)str.size();
599
600 for (size_t i = 0; i < size; i++)
601 {
602 pos = str.find(pattern, i);
603 if (pos < size)
604 {
605 std::string s = str.substr(i, pos - i);
606 result.push_back(s);
607 i = pos + pattern.size() - 1;
608 }
609 }
610 return result;
611 }
612
614 {
615 std::stringstream ss;
616
617 ss << v.x << " " << v.y << " " << v.z;
618
619 return ss.str();
620 }
621
623 {
624 std::stringstream ss;
625
626 ss << v.x << " " << v.y;
627
628 return ss.str();
629 }
630
631 Vec3f SceneLoaderXML::decodeVec3f(const std::string str)
632 {
633 std::stringstream ss(str);
634 std::string substr;
635
636 ss >> substr;
637 float x = std::stof(substr.c_str());
638
639 ss >> substr;
640 float y = std::stof(substr.c_str());
641
642 ss >> substr;
643 float z = std::stof(substr.c_str());
644
645 return Vec3f(x, y, z);
646 }
647
648 Vec2f SceneLoaderXML::decodeVec2f(const std::string str)
649 {
650 std::stringstream ss(str);
651 std::string substr;
652
653 ss >> substr;
654 float x = std::stof(substr.c_str());
655
656 ss >> substr;
657 float y = std::stof(substr.c_str());
658
659 return Vec2f(x, y);
660 }
661
662 bool SceneLoaderXML::canLoadFileByExtension(const std::string extension)
663 {
664 std::string str = extension;
665 std::transform(str.begin(), str.end(), str.begin(), ::tolower);
666 return (extension == "xml");
667 }
668
669}
virtual bool connect(FBase *dst)=0
std::list< std::shared_ptr< Module > > & getModuleList()
Definition Node.h:149
std::shared_ptr< Node > get() const
std::vector< FBase * > & getOutputFields()
Definition OBase.h:179
static Object * createObject(std::string name)
Definition Object.cpp:32
ObjectId objectId()
Definition Object.h:129
NodeIterator Iterator
Definition SceneGraph.h:34
Vec3f decodeVec3f(const std::string str)
std::string encodeVec2f(const Vec2f v)
virtual bool canLoadFileByExtension(const std::string extension)
bool addModule(std::shared_ptr< Node > node, std::shared_ptr< Module > module)
std::vector< std::string > split(std::string str, std::string pattern)
std::shared_ptr< Node > processNode(tinyxml2::XMLElement *nodeXML)
std::shared_ptr< SceneGraph > load(const std::string filename) override
std::shared_ptr< Module > processModule(tinyxml2::XMLElement *moduleXML)
Vec2f decodeVec2f(const std::string str)
std::string encodeVec3f(const Vec3f v)
bool save(std::shared_ptr< SceneGraph > scn, const std::string filename) override
std::vector< std::vector< ConnectionInfo > > mConnectionInfo
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
Vector< float, 2 > Vec2f
Definition Vector2D.h:81
Vector< float, 3 > Vec3f
Definition Vector3D.h:93
@ In
Definition FBase.h:31
@ State
Definition FBase.h:35
unsigned int uint
Definition VkProgram.h:14