writeDAE.cpp 4.0 KB

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