iron_obj.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #include "iron_obj.h"
  2. #include <math.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "iron_array.h"
  6. #include "iron_vec4.h"
  7. #include "iron_string.h"
  8. #include "iron_gc.h"
  9. static raw_mesh_t *part = NULL;
  10. static f32_array_t pos_temp;
  11. static f32_array_t uv_temp;
  12. static f32_array_t nor_temp;
  13. static uint32_t va[512];
  14. static uint32_t ua[512];
  15. static uint32_t na[512];
  16. static int vi = 0;
  17. static int ui = 0;
  18. static int ni = 0;
  19. static uint8_t buf[128];
  20. static char str[256];
  21. static int vind_off = 0;
  22. static int tind_off = 0;
  23. static int nind_off = 0;
  24. static uint8_t *bytes = NULL;
  25. static size_t bytes_length = 0;
  26. static f32_array_t *pos_first;
  27. static f32_array_t *uv_first;
  28. static f32_array_t *nor_first;
  29. static int read_int() {
  30. int bi = 0;
  31. while (true) { // Read into buffer
  32. char c = bytes[part->pos];
  33. if (c == '/' || c == '\n' || c == '\r' || c == ' ') {
  34. break;
  35. }
  36. part->pos++;
  37. buf[bi++] = c;
  38. }
  39. int res = 0; // Parse buffer into int
  40. int dec = 1;
  41. int off = buf[0] == '-' ? 1 : 0;
  42. int len = bi - 1;
  43. for (int i = 0; i < bi - off; ++i) {
  44. res += (buf[len - i] - 48) * dec;
  45. dec *= 10;
  46. }
  47. if (off > 0) {
  48. res *= -1;
  49. }
  50. return res;
  51. }
  52. static void read_face_fast() {
  53. while (true) {
  54. va[vi++] = read_int() - 1;
  55. part->pos++; // '/'
  56. ua[ui++] = read_int() - 1;
  57. part->pos++; // '/'
  58. na[ni++] = read_int() - 1;
  59. if (bytes[part->pos] == '\n' || bytes[part->pos] == '\r') {
  60. break;
  61. }
  62. part->pos++; // ' '
  63. // Some exporters put space at the end of "f" line
  64. if (vi >= 3 && (bytes[part->pos] == '\n' || bytes[part->pos] == '\r')) {
  65. break;
  66. }
  67. }
  68. }
  69. static void read_face() {
  70. while (true) {
  71. va[vi++] = read_int() - 1;
  72. if (uv_temp.length > 0 || nor_temp.length > 0) {
  73. part->pos++; // "/"
  74. if (uv_temp.length > 0) {
  75. ua[ui++] = read_int() - 1;
  76. }
  77. if (nor_temp.length > 0) {
  78. // Some exporters put fake uv index even when uv data is not present... (f 1/1/1 instead of f 1//1)
  79. bool has_bogus_uv = uv_temp.length == 0 && bytes[part->pos] != '/';
  80. if (has_bogus_uv) {
  81. read_int();
  82. }
  83. part->pos++; // "/"
  84. na[ni++] = read_int() - 1;
  85. }
  86. }
  87. // Some exporters put "//" even when normal and uv data are not present (f 1//)
  88. else if (uv_temp.length == 0 && nor_temp.length == 0 && bytes[part->pos] == '/') {
  89. part->pos += 2;
  90. }
  91. if (bytes[part->pos] == '\n' || bytes[part->pos] == '\r') {
  92. break;
  93. }
  94. part->pos++; // " "
  95. // Some exporters put space at the end of "f" line
  96. if (vi >= 3 && (bytes[part->pos] == '\n' || bytes[part->pos] == '\r')) {
  97. break;
  98. }
  99. }
  100. }
  101. static float read_float() {
  102. int bi = 0;
  103. while (true) { // Read into buffer
  104. char c = bytes[part->pos];
  105. if (c == ' ' || c == '\n' || c == '\r') {
  106. break;
  107. }
  108. if (c == 'E' || c == 'e') {
  109. part->pos++;
  110. int first = buf[0] == '-' ? -(buf[1] - 48) : buf[0] - 48;
  111. int exp = read_int();
  112. int dec = 1;
  113. int loop = exp > 0 ? exp : -exp;
  114. for (int i = 0; i < loop; ++i) {
  115. dec *= 10;
  116. }
  117. return exp > 0 ? (float)first * dec : (float)first / dec;
  118. }
  119. part->pos++;
  120. buf[bi++] = c;
  121. }
  122. float res = 0.0; // Parse buffer into float
  123. int64_t dot = 1;
  124. int64_t dec = 1;
  125. int off = buf[0] == '-' ? 1 : 0;
  126. int len = bi - 1;
  127. for (int i = 0; i < bi - off; ++i) {
  128. char c = buf[len - i];
  129. if (c == '.') {
  130. dot = dec;
  131. continue;
  132. }
  133. res += (c - 48) * dec;
  134. dec *= 10;
  135. }
  136. if (off > 0) {
  137. res /= -dot;
  138. }
  139. else {
  140. res /= dot;
  141. }
  142. return res;
  143. }
  144. static char *read_string() {
  145. size_t begin = part->pos;
  146. while (true) {
  147. char c = bytes[part->pos];
  148. if (c == '\n' || c == '\r' || c == ' ') {
  149. break;
  150. }
  151. part->pos++;
  152. }
  153. for (int i = 0; i < part->pos - begin; ++i) {
  154. str[i] = bytes[begin + i];
  155. }
  156. str[part->pos - begin] = '\0';
  157. return str;
  158. }
  159. static void next_line() {
  160. while (true) {
  161. char c = bytes[part->pos++];
  162. if (c == '\n' || part->pos >= bytes_length) {
  163. break; // \n, \r\n
  164. }
  165. }
  166. }
  167. static int get_tile(int i1, int i2, int i3, i32_array_t *uv_indices, int tiles_u) {
  168. float u1 = uv_temp.buffer[uv_indices->buffer[i1] * 2 ];
  169. float v1 = uv_temp.buffer[uv_indices->buffer[i1] * 2 + 1];
  170. float u2 = uv_temp.buffer[uv_indices->buffer[i2] * 2 ];
  171. float v2 = uv_temp.buffer[uv_indices->buffer[i2] * 2 + 1];
  172. float u3 = uv_temp.buffer[uv_indices->buffer[i3] * 2 ];
  173. float v3 = uv_temp.buffer[uv_indices->buffer[i3] * 2 + 1];
  174. int tile_u = (int)((u1 + u2 + u3) / 3);
  175. int tile_v = (int)((v1 + v2 + v3) / 3);
  176. return tile_u + tile_v * tiles_u;
  177. }
  178. static bool pnpoly(float v0x, float v0y, float v1x, float v1y, float v2x, float v2y, float px, float py) {
  179. // https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
  180. bool c = false;
  181. if (((v0y > py) != (v2y > py)) && (px < (v2x - v0x) * (py - v0y) / (v2y - v0y) + v0x)) {
  182. c = !c;
  183. }
  184. if (((v1y > py) != (v0y > py)) && (px < (v0x - v1x) * (py - v1y) / (v0y - v1y) + v1x)) {
  185. c = !c;
  186. }
  187. if (((v2y > py) != (v1y > py)) && (px < (v1x - v2x) * (py - v2y) / (v1y - v2y) + v2x)) {
  188. c = !c;
  189. }
  190. return c;
  191. }
  192. iron_vector4_t calc_normal(iron_vector4_t a, iron_vector4_t b, iron_vector4_t c) {
  193. iron_vector4_t cb = vec4_sub(c, b);
  194. iron_vector4_t ab = vec4_sub(a, b);
  195. cb = vec4_cross(cb, ab);
  196. cb = vec4_norm(cb);
  197. return cb;
  198. }
  199. // 'o' for object split, 'g' for groups, 'u'semtl for materials
  200. raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, bool udim) {
  201. bytes = file_bytes->buffer;
  202. bytes_length = file_bytes->length;
  203. part = gc_alloc(sizeof(raw_mesh_t));
  204. part->scale_pos = 1.0;
  205. part->scale_tex = 1.0;
  206. part->pos = start_pos;
  207. part->udims_u = 1;
  208. part->udims_v = 1;
  209. part->name = string_copy(str);
  210. i32_array_t pos_indices = {0};
  211. i32_array_t uv_indices = {0};
  212. i32_array_t nor_indices = {0};
  213. bool reading_faces = false;
  214. bool reading_object = false;
  215. bool full_attrib = false;
  216. if (start_pos == 0) {
  217. vind_off = tind_off = nind_off = 0;
  218. }
  219. if (split_code == 'u' && start_pos > 0) {
  220. pos_temp = *pos_first;
  221. nor_temp = *nor_first;
  222. uv_temp = *uv_first;
  223. }
  224. else {
  225. memset(&pos_temp, 0, sizeof(pos_temp));
  226. memset(&uv_temp, 0, sizeof(uv_temp));
  227. memset(&nor_temp, 0, sizeof(nor_temp));
  228. }
  229. while (true) {
  230. if (part->pos >= bytes_length) {
  231. break;
  232. }
  233. char c0 = bytes[part->pos++];
  234. if (reading_object && reading_faces && (c0 == 'v' || c0 == split_code)) {
  235. part->pos--;
  236. part->has_next = true;
  237. break;
  238. }
  239. if (c0 == 'v') {
  240. char c1 = bytes[part->pos++];
  241. if (c1 == ' ') {
  242. if (bytes[part->pos] == ' ') part->pos++; // Some exporters put additional space directly after "v"
  243. f32_array_push(&pos_temp, read_float());
  244. part->pos++; // Space
  245. f32_array_push(&pos_temp, read_float());
  246. part->pos++; // Space
  247. f32_array_push(&pos_temp, read_float());
  248. }
  249. else if (c1 == 't') {
  250. part->pos++; // Space
  251. f32_array_push(&uv_temp, read_float());
  252. part->pos++; // Space
  253. f32_array_push(&uv_temp, read_float());
  254. if (nor_temp.length > 0) {
  255. full_attrib = true;
  256. }
  257. }
  258. else if (c1 == 'n') {
  259. part->pos++; // Space
  260. f32_array_push(&nor_temp, read_float());
  261. part->pos++; // Space
  262. f32_array_push(&nor_temp, read_float());
  263. part->pos++; // Space
  264. f32_array_push(&nor_temp, read_float());
  265. if (uv_temp.length > 0) {
  266. full_attrib = true;
  267. }
  268. }
  269. }
  270. else if (c0 == 'f') {
  271. part->pos++; // Space
  272. if (bytes[part->pos] == ' ') {
  273. part->pos++; // Some exporters put additional space directly after "f"
  274. }
  275. reading_faces = true;
  276. vi = ui = ni = 0;
  277. full_attrib ? read_face_fast() : read_face();
  278. if (vi <= 4) { // Convex, fan triangulation
  279. i32_array_push(&pos_indices, va[0]);
  280. i32_array_push(&pos_indices, va[1]);
  281. i32_array_push(&pos_indices, va[2]);
  282. for (int i = 3; i < vi; ++i) {
  283. i32_array_push(&pos_indices, va[0]);
  284. i32_array_push(&pos_indices, va[i - 1]);
  285. i32_array_push(&pos_indices, va[i]);
  286. }
  287. if (uv_temp.length > 0) {
  288. i32_array_push(&uv_indices, ua[0]);
  289. i32_array_push(&uv_indices, ua[1]);
  290. i32_array_push(&uv_indices, ua[2]);
  291. for (int i = 3; i < ui; ++i) {
  292. i32_array_push(&uv_indices, ua[0]);
  293. i32_array_push(&uv_indices, ua[i - 1]);
  294. i32_array_push(&uv_indices, ua[i]);
  295. }
  296. }
  297. if (nor_temp.length > 0) {
  298. i32_array_push(&nor_indices, na[0]);
  299. i32_array_push(&nor_indices, na[1]);
  300. i32_array_push(&nor_indices, na[2]);
  301. for (int i = 3; i < ni; ++i) {
  302. i32_array_push(&nor_indices, na[0]);
  303. i32_array_push(&nor_indices, na[i - 1]);
  304. i32_array_push(&nor_indices, na[i]);
  305. }
  306. }
  307. }
  308. else { // Convex or concave, ear clipping
  309. int _vind_off = split_code == 'u' ? 0 : vind_off;
  310. int _nind_off = split_code == 'u' ? 0 : nind_off;
  311. float nx = 0.0;
  312. float ny = 0.0;
  313. float nz = 0.0;
  314. if (nor_temp.length > 0) {
  315. nx = nor_temp.buffer[(na[0] - _nind_off) * 3 ];
  316. ny = nor_temp.buffer[(na[0] - _nind_off) * 3 + 1];
  317. nz = nor_temp.buffer[(na[0] - _nind_off) * 3 + 2];
  318. }
  319. else {
  320. iron_vector4_t n = calc_normal(
  321. vec4_create(pos_temp.buffer[(va[0] - _vind_off) * 3], pos_temp.buffer[(va[0] - _vind_off) * 3 + 1], pos_temp.buffer[(va[0] - _vind_off) * 3 + 2], 1.0f),
  322. vec4_create(pos_temp.buffer[(va[1] - _vind_off) * 3], pos_temp.buffer[(va[1] - _vind_off) * 3 + 1], pos_temp.buffer[(va[1] - _vind_off) * 3 + 2], 1.0f),
  323. vec4_create(pos_temp.buffer[(va[2] - _vind_off) * 3], pos_temp.buffer[(va[2] - _vind_off) * 3 + 1], pos_temp.buffer[(va[2] - _vind_off) * 3 + 2], 1.0f)
  324. );
  325. nx = n.x;
  326. ny = n.y;
  327. nz = n.z;
  328. }
  329. float nxabs = (float)fabs(nx);
  330. float nyabs = (float)fabs(ny);
  331. float nzabs = (float)fabs(nz);
  332. bool flip = nx + ny + nz > 0;
  333. int axis = nxabs > nyabs && nxabs > nzabs ? 0 : nyabs > nxabs && nyabs > nzabs ? 1 : 2;
  334. int axis0 = axis == 0 ? (flip ? 2 : 1) : axis == 1 ? (flip ? 0 : 2) : (flip ? 1 : 0);
  335. int axis1 = axis == 0 ? (flip ? 1 : 2) : axis == 1 ? (flip ? 2 : 0) : (flip ? 0 : 1);
  336. int loops = 0;
  337. int i = -1;
  338. while (vi > 3 && loops++ < vi) {
  339. i = (i + 1) % vi;
  340. int i1 = (i + 1) % vi;
  341. int i2 = (i + 2) % vi;
  342. int vi0 = (va[i ] - _vind_off) * 3;
  343. int vi1 = (va[i1] - _vind_off) * 3;
  344. int vi2 = (va[i2] - _vind_off) * 3;
  345. float v0x = pos_temp.buffer[vi0 + axis0];
  346. float v0y = pos_temp.buffer[vi0 + axis1];
  347. float v1x = pos_temp.buffer[vi1 + axis0];
  348. float v1y = pos_temp.buffer[vi1 + axis1];
  349. float v2x = pos_temp.buffer[vi2 + axis0];
  350. float v2y = pos_temp.buffer[vi2 + axis1];
  351. float e0x = v0x - v1x; // Not an interior vertex
  352. float e0y = v0y - v1y;
  353. float e1x = v2x - v1x;
  354. float e1y = v2y - v1y;
  355. float cross = e0x * e1y - e0y * e1x;
  356. if (cross <= 0) {
  357. continue;
  358. }
  359. bool overlap = false; // Other vertex found inside this triangle
  360. for (int j = 0; j < vi - 3; ++j) {
  361. int j0 = (va[(i + 3 + j) % vi] - _vind_off) * 3;
  362. float px = pos_temp.buffer[j0 + axis0];
  363. float py = pos_temp.buffer[j0 + axis1];
  364. if (pnpoly(v0x, v0y, v1x, v1y, v2x, v2y, px, py)) {
  365. overlap = true;
  366. break;
  367. }
  368. }
  369. if (overlap) {
  370. continue;
  371. }
  372. i32_array_push(&pos_indices, va[i ]); // Found ear
  373. i32_array_push(&pos_indices, va[i1]);
  374. i32_array_push(&pos_indices, va[i2]);
  375. if (uv_temp.length > 0) {
  376. i32_array_push(&uv_indices, ua[i ]);
  377. i32_array_push(&uv_indices, ua[i1]);
  378. i32_array_push(&uv_indices, ua[i2]);
  379. }
  380. if (nor_temp.length > 0) {
  381. i32_array_push(&nor_indices, na[i ]);
  382. i32_array_push(&nor_indices, na[i1]);
  383. i32_array_push(&nor_indices, na[i2]);
  384. }
  385. for (int j = ((i + 1) % vi); j < vi - 1; ++j) { // Consume vertex
  386. va[j] = va[j + 1];
  387. ua[j] = ua[j + 1];
  388. na[j] = na[j + 1];
  389. }
  390. vi--;
  391. i--;
  392. loops = 0;
  393. }
  394. i32_array_push(&pos_indices, va[0]); // Last one
  395. i32_array_push(&pos_indices, va[1]);
  396. i32_array_push(&pos_indices, va[2]);
  397. if (uv_temp.length > 0) {
  398. i32_array_push(&uv_indices, ua[0]);
  399. i32_array_push(&uv_indices, ua[1]);
  400. i32_array_push(&uv_indices, ua[2]);
  401. }
  402. if (nor_temp.length > 0) {
  403. i32_array_push(&nor_indices, na[0]);
  404. i32_array_push(&nor_indices, na[1]);
  405. i32_array_push(&nor_indices, na[2]);
  406. }
  407. }
  408. }
  409. else if (c0 == split_code) {
  410. if (split_code == 'u') {
  411. part->pos += 5; // "u"semtl
  412. }
  413. part->pos++; // Space
  414. if (!udim) {
  415. reading_object = true;
  416. }
  417. part->name = string_copy(read_string());
  418. }
  419. next_line();
  420. }
  421. if (start_pos > 0) {
  422. if (split_code != 'u') {
  423. for (int i = 0; i < pos_indices.length; ++i) {
  424. pos_indices.buffer[i] -= vind_off;
  425. }
  426. for (int i = 0; i < uv_indices.length; ++i) {
  427. uv_indices.buffer[i] -= tind_off;
  428. }
  429. for (int i = 0; i < nor_indices.length; ++i) {
  430. nor_indices.buffer[i] -= nind_off;
  431. }
  432. }
  433. }
  434. else {
  435. if (split_code == 'u') {
  436. pos_first = &pos_temp;
  437. nor_first = &nor_temp;
  438. uv_first = &uv_temp;
  439. }
  440. }
  441. vind_off += (int)(pos_temp.length / 3); // Assumes separate vertex data per object
  442. tind_off += (int)(uv_temp.length / 2);
  443. nind_off += (int)(nor_temp.length / 3);
  444. // Pack positions to (-1, 1) range
  445. part->scale_pos = 0.0;
  446. for (int i = 0; i < pos_temp.length; ++i) {
  447. float f = (float)fabs(pos_temp.buffer[i]);
  448. if (part->scale_pos < f) {
  449. part->scale_pos = f;
  450. }
  451. }
  452. float inv = 32767 * (1 / part->scale_pos);
  453. part->posa = calloc(sizeof(i16_array_t), 1);
  454. part->posa->length = part->posa->capacity = pos_indices.length * 4;
  455. part->posa->buffer = malloc(part->posa->capacity * sizeof(int16_t));
  456. part->inda = calloc(sizeof(u32_array_t), 1);
  457. part->inda->length = part->inda->capacity = pos_indices.length;
  458. part->inda->buffer = malloc(part->inda->capacity * sizeof(uint32_t));
  459. part->vertex_count = pos_indices.length;
  460. part->index_count = pos_indices.length;
  461. int inda_length = pos_indices.length;
  462. for (int i = 0; i < pos_indices.length; ++i) {
  463. part->posa->buffer[i * 4 ] = (int)( pos_temp.buffer[pos_indices.buffer[i] * 3 ] * inv);
  464. part->posa->buffer[i * 4 + 1] = (int)(-pos_temp.buffer[pos_indices.buffer[i] * 3 + 2] * inv);
  465. part->posa->buffer[i * 4 + 2] = (int)( pos_temp.buffer[pos_indices.buffer[i] * 3 + 1] * inv);
  466. part->inda->buffer[i] = i;
  467. }
  468. if (nor_indices.length > 0) {
  469. part->nora = calloc(sizeof(i16_array_t), 1);
  470. part->nora->length = part->nora->capacity = nor_indices.length * 2;
  471. part->nora->buffer = malloc(part->nora->capacity * sizeof(int16_t));
  472. for (int i = 0; i < pos_indices.length; ++i) {
  473. part->nora->buffer[i * 2 ] = (int)( nor_temp.buffer[nor_indices.buffer[i] * 3 ] * 32767);
  474. part->nora->buffer[i * 2 + 1] = (int)(-nor_temp.buffer[nor_indices.buffer[i] * 3 + 2] * 32767);
  475. part->posa->buffer[i * 4 + 3] = (int)( nor_temp.buffer[nor_indices.buffer[i] * 3 + 1] * 32767);
  476. }
  477. }
  478. else {
  479. // Calc normals
  480. part->nora = calloc(sizeof(i16_array_t), 1);
  481. part->nora->length = part->nora->capacity = inda_length * 2;
  482. part->nora->buffer = malloc(part->nora->capacity * sizeof(int16_t));
  483. for (int i = 0; i < (int)(inda_length / 3); ++i) {
  484. int i1 = part->inda->buffer[i * 3 ];
  485. int i2 = part->inda->buffer[i * 3 + 1];
  486. int i3 = part->inda->buffer[i * 3 + 2];
  487. iron_vector4_t n = calc_normal(
  488. vec4_create(part->posa->buffer[i1 * 4], part->posa->buffer[i1 * 4 + 1], part->posa->buffer[i1 * 4 + 2], 1.0),
  489. vec4_create(part->posa->buffer[i2 * 4], part->posa->buffer[i2 * 4 + 1], part->posa->buffer[i2 * 4 + 2], 1.0),
  490. vec4_create(part->posa->buffer[i3 * 4], part->posa->buffer[i3 * 4 + 1], part->posa->buffer[i3 * 4 + 2], 1.0)
  491. );
  492. part->nora->buffer[i1 * 2 ] = (int)(n.x * 32767);
  493. part->nora->buffer[i1 * 2 + 1] = (int)(n.y * 32767);
  494. part->posa->buffer[i1 * 4 + 3] = (int)(n.z * 32767);
  495. part->nora->buffer[i2 * 2 ] = (int)(n.x * 32767);
  496. part->nora->buffer[i2 * 2 + 1] = (int)(n.y * 32767);
  497. part->posa->buffer[i2 * 4 + 3] = (int)(n.z * 32767);
  498. part->nora->buffer[i3 * 2 ] = (int)(n.x * 32767);
  499. part->nora->buffer[i3 * 2 + 1] = (int)(n.y * 32767);
  500. part->posa->buffer[i3 * 4 + 3] = (int)(n.z * 32767);
  501. }
  502. }
  503. if (uv_indices.length > 0) {
  504. if (udim) {
  505. // Find number of tiles
  506. int tiles_u = 1;
  507. int tiles_v = 1;
  508. for (int i = 0; i < (int)(uv_temp.length / 2); ++i) {
  509. while (uv_temp.buffer[i * 2 ] > tiles_u) tiles_u++;
  510. while (uv_temp.buffer[i * 2 + 1] > tiles_v) tiles_v++;
  511. }
  512. // Amount of indices pre tile
  513. uint32_t *num = (uint32_t *)malloc(tiles_u * tiles_v * sizeof(uint32_t));
  514. memset(num, 0, tiles_u * tiles_v * sizeof(uint32_t));
  515. for (int i = 0; i < (int)(inda_length / 3); ++i) {
  516. int tile = get_tile(part->inda->buffer[i * 3], part->inda->buffer[i * 3 + 1], part->inda->buffer[i * 3 + 2], &uv_indices, tiles_u);
  517. num[tile] += 3;
  518. }
  519. // Split indices per tile
  520. part->udims = any_array_create(tiles_u * tiles_v);
  521. part->udims_u = tiles_u;
  522. part->udims_v = tiles_v;
  523. for (int i = 0; i < tiles_u * tiles_v; ++i) {
  524. part->udims->buffer[i] = u32_array_create(num[i]);
  525. num[i] = 0;
  526. }
  527. for (int i = 0; i < (int)(inda_length / 3); ++i) {
  528. int i1 = part->inda->buffer[i * 3 ];
  529. int i2 = part->inda->buffer[i * 3 + 1];
  530. int i3 = part->inda->buffer[i * 3 + 2];
  531. int tile = get_tile(i1, i2, i3, &uv_indices, tiles_u);
  532. u32_array_t *a = part->udims->buffer[tile];
  533. a->buffer[num[tile]++] = i1;
  534. a->buffer[num[tile]++] = i2;
  535. a->buffer[num[tile]++] = i3;
  536. }
  537. // Normalize uvs to 0-1 range
  538. int16_t *uvtiles = (int16_t *)malloc(uv_temp.length * sizeof(int16_t));
  539. for (int i = 0; i < (int)(inda_length / 3); ++i) { // TODO: merge loops
  540. int i1 = part->inda->buffer[i * 3 ];
  541. int i2 = part->inda->buffer[i * 3 + 1];
  542. int i3 = part->inda->buffer[i * 3 + 2];
  543. int tile = get_tile(i1, i2, i3, &uv_indices, tiles_u);
  544. int tile_u = tile % tiles_u;
  545. int tile_v = (int)(tile / tiles_u);
  546. uvtiles[uv_indices.buffer[i1] * 2 ] = tile_u;
  547. uvtiles[uv_indices.buffer[i1] * 2 + 1] = tile_v;
  548. uvtiles[uv_indices.buffer[i2] * 2 ] = tile_u;
  549. uvtiles[uv_indices.buffer[i2] * 2 + 1] = tile_v;
  550. uvtiles[uv_indices.buffer[i3] * 2 ] = tile_u;
  551. uvtiles[uv_indices.buffer[i3] * 2 + 1] = tile_v;
  552. }
  553. for (int i = 0; i < uv_temp.length; ++i) {
  554. uv_temp.buffer[i] -= uvtiles[i];
  555. }
  556. free(uvtiles);
  557. free(num);
  558. }
  559. part->texa = calloc(sizeof(i16_array_t), 1);
  560. part->texa->length = part->texa->capacity = uv_indices.length * 2;
  561. part->texa->buffer = malloc(part->texa->capacity * sizeof(int16_t));
  562. for (int i = 0; i < uv_indices.length; ++i) {
  563. float uvx = uv_temp.buffer[uv_indices.buffer[i] * 2];
  564. if (uvx > 1.0) {
  565. uvx = uvx - (int)(uvx);
  566. }
  567. float uvy = uv_temp.buffer[uv_indices.buffer[i] * 2 + 1];
  568. if (uvy > 1.0) {
  569. uvy = uvy - (int)(uvy);
  570. }
  571. part->texa->buffer[i * 2 ] = (int)( uvx * 32767);
  572. part->texa->buffer[i * 2 + 1] = (int)((1.0 - uvy) * 32767);
  573. }
  574. }
  575. bytes = NULL;
  576. if (!part->has_next) {
  577. pos_first = nor_first = uv_first = NULL;
  578. array_free(&pos_temp);
  579. array_free(&uv_temp);
  580. array_free(&nor_temp);
  581. }
  582. array_free(&pos_indices);
  583. array_free(&uv_indices);
  584. array_free(&nor_indices);
  585. return part;
  586. }
  587. void obj_destroy(raw_mesh_t *part) {
  588. // if (part->udims != NULL) {
  589. // for (int i = 0; i < part->udims_u * part->udims_v; ++i) {
  590. // free(part->udims[i]);
  591. // }
  592. // free(part->udims);
  593. // }
  594. free(part->posa);
  595. free(part->nora);
  596. free(part->texa);
  597. free(part->inda);
  598. gc_free(part);
  599. }