MeshCompiler.cpp 15 KB

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