loadModel.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #include <vector>
  2. #include "loadModel.h"
  3. #include "vec3.h"
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. bool loadOBJ( const char *path, std::vector<vec3> &out_vertices, vec3 *bound,
  9. unsigned char mirror)
  10. {
  11. //Open file
  12. FILE *file = fopen(path, "r");
  13. //Failed to open file
  14. if (!file)
  15. {
  16. printf("Error opening file: %s\n", path);
  17. return false;
  18. }
  19. //Vector for vertices - Here will be saved all vertices by index (from file)
  20. std::vector<vec3> temp_vertices;
  21. //Buffer
  22. char lineHeader[100];
  23. //Read each word
  24. while (fscanf(file, "%s", lineHeader) != EOF)
  25. {
  26. //Found comment
  27. if ( lineHeader[0] == '#' )
  28. //Skip line
  29. fscanf(file, "%*[^\n]"); else
  30. //Found vertex
  31. if ( lineHeader[0] == 'v' )
  32. {
  33. //Create new vertex and get it's coordinates
  34. vec3 vertex;
  35. fscanf(file, "%f %f %f", &vertex.x, &vertex.y, &vertex.z);
  36. //Apply mirroring (if exists)
  37. if ( mirror == 1 )
  38. vertex.x = -vertex.x;
  39. if ( mirror == 2 )
  40. vertex.y = -vertex.y;
  41. if ( mirror == 4 )
  42. vertex.z = -vertex.z;
  43. //Save to vertices by index
  44. temp_vertices.push_back(vertex);
  45. //vec3 is passes for bound
  46. if (bound)
  47. {
  48. //This saves bound from center to positive axis
  49. // it isn't the best way, but for now it works
  50. if (bound->x < vertex.x) bound->x = vertex.x;
  51. if (bound->y < vertex.y) bound->y = vertex.y;
  52. if (bound->z < vertex.z) bound->z = vertex.z;
  53. }
  54. } else
  55. //Found face
  56. if ( lineHeader[0] == 'f' )
  57. {
  58. //Check the next three numbers
  59. unsigned int j;
  60. for (j = 0; j < 3; j++)
  61. {
  62. //Get index to vertex (from temp_vertices)
  63. unsigned int index;
  64. fscanf(file, "%d", &index);
  65. //Push vertex to final array. -1 because indexes start from 1 in .obj
  66. out_vertices.push_back(temp_vertices[ index-1 ]);
  67. }
  68. }
  69. } //While loop
  70. //Close file
  71. fclose(file);
  72. //Success!
  73. return true;
  74. }
  75. /* Opens file, reads header,
  76. * parses vertices (3 floats - position, 3 bytes - color) and faces (triangles only).
  77. * Toy parser only, it doesn't support all .ply files (probably)
  78. */
  79. bool loadPLY(
  80. const char *path,
  81. std::vector<vec3> &out_vertices,
  82. std::vector<vec3> &out_color,
  83. vec3 *bound,
  84. unsigned char mirror
  85. )
  86. {
  87. //Open file
  88. FILE *file = fopen(path, "r");
  89. //Failed to open file
  90. if (!file)
  91. {
  92. printf("Error opening file: %s\n", path);
  93. return false;
  94. }
  95. //Vector for vertices - save vertices/colors by index (from file)
  96. std::vector<vec3> temp_vertices, temp_color;
  97. //How many vertices and faces to expect (from PLY header)
  98. unsigned int vertices = 0, faces = 0;
  99. //Read each line (limited to 100 chars - I should change that sometime)
  100. char lineHeader[100];
  101. //Read words until end of file or end of header
  102. while ( fscanf(file, "%s", lineHeader) != EOF
  103. && strcmp(lineHeader, "end_header") != 0 )
  104. {
  105. //Found comment - Skip line
  106. if ( strcmp(lineHeader, "comment") == 0 )
  107. fscanf(file, "%*[^\n]"); else
  108. //Found an element
  109. if ( strcmp(lineHeader, "element") == 0 )
  110. {
  111. //Get next word
  112. fscanf(file, "%s", lineHeader);
  113. //Found vertices - save number of vertices
  114. if ( strcmp(lineHeader, "vertex") == 0 )
  115. fscanf(file, "%d", &vertices); else
  116. //Found faces - save number of faces
  117. if ( strcmp(lineHeader, "face") == 0 )
  118. fscanf(file, "%d", &faces);
  119. }
  120. }
  121. //Read vertices
  122. unsigned int i;
  123. for (i = 0; i < vertices; i++)
  124. {
  125. //New vertex
  126. vec3 vertex;
  127. //RGB values (0-255)
  128. unsigned char r, g, b;
  129. //Read vertex and colors values
  130. fscanf(file, "%f %f %f %hhu %hhu %hhu",
  131. &vertex.x, &vertex.y, &vertex.z,
  132. &r, &g, &b);
  133. //Create color and convert 0-255 to 0.0-1.0
  134. vec3 color(r /255.0f, g /255.0f, b /255.0f);
  135. //Apply mirroring (if exists)
  136. if ( mirror == 1 )
  137. vertex.x = -vertex.x;
  138. if ( mirror == 2 )
  139. vertex.y = -vertex.y;
  140. if ( mirror == 4)
  141. vertex.z = -vertex.z;
  142. //Add new vertex and color to temporary vectors
  143. temp_vertices.push_back(vertex);
  144. temp_color .push_back(color );
  145. //Calculate boundbox (if exists)
  146. if (bound)
  147. {
  148. if (bound->x < vertex.x) bound->x = vertex.x;
  149. if (bound->y < vertex.y) bound->y = vertex.y;
  150. if (bound->z < vertex.z) bound->z = vertex.z;
  151. }
  152. }
  153. //For each face
  154. for (i = 0; i < faces; i++)
  155. {
  156. //Faces number
  157. int fn;
  158. fscanf(file, "%d", &fn);
  159. //Get all faces
  160. int temp[fn];
  161. int j;
  162. for (j = 0; j < fn; j++)
  163. fscanf(file, "%d", temp+j);
  164. //Apply first face
  165. out_vertices.push_back( temp_vertices[ temp[0] ]);
  166. out_vertices.push_back( temp_vertices[ temp[1] ]);
  167. out_vertices.push_back( temp_vertices[ temp[2] ]);
  168. if (&out_color)
  169. {
  170. out_color.push_back( temp_color[ temp[0] ]);
  171. out_color.push_back( temp_color[ temp[1] ]);
  172. out_color.push_back( temp_color[ temp[2] ]);
  173. }
  174. //For each extra face
  175. j = 2;
  176. while (j < fn-1)
  177. {
  178. //More than 1 extra vertices
  179. if (fn-1 -j > 1)
  180. {
  181. out_vertices.push_back( temp_vertices[ temp[j ] ]);
  182. out_vertices.push_back( temp_vertices[ temp[j+1] ]);
  183. out_vertices.push_back( temp_vertices[ temp[j+2] ]);
  184. if (&out_color)
  185. {
  186. out_color.push_back( temp_color[ temp[j ] ]);
  187. out_color.push_back( temp_color[ temp[j+1] ]);
  188. out_color.push_back( temp_color[ temp[j+2] ]);
  189. }
  190. }
  191. //Only 1 extra vertex - finish shape
  192. else
  193. {
  194. out_vertices.push_back( temp_vertices[ temp[j ] ]);
  195. out_vertices.push_back( temp_vertices[ temp[j+1] ]);
  196. out_vertices.push_back( temp_vertices[ temp[ 0 ] ]);
  197. if (&out_color)
  198. {
  199. out_color.push_back( temp_color[ temp[j ] ]);
  200. out_color.push_back( temp_color[ temp[j+1] ]);
  201. out_color.push_back( temp_color[ temp[ 0 ] ]);
  202. }
  203. }
  204. //Advance counter
  205. j += 2;
  206. }
  207. }
  208. //Close file
  209. fclose(file);
  210. //Success!
  211. return true;
  212. }
  213. // So far parses vertex xyz and colors rgb
  214. mesh_data *loadPly(const char *path, int flags)
  215. {
  216. //File
  217. FILE *f;
  218. if ( !(f = fopen(path, "r")) )
  219. {
  220. fprintf(stderr, "loadPly: failed to open file: %s: %s\n",
  221. path, strerror(errno));
  222. return 0;
  223. }
  224. //Buffer
  225. char *buff = (char*)malloc(sizeof(char) *100);
  226. //Data
  227. unsigned int vertices = 0, faces = 0;
  228. std::vector<property> vert_prop;
  229. unsigned char face_ind_form, vert_ind_form;
  230. //Struct to return
  231. mesh_data *obj = new mesh_data;
  232. /* Check ply magic number:
  233. * Get 3 first chars. (ignore anything on the rest of the line)
  234. * Add terminating byte.
  235. * Compare with "ply".
  236. */
  237. if ( fscanf(f, "%3c%*[^\n]%*1c", buff) == EOF )
  238. goto error;
  239. buff[3] = '\0';
  240. if ( strcmp(buff, "ply") != 0 )
  241. goto error;
  242. /* Check format
  243. * Get first word.
  244. * Compare with "format".
  245. * Get rest of line
  246. * Compare with "ascii 1.0" | "binary_little_endian 1.0"
  247. | "binary_big_endian 1.0"
  248. * Set `format` accordingly.
  249. */
  250. char format;
  251. if ( fscanf(f, "%s", buff) == EOF )
  252. goto error;
  253. //Check format
  254. if ( strcmp(buff, "format") == 0 )
  255. {
  256. //Get actual format
  257. if ( fscanf(f, "%*c%[^\n]", buff) == EOF)
  258. goto error;
  259. //Ascii
  260. if ( strcmp(buff, "ascii 1.0") == 0 )
  261. format = 'a'; else
  262. //Little endian
  263. if ( strcmp(buff, "binary_little_endian 1.0") == 0 )
  264. format = 'l'; else
  265. //Big endian
  266. if ( strcmp(buff, "binary_big_endian 1.0") == 0 )
  267. format = 'b';
  268. //Error
  269. else goto error;
  270. }
  271. else goto error;
  272. /* What this parser reads:
  273. * element vertex
  274. property x
  275. property y
  276. property z
  277. property red
  278. property green
  279. property blue
  280. * element face
  281. property vertex_indices
  282. */
  283. /* Get elements
  284. * Read word-by-word.
  285. * Compare with "element"
  286. * Read next word.
  287. * Compare with "vertex"
  288. * Read next word as number of vertices to expect.
  289. * Compare with "faces"
  290. * Read mext wprd as number of faces to expect.
  291. * Compare with "property"
  292. * Read next word.
  293. * Compare with "list"
  294. * Read next word.
  295. * Get type amount of values from it.
  296. * Read next word.
  297. * Get type of actual values from it.
  298. * Read next word.
  299. * Hope that it's "vertex_indices"
  300. * else
  301. * Get property type (int, float, etc.)
  302. * Read next word.
  303. * Compare with x/y/z - red/green/blue
  304. */
  305. //Read word by word
  306. while ( fscanf(f, "%s", buff) != EOF
  307. && strcmp(buff, "end_header") != 0 )
  308. {
  309. //Found an element
  310. if ( strcmp(buff, "element") == 0 )
  311. {
  312. //This parser only reads vertices and faces
  313. if ( fscanf(f, "%s", buff) == EOF )
  314. goto error;
  315. //Vertex
  316. if ( strcmp(buff, "vertex") == 0 )
  317. {
  318. //Get vertex number
  319. if ( fscanf(f, "%u", &vertices) == EOF )
  320. goto error;
  321. } else
  322. //Face
  323. if ( strcmp(buff, "face") == 0 )
  324. {
  325. if ( fscanf(f, "%u", &faces) == EOF )
  326. goto error;
  327. }
  328. //Unsupported element - ignore
  329. else continue;
  330. } else
  331. //Found property
  332. if ( strcmp(buff, "property") == 0 )
  333. {
  334. //Face's property
  335. /* if ( faces != 0 )
  336. {
  337. //Get property type
  338. if (fscanf(f, "%s", buff) == EOF)
  339. goto error;
  340. //Ignore anything that is not a list
  341. if (strcmp(buff, "list") != 0)
  342. {
  343. if (fscanf(f, "%*[^\n]") == EOF)
  344. goto error;
  345. continue;
  346. }
  347. //Get face indices and vertex indices formats
  348. if (fscanf(f, "%s", buff) == EOF) goto error;
  349. face_ind_form = form_to_num(buff);
  350. if (fscanf(f, "%s", buff) == EOF) goto error;
  351. vert_ind_form = form_to_num(buff);
  352. //Get flag
  353. if (fscanf(f, "%s", buff) == EOF)
  354. goto error;
  355. //Property was vertex_indices - stop looking
  356. if (strcmp(buff, "vertex_indices") == 0)
  357. break;
  358. //Skip line
  359. if (fscanf(f, "%[^\n]", buff) == EOF)
  360. goto error;
  361. } else*/
  362. //Vertex's property
  363. if ( vertices != 0 )
  364. {
  365. //Init property
  366. property pr;
  367. //Get format
  368. if ( fscanf(f, "%s", buff) == EOF )
  369. goto error;
  370. pr.format = form_to_num( buff );
  371. //Get flag
  372. if ( fscanf(f, "%s", buff) == EOF )
  373. goto error;
  374. pr.flag = flag_to_num( buff );
  375. //Add property to vertex properties
  376. vert_prop.push_back(pr);
  377. //Skip line
  378. if ( fscanf(f, "%*[^\n]") == EOF )
  379. goto error;
  380. }
  381. }
  382. //Ignore unknown line (including comments)
  383. else
  384. {
  385. if ( fscanf(f, "%[^\n]", buff) == EOF )
  386. {
  387. printf("Ignored: %s\n", buff);
  388. goto error;
  389. }
  390. }
  391. } //Finished header
  392. printf("Parser is going to search for:\n");
  393. for (int i = 0; i < vert_prop.size(); i++)
  394. {
  395. printf("%s (%s)\n", flagstr(vert_prop[i].flag), formatstr(vert_prop[i].format));
  396. }
  397. return NULL;
  398. if (true)
  399. {
  400. char test[100] = "something";
  401. void *p;
  402. if ( ( p = malloc( sizeof(void*) *vert_prop.size() ) ) == NULL)
  403. goto error;
  404. unsigned int j;
  405. for (j = 0; j < vert_prop.size(); j++)
  406. {
  407. switch (vert_prop[j].flag)
  408. {
  409. //case FLG_V_POS_X:
  410. // p[j] = &mesh_data.pos;
  411. }
  412. switch (vert_prop[j].format)
  413. {
  414. case PLY_CHAR:
  415. strcat(test, "%s");
  416. }
  417. }
  418. printf("Search string: %s\n", test);
  419. }
  420. //float *temp_vertices;
  421. //if (temp_vertices = malloc() == NULL)
  422. // goto error;
  423. //Print all data gatheres so far
  424. unsigned int i;
  425. for (i = 0; i < vert_prop.size(); i++)
  426. {
  427. printf("Vertex property: %d\n", i);
  428. printf("format: %d | flag: %d\n", vert_prop[i].format, vert_prop[i].flag);
  429. }
  430. printf("Face indices format: %d\n" , face_ind_form);
  431. printf("Vertex indices format: %d\n", vert_ind_form);
  432. //Close file
  433. fclose(f);
  434. return obj;
  435. //Error
  436. error:
  437. if (ferror(f))
  438. fprintf(stderr, "loadPly: error while parsing: %s: %s\n", path,
  439. strerror(errno)); else
  440. if (feof(f))
  441. printf("loadPly: unexpected end of file: %s\n", path);
  442. else
  443. printf("loadPly: unexpected error: %s\n", path);
  444. fclose(f);
  445. return 0;
  446. }
  447. //Turns the read format to a number (specified by defines on loadModel.h)
  448. unsigned char form_to_num( char *format )
  449. {
  450. if (strcmp(format, "char") == 0
  451. || strcmp(format, "int8") == 0 )
  452. return PLY_CHAR;
  453. if (strcmp(format, "uchar") == 0
  454. || strcmp(format, "uint8") == 0 )
  455. return PLY_UCHAR;
  456. if (strcmp(format, "short") == 0
  457. || strcmp(format, "int16") == 0 )
  458. return PLY_SHORT;
  459. if (strcmp(format, "ushort") == 0
  460. || strcmp(format, "uint16") == 0 )
  461. return PLY_USHORT;
  462. if (strcmp(format, "int" ) == 0
  463. || strcmp(format, "int32") == 0 )
  464. return PLY_INT;
  465. if (strcmp(format, "uint" ) == 0
  466. || strcmp(format, "uint32") == 0 )
  467. return PLY_UINT;
  468. if (strcmp(format, "float" ) == 0
  469. || strcmp(format, "float32") == 0 )
  470. return PLY_FLOAT;
  471. if (strcmp(format, "double" ) == 0
  472. || strcmp(format, "float64") == 0 )
  473. return PLY_DOUBLE;
  474. return PLY_UNSUPPORTED;
  475. }
  476. unsigned int flag_to_num( char *flag )
  477. {
  478. if (strcmp(flag, "x") == 0)
  479. return FLG_V_POS_X;
  480. if (strcmp(flag, "y") == 0)
  481. return FLG_V_POS_Y;
  482. if (strcmp(flag, "z") == 0)
  483. return FLG_V_POS_Z;
  484. if (strcmp(flag, "red") == 0)
  485. return FLG_V_COL_R;
  486. if (strcmp(flag, "green") == 0)
  487. return FLG_V_COL_G;
  488. if (strcmp(flag, "blue") == 0)
  489. return FLG_V_COL_B;
  490. return 0;
  491. }
  492. char *flagstr( unsigned int flag )
  493. {
  494. switch (flag)
  495. {
  496. case FLG_V_POS_X: return "vertex position x";
  497. case FLG_V_POS_Y: return "vertex position y";
  498. case FLG_V_POS_Z: return "vertex position z";
  499. case FLG_V_COL_R: return "vertex color red";
  500. case FLG_V_COL_G: return "vertex color green";
  501. case FLG_V_COL_B: return "vertex color blue";
  502. case FLG_F_VINDICES: return "vertex indices";
  503. }
  504. return "Nothingness";
  505. }
  506. char *formatstr( char format )
  507. {
  508. switch (format)
  509. {
  510. case PLY_CHAR: return "char";
  511. case PLY_UCHAR: return "unsigned char";
  512. case PLY_SHORT: return "short";
  513. case PLY_USHORT: return "unsigned short";
  514. case PLY_INT: return "int";
  515. case PLY_UINT: return "unsigned int";
  516. case PLY_FLOAT: return "float";
  517. case PLY_DOUBLE: return "double";
  518. }
  519. return "Unsupported";
  520. }