writeDAE.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "writeDAE.h"
  9. #include "../STR.h"
  10. #include <tinyxml2.h>
  11. #include <map>
  12. #include <list>
  13. template <typename DerivedV, typename DerivedF>
  14. IGL_INLINE bool igl::xml::writeDAE(
  15. const std::string & filename,
  16. const Eigen::PlainObjectBase<DerivedV> & V,
  17. const Eigen::PlainObjectBase<DerivedF> & F)
  18. {
  19. using namespace std;
  20. using namespace Eigen;
  21. tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
  22. const auto & ele = [&doc](
  23. const std::string tag,
  24. // Can't just use `{}` as the default argument because of a clang-bug
  25. // http://stackoverflow.com/questions/17264067/
  26. const std::map<std::string,std::string> attribs =
  27. std::map<std::string,std::string>(),
  28. const std::string text="",
  29. const std::list<tinyxml2::XMLElement *> children =
  30. std::list<tinyxml2::XMLElement *>()
  31. )->tinyxml2::XMLElement *
  32. {
  33. tinyxml2::XMLElement * element = doc->NewElement(tag.c_str());
  34. for(const auto & key_value : attribs)
  35. {
  36. element->SetAttribute(key_value.first.c_str(),key_value.second.c_str());
  37. }
  38. if(!text.empty())
  39. {
  40. element->InsertEndChild(doc->NewText(text.c_str()));
  41. }
  42. for(auto & child : children)
  43. {
  44. element->InsertEndChild(child);
  45. }
  46. return element;
  47. };
  48. Eigen::IOFormat row_format(Eigen::FullPrecision,0," "," ","","","");
  49. doc->InsertEndChild(
  50. ele("COLLADA",
  51. {
  52. {"xmlns","http://www.collada.org/2005/11/COLLADASchema"},
  53. {"version","1.4.1"}
  54. },
  55. "",
  56. {
  57. ele("asset",{},"",
  58. {
  59. ele("unit",{{"meter","0.0254000"},{"name","inch"}}),
  60. ele("up_axis",{},"Y_UP")
  61. }),
  62. ele("library_visual_scenes",{},"",
  63. {
  64. ele("visual_scene",{{"id","ID2"}},"",
  65. {
  66. ele("node",{{"name","SketchUp"}},"",
  67. {
  68. ele("node",{{"id","ID3"},{"name","group_0"}},"",
  69. {
  70. ele("matrix",{},"1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"),
  71. ele("instance_geometry",{{"url","#ID4"}},"",
  72. {
  73. ele("bind_material",{},"",{ele("technique_common")}),
  74. }),
  75. }),
  76. }),
  77. }),
  78. }),
  79. ele("library_geometries",{},"",
  80. {
  81. ele("geometry",{{"id","ID4"}},"",
  82. {
  83. ele("mesh",{},"",
  84. {
  85. ele("source",{{"id","ID7"}},"",
  86. {
  87. ele(
  88. "float_array",
  89. {{"count",STR(V.size())},{"id","ID10"}},
  90. STR(V.format(row_format))),
  91. ele("technique_common",{},"",
  92. {
  93. ele(
  94. "accessor",
  95. {{"count",STR(V.rows())},{"source","#ID8"},{"stride","3"}},
  96. "",
  97. {
  98. ele("param",{{"name","X"},{"type","float"}}),
  99. ele("param",{{"name","Y"},{"type","float"}}),
  100. ele("param",{{"name","Z"},{"type","float"}}),
  101. })
  102. })
  103. }),
  104. ele(
  105. "vertices",
  106. {{"id","ID9"}},
  107. "",
  108. {ele("input",{{"semantic","POSITION"},{"source","#ID7"}})}),
  109. ele(
  110. "triangles",
  111. {{"count",STR(F.rows())}},
  112. "",
  113. {
  114. ele("input",{{"semantic","VERTEX"},{"source","#ID9"}}),
  115. ele("p",{},STR(F.format(row_format))),
  116. })
  117. })
  118. })
  119. }),
  120. ele("scene",{},"",{ele("instance_visual_scene",{{"url","#ID2"}})}),
  121. }));
  122. // tinyxml2 seems **not** to print the <?xml ...?> header by default, but it
  123. // also seems that that's OK
  124. tinyxml2::XMLError error = doc->SaveFile(filename.c_str());
  125. bool ret = true;
  126. if(error != tinyxml2::XML_SUCCESS)
  127. {
  128. doc->PrintError();
  129. ret = false;
  130. }
  131. delete doc;
  132. return ret;
  133. }