writeDAE.cpp 3.8 KB

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