objnurbs.h 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. /*
  2. * m3dconv/objnurbs.h
  3. *
  4. * Copyright (C) 2019 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * @brief simple 3D model to M3D converter OBJ (with NURBS) importer
  27. * https://gitlab.com/bztsrc/model3d
  28. *
  29. */
  30. typedef struct {
  31. int type;
  32. unsigned int num;
  33. uint32_t *data;
  34. } csmod_t;
  35. /**
  36. * Parse material file
  37. */
  38. void mtl_load(char *fn, m3d_t *m3d)
  39. {
  40. unsigned int siz, i, j, k, l;
  41. char *s, *e, *data, *path, *bn;
  42. float r,g,b,a;
  43. m3dm_t *m;
  44. storeinline = 0;
  45. data = (char*)readfile(fn, &siz);
  46. storeinline = doinline;
  47. if(data) {
  48. if(verbose > 2) printf(" Material library '%s'\n", fn);
  49. while(*data) {
  50. while(*data && (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')) data++;
  51. if(!*data) break;
  52. /* comments */
  53. if(*data == '#') { data = _m3d_findnl(data); continue; }
  54. /* material */
  55. if(!memcmp(data, "newmtl", 6)) {
  56. m = NULL;
  57. data = _m3d_findarg(data + 6);
  58. if(!*data || *data == '\r' || *data == '\n') goto skip;
  59. s = _m3d_safestr(data, 0);
  60. if(!s || !*s) goto skip;
  61. for(j = 0, i = -1U; j < m3d->nummaterial; j++)
  62. if(!strcmp(s, m3d->material[j].name)) { i = j; free(s); break; }
  63. if(i == -1U) {
  64. i = m3d->nummaterial++;
  65. m3d->material = (m3dm_t*)realloc(m3d->material, m3d->nummaterial * sizeof(m3dm_t));
  66. if(!m3d->material) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  67. m = &m3d->material[i];
  68. m->name = s;
  69. m->numprop = 0;
  70. m->prop = NULL;
  71. } else
  72. m = &m3d->material[i];
  73. }
  74. if(m) {
  75. k = i = 256;
  76. if(!memcmp(data, "map_", 4)) {
  77. k = m3dpf_map;
  78. data += 4;
  79. }
  80. for(j = 0; j < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); j++)
  81. if(!memcmp(data, m3d_propertytypes[j].key, strlen(m3d_propertytypes[j].key))) {
  82. i = m3d_propertytypes[j].id;
  83. if(k != m3dpf_map) k = m3d_propertytypes[j].format;
  84. break;
  85. }
  86. if(i != 256 && k != 256) {
  87. data = _m3d_findarg(data);
  88. if(!*data || *data == '\r' || *data == '\n') goto skip;
  89. i += (k == m3dpf_map && i < 128 ? 128 : 0);
  90. for(l = 0, j = -1U; l < m->numprop; l++)
  91. if(m->prop[l].type == i) { j = l; break; }
  92. if(j == -1U) {
  93. j = m->numprop++;
  94. m->prop = (m3dp_t*)realloc(m->prop, m->numprop * sizeof(m3dp_t));
  95. if(!m->prop) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  96. m->prop[j].type = i;
  97. }
  98. switch(k) {
  99. case m3dpf_color:
  100. r = g = b = a = 0.0f;
  101. data = _m3d_getfloat(data, &r);
  102. data = _m3d_getfloat(data, &g);
  103. data = _m3d_getfloat(data, &b);
  104. if(*data && *data != '\r' && *data != '\n')
  105. data = _m3d_getfloat(data, &a);
  106. else
  107. a = 1.0f;
  108. m->prop[j].value.color = ((uint8_t)(a*255) << 24L) |
  109. ((uint8_t)(b*255) << 16L) |
  110. ((uint8_t)(g*255) << 8L) |
  111. ((uint8_t)(r*255) << 0L);
  112. break;
  113. case m3dpf_uint8:
  114. case m3dpf_uint16:
  115. case m3dpf_uint32: data = _m3d_getint(data, &m->prop[j].value.num); break;
  116. case m3dpf_float: data = _m3d_getfloat(data, &m->prop[j].value.fnum); break;
  117. case m3dpf_map:
  118. s = e = _m3d_findnl(data);
  119. while(e > data && (e[-1] == ' ' || e[-1] == '\t' || e[-1] == '\r' || e[-1] == '\n')) e--;
  120. for(i = 0; s > data && s[-1] != ' ' && s[-1] != '/' && s[-1] != '\\'; s--)
  121. if(!i && *s == '.') { i = 1; *s = 0; }
  122. data = e;
  123. e = s;
  124. s = _m3d_safestr(s, 0);
  125. if(!s || !*s) goto skip;
  126. for(i = 0, l = -1U; i < m3d->numtexture; i++) {
  127. if(!strcmp(s, m3d->texture[i].name)) { l = i; free(s); break; }
  128. }
  129. if(l == -1U) {
  130. if(storeinline) {
  131. path = (char*)malloc(strlen(fn) + strlen(e) + 5);
  132. strcpy(path, fn);
  133. bn = strrchr(path, '/');
  134. if(!bn) bn = strrchr(path, '\\');
  135. if(!bn) bn = path; else bn++;
  136. strcpy(bn, e);
  137. bn += strlen(e);
  138. strcpy(bn, ".png");
  139. if(!readfile(path, &l)) {
  140. strcpy(bn, ".PNG");
  141. if(!readfile(path, &l)) {
  142. for(l = strlen(path)-1; l > 0 && path[l]!='/' && path[l]!='\\'; l--)
  143. if(path[l] >= 'A' && path[l] <= 'Z') path[l] += 'a'-'A';
  144. readfile(path, &l);
  145. }
  146. }
  147. if(l && verbose>1) printf(" Inlining '%s'\n", s);
  148. }
  149. l = m3d->numtexture++;
  150. m3d->texture = (m3dtx_t*)realloc(m3d->texture, m3d->numtexture * sizeof(m3dtx_t));
  151. if(!m3d->texture) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  152. m3d->texture[l].name = s;
  153. m3d->texture[l].w = m3d->texture[l].h = 0;
  154. m3d->texture[l].d = NULL;
  155. }
  156. m->prop[j].value.textureid = l;
  157. break;
  158. }
  159. }
  160. }
  161. skip: data = _m3d_findnl(data);
  162. }
  163. }
  164. }
  165. /**
  166. * Load a model and convert it's structures into a Model 3D in-memory format
  167. */
  168. m3d_t *obj_load(char *data, char *fn)
  169. {
  170. unsigned int i, j, sidx = 0, cidx = 0, numv = 0, numn = 0, nump = 0, numm = 0, numc, numpu, numpv, numsp, mi = -1U;
  171. unsigned int boneid = -1U, maxv = 0, maxn = 0, maxp = 0, maxuv = 0, maxl = 0;
  172. uint32_t cstype = 0, degu, degv, rangeu, rangev, csidx = 0, *sp = NULL, *ctrl = NULL, *cidxs = NULL, *sidxs = NULL;
  173. int idx;
  174. char *s, *an, *bn, *path, name[6];
  175. float r,g,b,a, ures, vres, maxlen, maxdist, maxangle, *paru = NULL, *parv = NULL;
  176. m3d_t *m3d;
  177. m3dv_t *v, *vertex = NULL, *normal = NULL, *param = NULL;
  178. m3dh_t *h;
  179. csmod_t *mod = NULL;
  180. m3d = (m3d_t*)malloc(sizeof(m3d_t));
  181. if(!m3d) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  182. memset(m3d, 0, sizeof(m3d_t));
  183. m3d->flags = M3D_FLG_FREESTR;
  184. /* add default position and orientation, may be needed by bones in group statements */
  185. m3d->numvertex = 2;
  186. m3d->vertex = (m3dv_t*)malloc(m3d->numvertex * sizeof(m3dv_t));
  187. if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  188. memset(m3d->vertex, 0, 2 * sizeof(m3dv_t));
  189. m3d->vertex[0].skinid = -1U;
  190. m3d->vertex[0].type = VT_WORLD;
  191. m3d->vertex[1].skinid = -2U;
  192. m3d->vertex[1].type = VT_QUATERN;
  193. while(*data) {
  194. while(*data && (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')) data++;
  195. if(!*data) break;
  196. /* comments */
  197. if(*data == '#') { data = _m3d_findnl(data); continue; }
  198. /* annotation label, not in the spec, but I needed it. This is the only statement I've added
  199. * "a (vertexid) (utf-8 string without control characters)"
  200. */
  201. if(data[0] == 'a' && data[1] == ' ') {
  202. data = _m3d_findarg(data + 1);
  203. if(!*data || *data == '\r' || *data == '\n') goto skip;
  204. data = _m3d_getint(data, (unsigned int*)&idx);
  205. if(idx > 0) idx--; else idx = numv - idx;
  206. data = _m3d_findarg(data);
  207. if(!*data || *data == '\r' || *data == '\n') goto skip;
  208. s = _m3d_safestr(data, 2);
  209. if(!s || !*s) goto skip;
  210. i = m3d->numlabel++;
  211. if(m3d->numlabel >= maxl) {
  212. maxl += 256;
  213. m3d->label = (m3dl_t*)realloc(m3d->label, maxl * sizeof(m3dl_t));
  214. if(!m3d->label) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  215. }
  216. m3d->label[i].name = NULL;
  217. m3d->label[i].lang = NULL;
  218. m3d->label[i].color = 0;
  219. m3d->label[i].vertexid = idx + m3d->numvertex;
  220. m3d->label[i].text = s;
  221. } else
  222. /* object name and groups */
  223. if(data[1] == ' ' && (data[0] == 'o' || data[0] == 'g')) {
  224. s = data;
  225. data = _m3d_findarg(data + 1);
  226. if(!*data || *data == '\r' || *data == '\n') goto skip;
  227. /* there can be several "o " lines, but we only use the first as model name */
  228. if(s[0] == 'o' && !m3d->name) m3d->name = _m3d_safestr(data, 2);
  229. /* create a bone for each group */
  230. boneid = -1U;
  231. an = _m3d_safestr(data, 0);
  232. if(an) {
  233. for(i = 0; i < m3d->numbone; i++)
  234. if(!strcmp(an, m3d->bone[i].name)) { boneid = i; break; }
  235. if(boneid == -1U) {
  236. boneid = m3d->numbone++;
  237. m3d->bone = (m3db_t*)realloc(m3d->bone, m3d->numbone * sizeof(m3db_t));
  238. if(!m3d->bone) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  239. memset(&m3d->bone[boneid], 0, sizeof(m3db_t));
  240. m3d->bone[boneid].parent = (M3D_INDEX)-1U;
  241. m3d->bone[boneid].name = an;
  242. m3d->bone[boneid].pos = 0;
  243. m3d->bone[boneid].ori = 1;
  244. } else
  245. free(an);
  246. }
  247. csidx = 0;
  248. } else
  249. /* material library */
  250. if(!memcmp(data, "mtllib", 6)) {
  251. data = _m3d_findarg(data + 6);
  252. if(!*data || *data == '\r' || *data == '\n') goto skip;
  253. s = bn = _m3d_findnl(data);
  254. while(bn > data && (bn[-1] == ' ' || bn[-1] == '\t' || bn[-1] == '\r' || bn[-1] == '\n')) bn--;
  255. while(s > data && s[-1] != '/' && s[-1] != '\\') s--;
  256. *bn++ = 0;
  257. data = bn;
  258. path = (char*)malloc(strlen(fn) + strlen(s) + 5);
  259. if(!path) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  260. strcpy(path, fn);
  261. bn = strrchr(path, '/');
  262. if(!bn) bn = strrchr(path, '\\');
  263. if(!bn) bn = path; else bn++;
  264. strcpy(bn, s);
  265. mtl_load(path, m3d);
  266. free(path);
  267. continue;
  268. } else
  269. /* use material */
  270. if(!memcmp(data, "usemtl", 6)) {
  271. data = _m3d_findarg(data + 6);
  272. if(!*data || *data == '\r' || *data == '\n') goto skip;
  273. mi = (M3D_INDEX)-1U;
  274. if(*data && *data != '\r' && *data != '\n') {
  275. s = _m3d_safestr(data, 0);
  276. if(!s || !*s) goto skip;
  277. for(i = 0; i < m3d->nummaterial; i++)
  278. if(!strcmp(s, m3d->material[i].name)) {
  279. mi = (M3D_INDEX)i;
  280. break;
  281. }
  282. free(s);
  283. }
  284. } else
  285. /* vertex lists */
  286. if(data[0] == 'v' && (data[1] == ' ' || (data[2] == ' ' && (data[1] == 'n' || data[1] == 'p')))) {
  287. s = data + 1;
  288. data = _m3d_findarg(data);
  289. if(!*data || *data == '\r' || *data == '\n') goto skip;
  290. v = NULL;
  291. switch(*s) {
  292. case 'n':
  293. i = numn++;
  294. if(numn >= maxn) {
  295. maxn += 1024;
  296. normal = (m3dv_t*)realloc(normal, maxn * sizeof(m3dv_t));
  297. if(!normal) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  298. }
  299. v = &normal[i];
  300. break;
  301. case 'p':
  302. i = nump++;
  303. if(nump >= maxp) {
  304. maxp += 1024;
  305. param = (m3dv_t*)realloc(param, maxp * sizeof(m3dv_t));
  306. if(!param) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  307. }
  308. v = &param[i];
  309. break;
  310. default:
  311. i = numv++;
  312. if(numv >= maxv) {
  313. maxv += 1024;
  314. vertex = (m3dv_t*)realloc(vertex, maxv * sizeof(m3dv_t));
  315. if(!vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  316. }
  317. v = &vertex[i];
  318. break;
  319. }
  320. if(!v) goto skip;
  321. memset(v, 0, sizeof(m3dv_t));
  322. if(*s == 'n') v->type = VT_NORMAL;
  323. v->skinid = (M3D_INDEX)-1U;
  324. v->w = (M3D_FLOAT)1.0;
  325. data = _m3d_getfloat(data, &v->x);
  326. if(*data && *data != '\r' && *data != '\n') {
  327. data = _m3d_getfloat(data, &v->y);
  328. if(*data && *data != '\r' && *data != '\n') {
  329. data = _m3d_getfloat(data, &v->z);
  330. if((*s == ' ' || *s == 'p') && *data && *data != '\r' && *data != '\n') {
  331. data = _m3d_getfloat(data, &v->w);
  332. if(*s == ' ' && *data && *data != '\r' && *data != '\n') {
  333. r = g = b = a = 0.0f;
  334. data = _m3d_getfloat(data, &r);
  335. data = _m3d_getfloat(data, &g);
  336. if(!*data || *data == '\r' || *data == '\n') {
  337. a = 1.0f; b = g; g = r; r = v->w;
  338. v->w = (M3D_FLOAT)1.0;
  339. } else {
  340. data = _m3d_getfloat(data, &b);
  341. if(*data && *data != '\r' && *data != '\n')
  342. data = _m3d_getfloat(data, &a);
  343. else
  344. a = 1.0f;
  345. }
  346. v->color = ((uint8_t)(a*255) << 24L) |
  347. ((uint8_t)(b*255) << 16L) |
  348. ((uint8_t)(g*255) << 8L) |
  349. ((uint8_t)(r*255) << 0L);
  350. }
  351. }
  352. }
  353. }
  354. } else
  355. /* texture map lists */
  356. if(data[0] == 'v' && data[1] == 't' && data[2] == ' ') {
  357. data = _m3d_findarg(data + 2);
  358. if(!*data || *data == '\r' || *data == '\n') goto skip;
  359. i = m3d->numtmap++;
  360. if(m3d->numtmap >= maxuv) {
  361. maxuv += 1024;
  362. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  363. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  364. }
  365. m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
  366. data = _m3d_getfloat(data, &m3d->tmap[i].u);
  367. if(*data && *data != '\r' && *data != '\n')
  368. data = _m3d_getfloat(data, &m3d->tmap[i].v);
  369. } else
  370. /* mesh face */
  371. if(data[0] == 'f' && data[1] == ' ') {
  372. data = _m3d_findarg(data + 1);
  373. if(!*data || *data == '\r' || *data == '\n') goto skip;
  374. bn = _m3d_findnl(data);
  375. i = 3 * ((int)(bn - data) / 2) * sizeof(uint32_t);
  376. ctrl = (uint32_t*)realloc(ctrl, i);
  377. if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  378. memset(ctrl, 255, i);
  379. /* get the polygon */
  380. for(numc = 0; *data && *data != '\r' && *data != '\n'; numc += 3) {
  381. data = _m3d_getint(data, (unsigned int*)&idx);
  382. if(idx > 0) idx--; else idx = numv - idx;
  383. ctrl[numc] = idx + m3d->numvertex;
  384. if(*data == '/') {
  385. data++;
  386. if(*data != '/') {
  387. data = _m3d_getint(data, (unsigned int*)&idx);
  388. if(idx > 0) idx--; else idx = m3d->numtmap - idx;
  389. ctrl[numc + 1] = idx;
  390. }
  391. if(*data == '/') {
  392. data = _m3d_getint(data + 1, (unsigned int*)&idx);
  393. if(idx > 0) idx--; else idx = numn - idx;
  394. ctrl[numc + 2] = idx + numv + m3d->numvertex;
  395. }
  396. }
  397. data = _m3d_findarg(data);
  398. }
  399. if(numc < 9) goto skip;
  400. /* triangulate, assuming CCW */
  401. numm = (numc / 3) - 2;
  402. i = m3d->numface; m3d->numface += numm;
  403. m3d->face = (m3df_t*)realloc(m3d->face, m3d->numface * sizeof(m3df_t));
  404. if(!m3d->face) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  405. memset(&m3d->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */
  406. for(j = 6; j < numc; j += 3, i++) {
  407. m3d->face[i].materialid = mi;
  408. m3d->face[i].vertex[0] = (M3D_INDEX)ctrl[0];
  409. m3d->face[i].texcoord[0] = (M3D_INDEX)ctrl[1];
  410. m3d->face[i].normal[0] = (M3D_INDEX)ctrl[2];
  411. m3d->face[i].vertex[1] = (M3D_INDEX)ctrl[j - 3];
  412. m3d->face[i].texcoord[1] = (M3D_INDEX)ctrl[j - 2];
  413. m3d->face[i].normal[1] = (M3D_INDEX)ctrl[j - 1];
  414. m3d->face[i].vertex[2] = (M3D_INDEX)ctrl[j + 0];
  415. m3d->face[i].texcoord[2] = (M3D_INDEX)ctrl[j + 1];
  416. m3d->face[i].normal[2] = (M3D_INDEX)ctrl[j + 2];
  417. }
  418. } else
  419. if(!domesh) {
  420. /* curves and surfaces */
  421. if(!memcmp(data, "cstype", 6)) {
  422. data = _m3d_findarg(data + 6);
  423. if(!memcmp(data, "rat", 3)) data = _m3d_findarg(data);
  424. if(!*data || *data == '\r' || *data == '\n') goto skip;
  425. cstype = 0;
  426. if(!memcmp(data, "bezier", 6)) cstype = 1; else
  427. if(!memcmp(data, "bspline", 7)) cstype = 4; else {
  428. if(verbose > 1) {
  429. for(s = data; *s && *s != '\r' && *s != '\n'; s++);
  430. *s = 0;
  431. printf(" Unknown curve / surface type '%s'\n", data);
  432. data = s + 1;
  433. }
  434. while(*data && memcmp(data, "end", 3)) data++;
  435. goto skip;
  436. }
  437. degu = degv = numc = numpv = numpu = numsp = numm = 0;
  438. rangeu = rangev = -1U;
  439. ures = vres = maxlen = maxdist = maxangle = 1.0f;
  440. } else
  441. if(cstype) {
  442. /* arguments for curves / surfaces */
  443. if(!memcmp(data, "deg", 3)) {
  444. data = _m3d_findarg(data + 3);
  445. if(!*data || *data == '\r' || *data == '\n') goto skip;
  446. data = _m3d_getint(data, &degu);
  447. if(*data && *data != '\r' && *data != '\n')
  448. data = _m3d_getint(data, &degv);
  449. else
  450. degv = degu;
  451. } else
  452. if((data[0] == 'c' && data[1] == 's') && !memcmp(data + 1, "tech", 4)) {
  453. data = _m3d_findarg(data + 5);
  454. if(!*data || *data == '\r' || *data == '\n') goto skip;
  455. if(!memcmp(data, "cparm", 5)) {
  456. s = data + 5;
  457. data = _m3d_findarg(data + 5);
  458. if(!*data || *data == '\r' || *data == '\n') goto skip;
  459. data = _m3d_getfloat(data, &ures);
  460. if(*s == 'b' && *data && *data != '\r' && *data != '\n')
  461. data = _m3d_getfloat(data, &vres);
  462. else
  463. vres = ures;
  464. } else
  465. if(!memcmp(data, "cspace", 6)) {
  466. data = _m3d_findarg(data + 6);
  467. if(!*data || *data == '\r' || *data == '\n') goto skip;
  468. data = _m3d_getfloat(data, &maxlen);
  469. } else
  470. if(!memcmp(data, "curv", 4)) {
  471. data = _m3d_findarg(data + 4);
  472. if(!*data || *data == '\r' || *data == '\n') goto skip;
  473. data = _m3d_getfloat(data, &maxdist);
  474. if(*data && *data != '\r' && *data != '\n')
  475. data = _m3d_getfloat(data, &maxangle);
  476. }
  477. } else
  478. if(!memcmp(data, "parm", 4)) {
  479. data = _m3d_findarg(data + 4);
  480. if(!*data || *data == '\r' || *data == '\n') goto skip;
  481. bn = _m3d_findnl(data);
  482. s = data;
  483. data = _m3d_findarg(data);
  484. if(!*data || *data == '\r' || *data == '\n') goto skip;
  485. if(*s != 'v') {
  486. paru = (float*)realloc(paru, ((int)(bn - data) / 2) * sizeof(float));
  487. if(!paru) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  488. for(numpu = 0; *data && *data != '\r' && *data != '\n'; numpu++)
  489. data = _m3d_getfloat(data, &paru[numpu]);
  490. } else {
  491. parv = (float*)realloc(parv, ((int)(bn - data) / 2) * sizeof(float));
  492. if(!parv) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  493. for(numpv = 0; *data && *data != '\r' && *data != '\n'; numpv++)
  494. data = _m3d_getfloat(data, &parv[numpv]);
  495. }
  496. } else
  497. if(!memcmp(data, "sp", 2)) {
  498. data = _m3d_findarg(data + 2);
  499. bn = _m3d_findnl(data);
  500. sp = (uint32_t*)realloc(sp, ((int)(bn - data) / 2) * sizeof(uint32_t));
  501. if(!sp) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  502. for(numsp = 0; *data && *data != '\r' && *data != '\n'; numsp++) {
  503. data = _m3d_getint(data, (unsigned int*)&idx);
  504. if(idx > 0) idx--; else idx = nump - idx;
  505. sp[numsp] = idx + numv + numn;
  506. data = _m3d_findarg(data);
  507. }
  508. } else
  509. if(!memcmp(data, "trim", 4) || !memcmp(data, "hole", 4) || !memcmp(data, "scrv", 4)) {
  510. i = numm++;
  511. mod = (csmod_t*)realloc(mod, numm * sizeof(uint32_t));
  512. if(!mod) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  513. switch(*data) {
  514. case 't': mod[i].type = m3dc_trim; break;
  515. case 'h': mod[i].type = m3dc_hole; break;
  516. case 's': mod[i].type = m3dc_scrv; break;
  517. }
  518. mod[i].num = 0;
  519. s = data;
  520. data = _m3d_findarg(data + 4);
  521. bn = _m3d_findnl(data);
  522. mod[i].data = (uint32_t*)malloc(((int)(bn - data) / 6) * 2 * sizeof(uint32_t));
  523. if(!mod[i].data) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  524. for(mod[i].num = 0; *data && *data != '\r' && *data != '\n';) {
  525. j = m3d->numtmap++;
  526. if(m3d->numtmap >= maxuv) {
  527. maxuv += 1024;
  528. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  529. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  530. }
  531. m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
  532. data = _m3d_getfloat(data, &m3d->tmap[j].u);
  533. if(*data && *data != '\r' && *data != '\n') {
  534. data = _m3d_getfloat(data, &m3d->tmap[j].v);
  535. mod[i].data[mod[i].num++] = j;
  536. if(*data && *data != '\r' && *data != '\n' && !cidxs) {
  537. data = _m3d_getint(data, (unsigned int*)&idx);
  538. if(idx > 0) idx--; else idx = cidx - idx;
  539. mod[i].data[mod[i].num++] = cidxs[idx];
  540. data = _m3d_findarg(data);
  541. }
  542. }
  543. }
  544. } else
  545. /* control points */
  546. if(!memcmp(data, "curv2", 5)) {
  547. cstype++;
  548. data = _m3d_findarg(data + 5);
  549. bn = _m3d_findnl(data);
  550. ctrl = (uint32_t*)realloc(ctrl, ((int)(bn - data) / 2) * sizeof(uint32_t));
  551. if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  552. for(numc = 0; *data && *data != '\r' && *data != '\n'; numc++) {
  553. data = _m3d_getint(data, (unsigned int*)&idx);
  554. if(idx > 0) idx--; else idx = nump - idx;
  555. ctrl[numc] = idx + numv + numn + m3d->numvertex;
  556. data = _m3d_findarg(data);
  557. }
  558. } else
  559. if(!memcmp(data, "curv", 4)) {
  560. data = _m3d_findarg(data + 4);
  561. i = m3d->numtmap++;
  562. if(m3d->numtmap >= maxuv) {
  563. maxuv += 1024;
  564. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  565. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  566. }
  567. m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
  568. data = _m3d_getfloat(data, &m3d->tmap[i].u);
  569. if(*data && *data != '\r' && *data != '\n')
  570. data = _m3d_getfloat(data, &m3d->tmap[i].v);
  571. rangeu = i;
  572. bn = _m3d_findnl(data);
  573. ctrl = (uint32_t*)realloc(ctrl, ((int)(bn - data) / 2) * sizeof(uint32_t));
  574. if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  575. for(numc = 0; *data && *data != '\r' && *data != '\n'; numc++) {
  576. data = _m3d_getint(data, (unsigned int*)&idx);
  577. if(idx > 0) idx--; else idx = numv - idx;
  578. ctrl[numc] = idx;
  579. data = _m3d_findarg(data);
  580. }
  581. } else
  582. if(!memcmp(data, "surf", 4)) {
  583. cstype += 2;
  584. data = _m3d_findarg(data + 4);
  585. i = m3d->numtmap++;
  586. if(m3d->numtmap >= maxuv) {
  587. maxuv += 1024;
  588. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  589. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  590. }
  591. m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
  592. data = _m3d_getfloat(data, &m3d->tmap[i].u);
  593. if(*data && *data != '\r' && *data != '\n')
  594. data = _m3d_getfloat(data, &m3d->tmap[i].v);
  595. rangeu = i;
  596. i = m3d->numtmap++;
  597. if(m3d->numtmap >= maxuv) {
  598. maxuv += 1024;
  599. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  600. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  601. }
  602. m3d->tmap[i].u = m3d->tmap[i].v = (M3D_FLOAT)0.0;
  603. data = _m3d_getfloat(data, &m3d->tmap[i].u);
  604. if(*data && *data != '\r' && *data != '\n')
  605. data = _m3d_getfloat(data, &m3d->tmap[i].v);
  606. rangev = i;
  607. bn = _m3d_findnl(data);
  608. ctrl = (uint32_t*)realloc(ctrl, 3 * ((int)(bn - data) / 2) * sizeof(uint32_t));
  609. if(!ctrl) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  610. for(numc = 0; *data && *data != '\r' && *data != '\n';) {
  611. data = _m3d_getint(data, (unsigned int*)&idx);
  612. if(idx > 0) idx--; else idx = numv - idx;
  613. ctrl[numc++] = idx + m3d->numvertex;
  614. if(*data == '/') {
  615. data++;
  616. if(*data != '/') {
  617. data = _m3d_getint(data, (unsigned int*)&idx);
  618. if(idx > 0) idx--; else idx = m3d->numtmap - idx;
  619. ctrl[numc++] = idx;
  620. cstype |= 0x40;
  621. }
  622. if(*data == '/') {
  623. data = _m3d_getint(data + 1, (unsigned int*)&idx);
  624. if(idx > 0) idx--; else idx = numn - idx;
  625. ctrl[numc++] = idx + numv + m3d->numvertex;
  626. cstype |= 0x80;
  627. }
  628. }
  629. data = _m3d_findarg(data);
  630. }
  631. } else
  632. /* on block end, convert everything into M3D shape commands */
  633. if(!memcmp(data, "end", 3)) {
  634. if(numc && degu) {
  635. /* add a new shape if we must */
  636. if(!csidx) {
  637. i = m3d->numshape++;
  638. m3d->shape = (m3dh_t*)realloc(m3d->shape, m3d->numshape * sizeof(m3dh_t));
  639. if(!m3d->shape) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  640. h = &m3d->shape[i];
  641. h->numcmd = 0;
  642. h->cmd = NULL;
  643. h->group = boneid;
  644. sprintf(name, "s%04X", i);
  645. h->name = _m3d_safestr((char*)&name, 0);
  646. }
  647. /* count how many commands we need */
  648. j = 1 + numm;
  649. if(ures != 1.0f || vres != 1.0f) j++;
  650. if(maxlen != 1.0f) j++;
  651. if(maxdist != 1.0f || maxangle != 1.0f) j++;
  652. if(degu || degv) j++;
  653. if(rangeu != -1U || rangev != -1U) j++;
  654. if(numpu) j++;
  655. if(numpv) j++;
  656. i = h->numcmd; h->numcmd += j;
  657. /* allocate commands */
  658. h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
  659. if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  660. /* add commands */
  661. if(ures != 1.0f || vres != 1.0f) {
  662. if(ures == vres) {
  663. h->cmd[i].type = m3dc_div;
  664. h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
  665. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  666. memcpy(&h->cmd[i].arg[0], &ures, sizeof(uint32_t));
  667. } else {
  668. h->cmd[i].type = m3dc_sub;
  669. h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
  670. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  671. memcpy(&h->cmd[i].arg[0], &ures, sizeof(uint32_t));
  672. memcpy(&h->cmd[i].arg[1], &vres, sizeof(uint32_t));
  673. }
  674. i++;
  675. }
  676. if(maxlen != 1.0f) {
  677. h->cmd[i].type = m3dc_len;
  678. h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
  679. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  680. memcpy(&h->cmd[i].arg[0], &maxlen, sizeof(uint32_t));
  681. i++;
  682. }
  683. if(maxdist != 1.0f || maxangle != 1.0f) {
  684. h->cmd[i].type = m3dc_dist;
  685. h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
  686. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  687. memcpy(&h->cmd[i].arg[0], &maxdist, sizeof(uint32_t));
  688. memcpy(&h->cmd[i].arg[1], &maxangle, sizeof(uint32_t));
  689. i++;
  690. }
  691. if(degu || degv) {
  692. if(degu == degv) {
  693. h->cmd[i].type = m3dc_degu;
  694. h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
  695. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  696. h->cmd[i].arg[0] = degu;
  697. } else {
  698. h->cmd[i].type = m3dc_deg;
  699. h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
  700. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  701. h->cmd[i].arg[0] = degu;
  702. h->cmd[i].arg[1] = degv;
  703. }
  704. i++;
  705. }
  706. if(rangeu != -1U || rangev != -1U) {
  707. if(rangev == -1U) {
  708. h->cmd[i].type = m3dc_rangeu;
  709. h->cmd[i].arg = (uint32_t*)malloc(1 * sizeof(uint32_t));
  710. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  711. h->cmd[i].arg[0] = rangeu;
  712. } else {
  713. h->cmd[i].type = m3dc_range;
  714. h->cmd[i].arg = (uint32_t*)malloc(2 * sizeof(uint32_t));
  715. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  716. h->cmd[i].arg[0] = rangeu;
  717. h->cmd[i].arg[1] = rangev;
  718. }
  719. i++;
  720. }
  721. if(numpu) {
  722. h->cmd[i].type = m3dc_paru;
  723. h->cmd[i].arg = (uint32_t*)malloc((numpu + 1) * sizeof(uint32_t));
  724. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  725. h->cmd[i].arg[0] = numpu;
  726. memcpy(&h->cmd[i].arg[1], &paru, numpu * sizeof(uint32_t));
  727. i++;
  728. }
  729. if(numpv) {
  730. h->cmd[i].type = m3dc_parv;
  731. h->cmd[i].arg = (uint32_t*)malloc((numpv + 1) * sizeof(uint32_t));
  732. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  733. h->cmd[i].arg[0] = numpv;
  734. memcpy(&h->cmd[i].arg[1], &parv, numpv * sizeof(uint32_t));
  735. i++;
  736. }
  737. for(j = 0; j < numm; j++) {
  738. h->cmd[i].type = mod[j].type;
  739. h->cmd[i].arg = (uint32_t*)malloc((mod[j].num + 1) * sizeof(uint32_t));
  740. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  741. h->cmd[i].arg[0] = mod[j].num;
  742. memcpy(&h->cmd[i].arg[1], &mod[j].data, mod[j].num * sizeof(uint32_t));
  743. free(mod[j].data);
  744. i++;
  745. }
  746. j = (cstype >> 6) & 3;
  747. if((cstype & 0x3F) == 3 || (cstype & 0x3F) == 6) {
  748. sidxs = (uint32_t*)realloc(sidxs, (sidx+1) * sizeof(uint32_t));
  749. sidxs[sidx] = csidx;
  750. } else {
  751. cidxs = (uint32_t*)realloc(cidxs, (cidx+1) * sizeof(uint32_t));
  752. cidxs[cidx] = csidx;
  753. }
  754. switch(cstype & 0x3F) {
  755. case 1: j = m3dc_bez1; cidx++; break;
  756. case 2: j = m3dc_bez2; cidx++; break;
  757. case 3: j += m3dc_bez; sidx++; break;
  758. case 4: j = m3dc_bsp1; cidx++; break;
  759. case 5: j = m3dc_bsp2; cidx++; break;
  760. case 6: j += m3dc_nurbs; sidx++; break;
  761. }
  762. h->cmd[i].type = j;
  763. h->cmd[i].arg = (uint32_t*)malloc((numc + 1) * sizeof(uint32_t));
  764. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  765. h->cmd[i].arg[0] = (cstype & 0xC0) == 0xC0 ? numc / 3 : (cstype & 0xC0 ? numc / 2 : numc);
  766. memcpy(&h->cmd[i].arg[1], &ctrl, numc * sizeof(uint32_t));
  767. csidx++;
  768. }
  769. cstype = 0;
  770. }
  771. } else
  772. if(data[0] == 'l' && data[1] == ' ') {
  773. data = _m3d_findarg(data + 1);
  774. if(!*data || *data == '\r' || *data == '\n') goto skip;
  775. /* add a new shape if we must */
  776. if(!csidx) {
  777. i = m3d->numshape++;
  778. m3d->shape = (m3dh_t*)realloc(m3d->shape, m3d->numshape * sizeof(m3dh_t));
  779. if(!m3d->shape) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  780. h = &m3d->shape[i];
  781. h->numcmd = 0;
  782. h->cmd = NULL;
  783. h->group = boneid;
  784. sprintf(name, "s%04X", i);
  785. h->name = _m3d_safestr((char*)&name, 0);
  786. }
  787. i = h->numcmd++;
  788. h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
  789. if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  790. bn = _m3d_findnl(data);
  791. h->cmd[i].arg = (uint32_t*)malloc((((int)(bn - data) / 2) + 1) * sizeof(uint32_t));
  792. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  793. h->cmd[i].type = m3dc_line;
  794. for(j = 0; *data && *data != '\r' && *data != '\n'; j++) {
  795. data = _m3d_getint(data, (unsigned int*)&idx);
  796. if(idx > 0) idx--; else idx = numv - idx;
  797. h->cmd[i].arg[j + 1] = idx;
  798. data = _m3d_findarg(data);
  799. }
  800. h->cmd[i].arg[0] = j;
  801. csidx++;
  802. } else
  803. if(!memcmp(data, "con", 3) && h) {
  804. data = _m3d_findarg(data + 3);
  805. if(!*data || *data == '\r' || *data == '\n' || !cidxs || !sidxs) goto skip;
  806. /* allocate command and its arguments */
  807. i = h->numcmd++;
  808. h->cmd = (m3dc_t*)realloc(h->cmd, h->numcmd * sizeof(m3dc_t));
  809. if(!h->cmd) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  810. h->cmd[i].arg = (uint32_t*)malloc(6 * sizeof(uint32_t));
  811. if(!h->cmd[i].arg) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  812. h->cmd[i].type = m3dc_conn;
  813. /* get arguments */
  814. data = _m3d_getint(data, (unsigned int*)&idx);
  815. if(idx > 0) idx--; else idx = sidx - idx;
  816. h->cmd[i].arg[0] = sidxs[idx];
  817. data = _m3d_findarg(data);
  818. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  819. j = m3d->numtmap++;
  820. if(m3d->numtmap >= maxuv) {
  821. maxuv += 1024;
  822. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  823. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  824. }
  825. m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
  826. data = _m3d_getfloat(data, &m3d->tmap[j].u);
  827. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  828. data = _m3d_getfloat(data, &m3d->tmap[j].v);
  829. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  830. h->cmd[i].arg[1] = j;
  831. data = _m3d_getint(data, (unsigned int*)&idx);
  832. if(idx > 0) idx--; else idx = cidx - idx;
  833. h->cmd[i].arg[2] = cidxs[idx];
  834. data = _m3d_findarg(data);
  835. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  836. data = _m3d_getint(data, (unsigned int*)&idx);
  837. if(idx > 0) idx--; else idx = sidx - idx;
  838. h->cmd[i].arg[3] = sidxs[idx];
  839. data = _m3d_findarg(data);
  840. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  841. j = m3d->numtmap++;
  842. if(m3d->numtmap >= maxuv) {
  843. maxuv += 1024;
  844. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, maxuv * sizeof(m3dti_t));
  845. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  846. }
  847. m3d->tmap[j].u = m3d->tmap[j].v = (M3D_FLOAT)0.0;
  848. data = _m3d_getfloat(data, &m3d->tmap[j].u);
  849. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  850. data = _m3d_getfloat(data, &m3d->tmap[j].v);
  851. if(!*data || *data == '\r' || *data == '\n') { free(h->cmd[i].arg); h->numcmd--; goto skip; }
  852. h->cmd[i].arg[4] = j;
  853. data = _m3d_getint(data, (unsigned int*)&idx);
  854. if(idx > 0) idx--; else idx = cidx - idx;
  855. h->cmd[i].arg[5] = cidxs[idx];
  856. }
  857. }
  858. skip: data = _m3d_findnl(data);
  859. }
  860. i = numv + numn + nump;
  861. if(i) {
  862. m3d->vertex = (m3dv_t*)realloc(m3d->vertex, (m3d->numvertex + i) * sizeof(m3dv_t));
  863. if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  864. if(numv) memcpy(&m3d->vertex[m3d->numvertex], vertex, numv * sizeof(m3dv_t));
  865. if(numn) memcpy(&m3d->vertex[m3d->numvertex + numv], normal, numn * sizeof(m3dv_t));
  866. if(nump) memcpy(&m3d->vertex[m3d->numvertex + numv + numn], param, nump * sizeof(m3dv_t));
  867. m3d->numvertex += i;
  868. }
  869. if(m3d->numtmap) {
  870. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, m3d->numtmap * sizeof(m3dti_t));
  871. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  872. }
  873. if(m3d->numlabel) {
  874. m3d->label = (m3dl_t*)realloc(m3d->label, m3d->numlabel * sizeof(m3dl_t));
  875. if(!m3d->label) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  876. }
  877. if(vertex) free(vertex);
  878. if(normal) free(normal);
  879. if(param) free(param);
  880. if(cidxs) free(cidxs);
  881. if(sidxs) free(sidxs);
  882. if(ctrl) free(ctrl);
  883. if(paru) free(paru);
  884. if(parv) free(parv);
  885. if(mod) free(mod);
  886. if(sp) free(sp);
  887. return m3d;
  888. }