MeshCompiler.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <iostream>
  24. #include <sstream>
  25. #include "DAECompiler.h"
  26. using tinyxml2::XMLDocument;
  27. using tinyxml2::XMLElement;
  28. using tinyxml2::XML_NO_ERROR;
  29. using tinyxml2::XML_NO_ATTRIBUTE;
  30. using std::vector;
  31. using std::cout;
  32. using std::endl;
  33. namespace crown
  34. {
  35. //-----------------------------------------------------------------------------
  36. DAECompiler::DAECompiler()
  37. {
  38. }
  39. //-----------------------------------------------------------------------------
  40. DAECompiler::~DAECompiler()
  41. {
  42. }
  43. //-----------------------------------------------------------------------------
  44. size_t DAECompiler::compile_impl(const char* resource_path)
  45. {
  46. DAEModel model;
  47. if (!parse_collada(resource_path, model))
  48. {
  49. return 0;
  50. }
  51. // Check that polylist is composed of triangles
  52. const vector<uint32_t>& vcount = model.geometries[0].mesh.polylist.vcount;
  53. for (uint32_t i = 0; i < vcount.size(); i++)
  54. {
  55. if (vcount[i] != 3)
  56. {
  57. cout << "Bad polylist: only triangle primitives allowed." << endl;
  58. return false;
  59. }
  60. }
  61. // Find vertices
  62. DAESource vertex_source;
  63. if (!find_vertices(model.geometries[0].mesh, vertex_source))
  64. {
  65. return false;
  66. }
  67. const vector<float>& vertex_vertices = vertex_source.float_array.array;
  68. m_vertex_vertices = vertex_vertices;
  69. vector<uint16_t> vertex_indices;
  70. if (!extract_vertex_indices(model.geometries[0].mesh, vertex_indices))
  71. {
  72. return false;
  73. }
  74. m_vertex_indices = vertex_indices;
  75. // cout << "Vertices: " << vertex_vertices.size() << endl;
  76. // cout << "Indices: " << vertex_indices.size() << endl;
  77. m_mesh_header.version = MESH_VERSION;
  78. m_mesh_header.mesh_count = 1;
  79. m_mesh_header.joint_count = 0;
  80. //m_mesh_header.padding[0] = 0xCECECECE;
  81. return sizeof(MeshHeader) +
  82. sizeof(uint32_t) + vertex_vertices.size() * sizeof(float) +
  83. sizeof(uint32_t) + vertex_indices.size() * sizeof(uint16_t);
  84. }
  85. //-----------------------------------------------------------------------------
  86. void DAECompiler::write_impl(std::fstream& out_file)
  87. {
  88. out_file.write((char*) &m_mesh_header, sizeof(MeshHeader));
  89. uint32_t vertex_count = m_vertex_vertices.size();
  90. out_file.write((char*)&vertex_count, sizeof(uint32_t));
  91. out_file.write((char*) m_vertex_vertices.data(), m_vertex_vertices.size() * sizeof(float));
  92. uint32_t triangle_count = m_vertex_indices.size();
  93. out_file.write((char*)&triangle_count, sizeof(uint32_t));
  94. out_file.write((char*) m_vertex_indices.data(), m_vertex_indices.size() * sizeof(uint16_t));
  95. }
  96. //-----------------------------------------------------------------------------
  97. bool DAECompiler::parse_collada(const char* path, DAEModel& m)
  98. {
  99. XMLDocument doc;
  100. if (doc.LoadFile(path) != XML_NO_ERROR)
  101. {
  102. cout << "Unable to open '" << path << "'." << endl;
  103. return false;
  104. }
  105. // Read root
  106. XMLElement* root_node = doc.FirstChildElement("COLLADA");
  107. if (root_node == NULL)
  108. {
  109. cout << "Bad document: missing COLLADA root element." << endl;
  110. return false;
  111. }
  112. // Read geometries
  113. XMLElement* library_geometries = root_node->FirstChildElement("library_geometries");
  114. if (library_geometries == NULL)
  115. {
  116. cout << "Bad document: missing geometries library." << endl;
  117. return false;
  118. }
  119. XMLElement* geometry = library_geometries->FirstChildElement("geometry");
  120. if (geometry == NULL)
  121. {
  122. cout << "Bad document: no geometries found." << endl;
  123. return false;
  124. }
  125. for (; geometry != NULL; geometry = geometry->NextSiblingElement("geometry"))
  126. {
  127. DAEGeometry g;
  128. if (parse_geometry(geometry, g))
  129. {
  130. m.geometries.push_back(g);
  131. }
  132. else
  133. {
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. //-----------------------------------------------------------------------------
  140. bool DAECompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
  141. {
  142. // Read geometry id
  143. const char* geom_id = geometry->Attribute("id");
  144. if (geom_id == NULL)
  145. {
  146. cout << "Bad geometry: missing 'id' attribute." << endl;
  147. return false;
  148. }
  149. g.id = geom_id;
  150. // Read geometry name
  151. const char* geom_name = geometry->Attribute("name");
  152. if (geom_name == NULL)
  153. {
  154. cout << "Bad geometry: missing 'name' attribute." << endl;
  155. return false;
  156. }
  157. g.name = geom_name;
  158. // Read geometry mesh
  159. XMLElement* mesh = geometry->FirstChildElement("mesh");
  160. if (mesh == NULL)
  161. {
  162. cout << "Bad geometry: no meshes found." << endl;
  163. return false;
  164. }
  165. // Actually, there is more stuff to parse
  166. return parse_mesh(mesh, g.mesh);
  167. }
  168. //-----------------------------------------------------------------------------
  169. bool DAECompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
  170. {
  171. /// Read sources
  172. XMLElement* source = mesh->FirstChildElement("source");
  173. if (source == NULL)
  174. {
  175. cout << "Bad mesh: no sources found." << endl;
  176. return false;
  177. }
  178. for (; source != NULL; source = source->NextSiblingElement("source"))
  179. {
  180. DAESource s;
  181. if (parse_source(source, s))
  182. {
  183. m.sources.push_back(s);
  184. }
  185. else
  186. {
  187. return false;
  188. }
  189. }
  190. // Read vertices
  191. XMLElement* vertices = mesh->FirstChildElement("vertices");
  192. if (vertices == NULL)
  193. {
  194. cout << "Bad mesh: no vertices found." << endl;
  195. return false;
  196. }
  197. if (!parse_vertices(vertices, m.vertices))
  198. {
  199. return false;
  200. }
  201. // Read polylist
  202. XMLElement* polylist = mesh->FirstChildElement("polylist");
  203. if (polylist == NULL)
  204. {
  205. cout << "Bad mesh: no polylist found." << endl;
  206. return false;
  207. }
  208. return parse_polylist(polylist, m.polylist);
  209. }
  210. //-----------------------------------------------------------------------------
  211. bool DAECompiler::parse_source(XMLElement* source, DAESource& s)
  212. {
  213. // Read source id
  214. const char* source_id = source->Attribute("id");
  215. if (source_id == NULL)
  216. {
  217. cout << "Bad source: missing 'id' attribute." << endl;
  218. return false;
  219. }
  220. s.id = source_id;
  221. // Read float array
  222. XMLElement* float_array = source->FirstChildElement("float_array");
  223. if (float_array == NULL)
  224. {
  225. cout << "Bad source: no 'float_array' found." << endl;
  226. return false;
  227. }
  228. if (!parse_float_array(float_array, s.float_array))
  229. {
  230. return false;
  231. }
  232. // Read technique
  233. XMLElement* technique_common = source->FirstChildElement("technique_common");
  234. if (technique_common == NULL)
  235. {
  236. cout << "Bad source: no 'technique_common' found." << endl;
  237. return false;
  238. }
  239. if (!parse_technique_common(technique_common, s.technique_common))
  240. {
  241. return false;
  242. }
  243. return true;
  244. }
  245. //-----------------------------------------------------------------------------
  246. bool DAECompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
  247. {
  248. // Read float array id
  249. const char* float_array_id = array->Attribute("id");
  250. if (float_array_id == NULL)
  251. {
  252. cout << "Bad float array: missing 'id' attribute." << endl;
  253. return false;
  254. }
  255. a.id = float_array_id;
  256. // Read number of floats
  257. uint32_t count = 0;
  258. if (array->QueryUnsignedAttribute("count", &count) != XML_NO_ERROR)
  259. {
  260. cout << "Bad float array: missing 'count' attribute." << endl;
  261. return false;
  262. }
  263. std::istringstream floats(array->GetText());
  264. for (uint32_t i = 0; i < count; i++)
  265. {
  266. float out = 0.0f;
  267. floats >> out;
  268. a.array.push_back(out);
  269. }
  270. return true;
  271. }
  272. //-----------------------------------------------------------------------------
  273. bool DAECompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
  274. {
  275. // Read accessor
  276. XMLElement* accessor = technique->FirstChildElement("accessor");
  277. if (accessor == NULL)
  278. {
  279. cout << "Bad technique: no accessors found." << endl;
  280. return false;
  281. }
  282. return parse_accessor(accessor, t.accessor);
  283. }
  284. //-----------------------------------------------------------------------------
  285. bool DAECompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
  286. {
  287. // Read accessor source
  288. const char* accessor_source = accessor->Attribute("source");
  289. if (accessor_source == NULL)
  290. {
  291. cout << "Bad accessor: missing 'source' attribute." << endl;
  292. return false;
  293. }
  294. // First char is '#'
  295. a.source = &accessor_source[1];
  296. // Read accessor count
  297. if (accessor->QueryUnsignedAttribute("count", &a.count) != XML_NO_ERROR)
  298. {
  299. cout << "Bad accessor: missing 'count' attribute." << endl;
  300. return false;
  301. }
  302. // Read accessor stride
  303. if (accessor->QueryUnsignedAttribute("stride", &a.stride) != XML_NO_ERROR)
  304. {
  305. cout << "Bad accessor: missing 'stride' attribute." << endl;
  306. return false;
  307. }
  308. // Read params
  309. XMLElement* param = accessor->FirstChildElement("param");
  310. if (param == NULL)
  311. {
  312. cout << "Bad accessor: no params found." << endl;
  313. return false;
  314. }
  315. for (; param != NULL; param = param->NextSiblingElement("param"))
  316. {
  317. DAEParam p;
  318. if (parse_param(param, p))
  319. {
  320. a.params.push_back(p);
  321. }
  322. else
  323. {
  324. return false;
  325. }
  326. }
  327. return true;
  328. }
  329. //-----------------------------------------------------------------------------
  330. bool DAECompiler::parse_param(XMLElement* param, DAEParam& p)
  331. {
  332. // Read param name
  333. const char* param_name = param->Attribute("name");
  334. if (param_name == NULL)
  335. {
  336. cout << "Bad param: missing 'name' attribute." << endl;
  337. return false;
  338. }
  339. p.name = param_name;
  340. // Read param type
  341. const char* param_type = param->Attribute("type");
  342. if (param_type == NULL)
  343. {
  344. cout << "Bad param: missing 'type' attribute." << endl;
  345. return false;
  346. }
  347. p.type = param_type;
  348. return true;
  349. }
  350. //-----------------------------------------------------------------------------
  351. bool DAECompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
  352. {
  353. // Read vertices id
  354. const char* vertices_id = vertices->Attribute("id");
  355. if (vertices_id == NULL)
  356. {
  357. cout << "Bad vertices: missing 'id' attribute." << endl;
  358. return false;
  359. }
  360. v.id = vertices_id;
  361. // Read inputs
  362. XMLElement* input = vertices->FirstChildElement("input");
  363. if (input == NULL)
  364. {
  365. cout << "Bad vertices: no inputs found." << endl;
  366. return false;
  367. }
  368. for (; input != NULL; input = input->NextSiblingElement("input"))
  369. {
  370. DAEInput i;
  371. if (parse_input(input, i))
  372. {
  373. v.inputs.push_back(i);
  374. }
  375. else
  376. {
  377. return false;
  378. }
  379. }
  380. return true;
  381. }
  382. //-----------------------------------------------------------------------------
  383. bool DAECompiler::parse_input(XMLElement* input, DAEInput& i)
  384. {
  385. // Read input semantic
  386. const char* input_semantic = input->Attribute("semantic");
  387. if (input_semantic == NULL)
  388. {
  389. cout << "Bad input: missing 'semantic' attribute." << endl;
  390. return false;
  391. }
  392. i.semantic = input_semantic;
  393. // Read input source
  394. const char* input_source = input->Attribute("source");
  395. if (input_source == NULL)
  396. {
  397. cout << "Bad input: missing 'source' attribute." << endl;
  398. return false;
  399. }
  400. // First char is '#'
  401. i.source = &input_source[1];
  402. if (input->QueryUnsignedAttribute("offset", &i.offset) == XML_NO_ATTRIBUTE)
  403. {
  404. i.offset = 0;
  405. }
  406. return true;
  407. }
  408. //-----------------------------------------------------------------------------
  409. bool DAECompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
  410. {
  411. // Read polylist count
  412. if (polylist->QueryUnsignedAttribute("count", &p.count) != XML_NO_ERROR)
  413. {
  414. cout << "Bad polylist: missing 'count' attribute." << endl;
  415. return false;
  416. }
  417. // Read inputs
  418. XMLElement* input = polylist->FirstChildElement("input");
  419. if (input == NULL)
  420. {
  421. cout << "Bad polylist: no inputs found." << endl;
  422. return false;
  423. }
  424. for (; input != NULL; input = input->NextSiblingElement("input"))
  425. {
  426. DAEInput i;
  427. if (parse_input(input, i))
  428. {
  429. p.inputs.push_back(i);
  430. }
  431. else
  432. {
  433. return false;
  434. }
  435. }
  436. // Read vcount
  437. XMLElement* vcount = polylist->FirstChildElement("vcount");
  438. if (vcount == NULL)
  439. {
  440. cout << "Bad polylist: no vcount found." << endl;
  441. return false;
  442. }
  443. std::istringstream vcount_text(vcount->GetText());
  444. uint32_t vcount_item = 0;
  445. while (vcount_text >> vcount_item)
  446. {
  447. p.vcount.push_back(vcount_item);
  448. }
  449. // Read p
  450. XMLElement* p_element = polylist->FirstChildElement("p");
  451. if (p_element == NULL)
  452. {
  453. cout << "Bad polylist: no p found." << endl;
  454. return false;
  455. }
  456. std::istringstream p_text(p_element->GetText());
  457. uint32_t p_item = 0;
  458. while (p_text >> p_item)
  459. {
  460. p.p.push_back(p_item);
  461. }
  462. return true;
  463. }
  464. //-----------------------------------------------------------------------------
  465. bool DAECompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
  466. {
  467. const vector<DAESource>& sources = mesh.sources;
  468. const vector<DAEInput>& inputs = mesh.vertices.inputs;
  469. for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
  470. {
  471. const DAEInput& input = inputs[input_i];
  472. for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
  473. {
  474. const DAESource& source = sources[source_i];
  475. if (input.semantic == "POSITION" && input.source == source.id)
  476. {
  477. source_out = source;
  478. return true;
  479. }
  480. }
  481. }
  482. cout << "Failed to find 'POSITION' source." << endl;
  483. return false;
  484. }
  485. //-----------------------------------------------------------------------------
  486. bool DAECompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
  487. {
  488. const vector<DAESource>& sources = mesh.sources;
  489. const vector<DAEInput>& inputs = mesh.polylist.inputs;
  490. for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
  491. {
  492. const DAEInput& input = inputs[input_i];
  493. for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
  494. {
  495. const DAESource& source = sources[source_i];
  496. cout << input.semantic << " " << input.source << " " << source.id << endl;
  497. if (input.semantic == "NORMAL" && input.source == source.id)
  498. {
  499. source_out = source;
  500. return true;
  501. }
  502. }
  503. }
  504. cout << "Failed to find 'NORMAL' source." << endl;
  505. return false;
  506. }
  507. //-----------------------------------------------------------------------------
  508. bool DAECompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
  509. {
  510. // Find vertices
  511. DAESource vertex_source;
  512. if (!find_vertices(mesh, vertex_source))
  513. {
  514. return false;
  515. }
  516. // Read vertices
  517. const vector<uint32_t>& primitives = mesh.polylist.p;
  518. const vector<float>& vertices = vertex_source.float_array.array;
  519. // FIXME FIXME FIXME
  520. uint32_t offset = 0;
  521. uint32_t attribs = mesh.polylist.inputs.size();
  522. uint32_t prims = 0;
  523. while(prims < primitives.size())
  524. {
  525. indices_out.push_back((uint16_t) primitives[prims]);
  526. prims += attribs;
  527. }
  528. return true;
  529. }
  530. } // namespace crown