pmx.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*
  2. * m3dconv/pmx.h
  3. *
  4. * Copyright (C) 2023 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 Polygon Model eXtended importer
  27. * https://gitlab.com/bztsrc/model3d
  28. *
  29. */
  30. static int te = 0, vc = 0, vs = 1, ts = 1, ms = 1, bs = 1, as = 1, rs = 1;
  31. /**
  32. * Read an index from PMX
  33. */
  34. int pmx_idx(uint8_t *data, int type)
  35. {
  36. switch(type) {
  37. case 1: return data[0] == 0xff ? -1 : data[0];
  38. case 2: return data[0] == 0xff && data[1] == 0xff ? -1 : data[0] | (data[1] << 8);
  39. case 4: return data[0] == 0xff && data[1] == 0xff && data[2] == 0xff && data[3] == 0xff ? -1 :
  40. data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
  41. }
  42. return -1;
  43. }
  44. /**
  45. * Convert a PMX string into a zero terminated UTF-8 C string
  46. */
  47. void pmx_str(uint8_t *data, int n, char *tmp)
  48. {
  49. uint16_t u;
  50. int i, l = 0;
  51. tmp[0] = 0;
  52. if(te) {
  53. for(i = l = 0; i < n && l < 1023; i++) {
  54. if(data[i] == '\r' || (data[i] == '\n' && l && tmp[l-1] == '\n')) continue;
  55. tmp[l++] = data[i];
  56. }
  57. } else {
  58. for(i = l = 0; i < n && l < 1020; i++) {
  59. u = data[i*2] | (data[i*2+1] << 8);
  60. if(u == '\r' || (u == '\n' && l && tmp[l-1] == '\n')) continue;
  61. if(u < 0x80) { tmp[l++] = u; } else
  62. if(u < 0x800) { tmp[l++] = ((u>>6)&0x1F)|0xC0; tmp[l++] = (u&0x3F)|0x80; }
  63. else { tmp[l++] = ((u>>12)&0x0F)|0xE0; tmp[l++] = ((u>>6)&0x3F)|0x80; tmp[l++] = (u&0x3F)|0x80; }
  64. }
  65. }
  66. tmp[l] = 0;
  67. }
  68. /**
  69. * Load a model and convert it's structures into a Model 3D in-memory format
  70. */
  71. m3d_t *pmx_load(unsigned char *data, unsigned int size)
  72. {
  73. uint8_t *end = data + size, *sav;
  74. m3d_t *m3d;
  75. m3dm_t *m;
  76. m3dv_t *v;
  77. uint32_t siz;
  78. int i, j, k, l, n, o, idx, nv = 0, nf = 0, nt = 0, nm = 0, nb = 0;
  79. float ver, r, g, b, a;
  80. char tmp[1024], *s, *e;
  81. m3d = (m3d_t*)malloc(sizeof(m3d_t));
  82. if(!m3d) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  83. memset(m3d, 0, sizeof(m3d_t));
  84. m3d->flags = M3D_FLG_FREESTR;
  85. /* add default position and orientation, may be needed by bones in group statements */
  86. m3d->numvertex = 2;
  87. m3d->vertex = (m3dv_t*)malloc(m3d->numvertex * sizeof(m3dv_t));
  88. if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  89. memset(m3d->vertex, 0, 2 * sizeof(m3dv_t));
  90. m3d->vertex[0].skinid = -1U;
  91. m3d->vertex[0].type = VT_WORLD;
  92. m3d->vertex[1].skinid = -2U;
  93. m3d->vertex[1].type = VT_QUATERN;
  94. /* header */
  95. memcpy(&ver, data + 4, 4); data += 8;
  96. n = (int)(uint32_t)*data++;
  97. if(n > 0) te = data[0]; /* text encoding, 0-UTF16LE, 1-UTF8 */
  98. if(n > 1) vc = data[1]; /* additional vertex vec4 count */
  99. if(n > 2) vs = data[2]; /* vertex index size */
  100. if(n > 3) ts = data[3]; /* texture index size */
  101. if(n > 4) ms = data[4]; /* material index size */
  102. if(n > 5) bs = data[5]; /* bone index size */
  103. if(n > 6) as = data[6]; /* animation morph index size */
  104. if(n > 7) rs = data[7]; /* rigidbody index size */
  105. data += n;
  106. /* name */
  107. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  108. if(!data[n] && !data[n + 1] && !data[n + 2]) {
  109. pmx_str(data, n, tmp); data += n;
  110. data += (data[0] | (data[1] << 8) | (data[2] << 16)) + 4;
  111. } else {
  112. data += n; n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  113. pmx_str(data, n, tmp); data += n;
  114. }
  115. m3d->name = _m3d_safestr(tmp, 2);
  116. /* comment */
  117. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  118. if(!data[n] && !data[n + 1] && !data[n + 2]) {
  119. pmx_str(data, n, tmp); data += n;
  120. data += (data[0] | (data[1] << 8) | (data[2] << 16)) + 4;
  121. } else {
  122. data += n; n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  123. pmx_str(data, n, tmp); data += n;
  124. }
  125. m3d->desc = _m3d_safestr(tmp, 3);
  126. /* vertex list */
  127. nv = data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24); data += 4;
  128. if(verbose > 1) printf(" NumVertex %u\n", nv);
  129. m3d->vertex = (m3dv_t*)realloc(m3d->vertex, (m3d->numvertex + 2 * nv) * sizeof(m3dv_t));
  130. if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  131. memset(&m3d->vertex[m3d->numvertex], 0, 2*nv * sizeof(m3dv_t));
  132. m3d->tmap = (m3dti_t*)realloc(m3d->tmap, (m3d->numtmap + nv) * sizeof(m3dti_t));
  133. if(!m3d->tmap) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  134. memset(&m3d->tmap[m3d->numtmap], 0, nv * sizeof(m3dti_t));
  135. m3d->skin = (m3ds_t*)realloc(m3d->skin, (m3d->numskin + nv) * sizeof(m3ds_t));
  136. if(!m3d->skin) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  137. memset(&m3d->skin[m3d->numskin], 0, nv * sizeof(m3ds_t));
  138. for(i = 0; i < nv && data < end; i++) {
  139. /* position */
  140. memcpy(&m3d->vertex[m3d->numvertex + i].x, data, 3 * sizeof(float));
  141. m3d->vertex[m3d->numvertex + i].z *= -1.0f;
  142. m3d->vertex[m3d->numvertex + i].w = 1.0f;
  143. m3d->vertex[m3d->numvertex + i].skinid = m3d->numskin + i;
  144. m3d->vertex[m3d->numvertex + i].type = VT_WORLD;
  145. data += 3 * sizeof(float);
  146. /* normal */
  147. memcpy(&m3d->vertex[m3d->numvertex + nv + i], data, 3 * sizeof(float));
  148. m3d->vertex[m3d->numvertex + nv + i].z *= -1.0f;
  149. m3d->vertex[m3d->numvertex + nv + i].w = 1.0f;
  150. m3d->vertex[m3d->numvertex + nv + i].skinid = -1U;
  151. m3d->vertex[m3d->numvertex + nv + i].type = VT_NORMAL;
  152. data += 3 * sizeof(float);
  153. /* uv */
  154. memcpy(&m3d->tmap[m3d->numtmap + i], data, 2 * sizeof(float));
  155. m3d->tmap[m3d->numtmap + i].v *= -1.0f;
  156. data += 2 * sizeof(float);
  157. /* additional vec4 */
  158. if(vc) {
  159. memcpy(&r, data + 0*sizeof(float), sizeof(float));
  160. memcpy(&b, data + 1*sizeof(float), sizeof(float));
  161. memcpy(&g, data + 2*sizeof(float), sizeof(float));
  162. memcpy(&a, data + 3*sizeof(float), sizeof(float));
  163. if(a > 0.1f)
  164. m3d->vertex[m3d->numvertex + i].color =
  165. ((uint32_t)(a*255.0) << 24L) |
  166. ((uint32_t)(b*255.0) << 16L) |
  167. ((uint32_t)(g*255.0) << 8L) |
  168. ((uint32_t)(r*255.0) << 0L);
  169. }
  170. data += 4 * vc * sizeof(float);
  171. /* skin */
  172. for(j = 0; j < M3D_NUMBONE; j++) m3d->skin[m3d->numskin + i].boneid[j] = -1U;
  173. switch(*data++) {
  174. case 0: /* BDEF1 */
  175. m3d->skin[m3d->numskin + i].boneid[0] = pmx_idx(data, bs); data += bs;
  176. m3d->skin[m3d->numskin + i].weight[0] = 1.0;
  177. break;
  178. case 1: /* BDEF2 */
  179. m3d->skin[m3d->numskin + i].boneid[0] = pmx_idx(data, bs); data += bs;
  180. m3d->skin[m3d->numskin + i].boneid[1] = pmx_idx(data, bs); data += bs;
  181. memcpy(&m3d->skin[m3d->numskin + i].weight[0], data, sizeof(float)); data += sizeof(float);
  182. m3d->skin[m3d->numskin + i].weight[1] = 1.0 - m3d->skin[m3d->numskin + i].weight[0];
  183. break;
  184. case 2: /* BDEF4 */
  185. for(j = 0; j < 4; j++, data += bs)
  186. m3d->skin[m3d->numskin + i].boneid[j] = pmx_idx(data, bs);
  187. for(j = 0; j < 4; j++, data += sizeof(float))
  188. memcpy(&m3d->skin[m3d->numskin + i].weight[j], data, sizeof(float));
  189. break;
  190. case 3: /* SDEF */
  191. data += bs + bs + 10 * sizeof(float);
  192. break;
  193. case 4: /* QDEF */
  194. data += 4 * (bs + sizeof(float));
  195. break;
  196. }
  197. data += sizeof(float); /* outline */
  198. }
  199. /* surface */
  200. n = data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24); data += 4;
  201. nf = n / 3; sav = data;
  202. if(verbose > 1) printf(" NumSurface %u (tri %u)\n", n, nf);
  203. m3d->face = (m3df_t*)realloc(m3d->face, (m3d->numface + nf) * sizeof(m3df_t));
  204. if(!m3d->face) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  205. memset(&m3d->face[m3d->numface], 255, nf * sizeof(m3df_t));
  206. for(i = 0; i < nf && data < end; i++) {
  207. m3d->face[m3d->numface + i].materialid = -1U;
  208. /* CW -> CCW */
  209. idx = pmx_idx(data, vs); data += vs;
  210. m3d->face[m3d->numface + i].vertex[0] = m3d->numvertex + idx;
  211. m3d->face[m3d->numface + i].normal[0] = m3d->numvertex + nv + idx;
  212. m3d->face[m3d->numface + i].texcoord[0] = m3d->numtmap + idx;
  213. idx = pmx_idx(data, vs); data += vs;
  214. m3d->face[m3d->numface + i].vertex[2] = m3d->numvertex + idx;
  215. m3d->face[m3d->numface + i].normal[2] = m3d->numvertex + nv + idx;
  216. m3d->face[m3d->numface + i].texcoord[2] = m3d->numtmap + idx;
  217. idx = pmx_idx(data, vs); data += vs;
  218. m3d->face[m3d->numface + i].vertex[1] = m3d->numvertex + idx;
  219. m3d->face[m3d->numface + i].normal[1] = m3d->numvertex + nv + idx;
  220. m3d->face[m3d->numface + i].texcoord[1] = m3d->numtmap + idx;
  221. }
  222. data = sav + n * vs;
  223. /* texture data */
  224. nt = data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24); data += 4;
  225. if(verbose > 1) printf(" NumTexture %u\n", nt);
  226. m3d->texture = (m3dtx_t*)realloc(m3d->texture, (m3d->numtexture + nt) * sizeof(m3dtx_t));
  227. if(!m3d->texture) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  228. memset(&m3d->texture[m3d->numtexture], 0, nt * sizeof(m3dtx_t));
  229. for(i = 0; i < nt && data < end; i++) {
  230. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  231. pmx_str(data, n, tmp); data += n;
  232. s = strrchr(tmp, '/');
  233. if(!s) s = strrchr(tmp, '\\');
  234. if(!s) s = tmp; else s++;
  235. e = strrchr(s, '.'); if(e) *e = 0;
  236. m3d->texture[m3d->numtexture + i].name = _m3d_safestr(s, 0);
  237. if(storeinline) {
  238. if(!e) e = s + strlen(s);
  239. strcpy(e, ".png");
  240. for(siz = strlen(tmp)-1; siz > 0; siz--) if(tmp[siz] == '\\') tmp[siz] = '/';
  241. if(!(readfile(tmp, &siz))) {
  242. strcpy(e, ".PNG");
  243. if(!(readfile(tmp, &siz))) {
  244. for(siz = strlen(tmp)-1; siz > 0; siz--)
  245. if(tmp[siz] >= 'A' && tmp[siz] <= 'Z') tmp[siz] += 'a'-'A';
  246. readfile(tmp, &siz);
  247. }
  248. }
  249. if(siz) {
  250. if(verbose > 1) printf(" Inlining '%s'\n", m3d->texture[m3d->numtexture + i].name);
  251. } else {
  252. if(verbose > 2) printf(" Texture '%s' not found\n", tmp);
  253. }
  254. }
  255. }
  256. /* materials */
  257. nm = data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24); data += 4;
  258. if(verbose > 1) printf(" NumMaterial %u\n", nm);
  259. m3d->material = (m3dm_t*)realloc(m3d->material, (m3d->nummaterial + nm) * sizeof(m3dm_t));
  260. if(!m3d->material) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  261. memset(&m3d->material[m3d->nummaterial], 0, nm * sizeof(m3dm_t));
  262. for(i = o = 0; i < nm && data < end; i++) {
  263. m = &m3d->material[m3d->nummaterial + i];
  264. m->prop = (m3dp_t*)malloc(8 * sizeof(m3dp_t));
  265. if(!m->prop) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  266. memset(m->prop, 0, 8 * sizeof(m3dp_t));
  267. /* name */
  268. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  269. if(!data[n] && !data[n + 1] && !data[n + 2]) {
  270. pmx_str(data, n, tmp); data += n;
  271. data += (data[0] | (data[1] << 8) | (data[2] << 16)) + 4;
  272. } else {
  273. data += n; n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  274. pmx_str(data, n, tmp); data += n;
  275. }
  276. m->name = _m3d_safestr(tmp, 0);
  277. if(verbose > 1) printf(" Material '%s' (%d, '%s')\n", tmp, i, m->name);
  278. /* diffuse color */
  279. memcpy(&r, data, sizeof(float)); data += sizeof(float);
  280. memcpy(&g, data, sizeof(float)); data += sizeof(float);
  281. memcpy(&b, data, sizeof(float)); data += sizeof(float);
  282. memcpy(&a, data, sizeof(float)); data += sizeof(float);
  283. if(r > M3D_EPSILON && g > M3D_EPSILON && b > M3D_EPSILON && a > M3D_EPSILON) {
  284. m->prop[m->numprop].type = m3dp_Kd;
  285. m->prop[m->numprop].value.color =
  286. ((uint32_t)(a*255.0) << 24L) |
  287. ((uint32_t)(b*255.0) << 16L) |
  288. ((uint32_t)(g*255.0) << 8L) |
  289. ((uint32_t)(r*255.0) << 0L);
  290. if(verbose > 2) printf(" Diffuse %08x\n", m->prop[m->numprop].value.color);
  291. m->numprop++;
  292. }
  293. /* specular color and strength */
  294. memcpy(&r, data, sizeof(float)); data += sizeof(float);
  295. memcpy(&g, data, sizeof(float)); data += sizeof(float);
  296. memcpy(&b, data, sizeof(float)); data += sizeof(float);
  297. memcpy(&a, data, sizeof(float)); data += sizeof(float);
  298. if(r > M3D_EPSILON && g > M3D_EPSILON && b > M3D_EPSILON && a > M3D_EPSILON) {
  299. m->prop[m->numprop].type = m3dp_Ks;
  300. m->prop[m->numprop].value.color =
  301. ((uint32_t)0xFF << 24L) |
  302. ((uint32_t)(b*255.0) << 16L) |
  303. ((uint32_t)(g*255.0) << 8L) |
  304. ((uint32_t)(r*255.0) << 0L);
  305. if(verbose > 2) printf(" Specular %08x (strength %f)\n", m->prop[m->numprop].value.color, a);
  306. m->numprop++;
  307. m->prop[m->numprop].type = m3dp_Ns;
  308. m->prop[m->numprop].value.fnum = a;
  309. m->numprop++;
  310. }
  311. /* ambient color */
  312. memcpy(&r, data, sizeof(float)); data += sizeof(float);
  313. memcpy(&g, data, sizeof(float)); data += sizeof(float);
  314. memcpy(&b, data, sizeof(float)); data += sizeof(float);
  315. if(r > M3D_EPSILON && g > M3D_EPSILON && b > M3D_EPSILON) {
  316. m->prop[m->numprop].type = m3dp_Ka;
  317. m->prop[m->numprop].value.color =
  318. ((uint32_t)0xFF << 24L) |
  319. ((uint32_t)(b*255.0) << 16L) |
  320. ((uint32_t)(g*255.0) << 8L) |
  321. ((uint32_t)(r*255.0) << 0L);
  322. if(verbose > 2) printf(" Ambient %08x\n", m->prop[m->numprop].value.color);
  323. m->numprop++;
  324. }
  325. /* flags */
  326. k = *data++;
  327. if(verbose > 2) printf(" Flags %02x\n", k);
  328. /* edge */
  329. data += 5 * sizeof(float);
  330. /* diffuse map */
  331. idx = pmx_idx(data, ts); data += ts;
  332. if(idx != -1) {
  333. l = m->numprop;
  334. m->prop[m->numprop].type = m3dp_map_Kd;
  335. m->prop[m->numprop++].value.textureid = m3d->numtexture + idx;
  336. if(verbose > 2) printf(" DiffuseMap %d\n", idx);
  337. } else l = -1;
  338. /* environment map and blend mode */
  339. idx = pmx_idx(data, ts); data += ts;
  340. if(idx != -1) {
  341. m->prop[m->numprop].type = m3dp_map_Km;
  342. m->prop[m->numprop++].value.textureid = m3d->numtexture + idx;
  343. if(verbose > 2) printf(" EnvMap %d\n", idx);
  344. }
  345. data++;
  346. /* toon texture */
  347. if(*data++) {
  348. idx = *data++;
  349. if(idx != -1) {
  350. sprintf(tmp, "toon%02u", idx);
  351. for(j = 0; j < nt && strcmp(m3d->texture[m3d->numtexture + j].name, tmp); j++);
  352. if(j >= nt) {
  353. sprintf(tmp, "toon-%02u", idx);
  354. for(j = 0; j < nt && strcmp(m3d->texture[m3d->numtexture + j].name, tmp); j++);
  355. if(j >= nt) {
  356. sprintf(tmp, "toon%u", idx);
  357. for(j = 0; j < nt && strcmp(m3d->texture[m3d->numtexture + j].name, tmp); j++);
  358. if(j >= nt) {
  359. sprintf(tmp, "toon-%u", idx);
  360. for(j = 0; j < nt && strcmp(m3d->texture[m3d->numtexture + j].name, tmp); j++);
  361. if(j >= nt) idx = -1;
  362. }
  363. }
  364. }
  365. }
  366. } else { idx = pmx_idx(data, ts); data += ts; }
  367. if(idx != -1) {
  368. if(verbose > 2) printf(" ToonTexture %d\n", idx);
  369. /* if we already have a DiffuseMap, replace it */
  370. /*
  371. if(l != -1) m->prop[l].value.textureid = m3d->numtexture + idx;
  372. else {
  373. m->prop[m->numprop].type = m3dp_map_Kd;
  374. m->prop[m->numprop++].value.textureid = m3d->numtexture + idx;
  375. }
  376. */
  377. }
  378. /* meta */
  379. data += (data[0] | (data[1] << 8) | (data[2] << 16)) + 4;
  380. /* surface count */
  381. l = (data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24)) / 3; data += 4;
  382. if(verbose > 2) printf(" SurfaceCount %u VertexColor %d\n", l, (k & (1 << 5)) ? 1 : 0);
  383. for(j = 0; j < l; j++, o++)
  384. /* vertex color flag not set */
  385. if(!(k & (1 << 5))) {
  386. m3d->face[m3d->numface + o].materialid = m3d->nummaterial + i;
  387. m3d->vertex[m3d->face[m3d->numface + o].vertex[0]].color =
  388. m3d->vertex[m3d->face[m3d->numface + o].vertex[1]].color =
  389. m3d->vertex[m3d->face[m3d->numface + o].vertex[2]].color = 0;
  390. }
  391. }
  392. if(verbose > 1 && o != nf) printf(" SurfaceCount %u != NumSurface %u\n", o, nf);
  393. /* bones */
  394. nb = data[0] | (data[1] << 8) | (data[2] << 16) | ((data[3] & 0x7F) << 24); data += 4;
  395. m3d->bone = (m3db_t*)realloc(m3d->bone, (m3d->numbone + nb) * sizeof(m3db_t));
  396. if(!m3d->bone) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  397. memset(&m3d->bone[m3d->numbone], 0, nb * sizeof(m3db_t));
  398. m3d->vertex = (m3dv_t*)realloc(m3d->vertex, (m3d->numvertex + 2 * (nv + nb)) * sizeof(m3dv_t));
  399. if(!m3d->vertex) { fprintf(stderr, "m3dconv: unable to allocate memory\n"); exit(1); }
  400. memset(&m3d->vertex[m3d->numvertex + 2 * nv], 0, 2 * nb * sizeof(m3dv_t));
  401. for(i = 0; i < nb && data < end; i++) {
  402. /* name */
  403. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  404. if(!data[n] && !data[n + 1] && !data[n + 2]) {
  405. pmx_str(data, n, tmp); data += n;
  406. data += (data[0] | (data[1] << 8) | (data[2] << 16)) + 4;
  407. } else {
  408. data += n; n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  409. pmx_str(data, n, tmp); data += n;
  410. }
  411. m3d->bone[m3d->numbone + i].name = _m3d_safestr(tmp, 0);
  412. if(verbose > 1) printf(" Bone '%s' (%d, '%s')\n", tmp, i, m3d->bone[m3d->numbone + i].name);
  413. /* position */
  414. j = m3d->numvertex + 2 * (nv + i);
  415. memcpy(&m3d->vertex[j].x, data, 3 * sizeof(float)); data += 3 * sizeof(float);
  416. m3d->vertex[j].z *= -1.0f;
  417. m3d->vertex[j].w = 1.0f;
  418. m3d->vertex[j].skinid = -1U;
  419. m3d->vertex[j].type = VT_WORLD;
  420. m3d->bone[m3d->numbone + i].pos = j;
  421. if(verbose > 2) printf(" Position %u (%f, %f, %f)\n", j, m3d->vertex[j].x, m3d->vertex[j].y, m3d->vertex[j].z);
  422. /* parent */
  423. m3d->bone[m3d->numbone + i].parent = pmx_idx(data, bs); data += bs;
  424. if(verbose > 2) printf(" Parent %d\n", m3d->bone[m3d->numbone + i].parent);
  425. /* layer */
  426. data += 4;
  427. /* flags */
  428. k = data[0] | (data[1] << 8); data += 2;
  429. if(verbose > 2) printf(" Flags %04x\n", k);
  430. /* tail */
  431. if(!(k & 1)) {
  432. j = m3d->numvertex + 2 * (nv + i) + 1;
  433. /* temporarily store the tail position in the oriantaion's place */
  434. memcpy(&m3d->vertex[j].x, data, 3 * sizeof(float)); data += 3 * sizeof(float);
  435. m3d->vertex[j].z *= -1.0f;
  436. m3d->bone[m3d->numbone + i].ori = j;
  437. m3d->bone[m3d->numbone + i].numweight = 0; /* use numweight as a flag */
  438. if(verbose > 2) printf(" Tail Pos %u (%f, %f, %f)\n", j, m3d->vertex[j].x, m3d->vertex[j].y, m3d->vertex[j].z);
  439. } else {
  440. /* temporarily store the tail bone index in the oriantaion's index */
  441. m3d->bone[m3d->numbone + i].ori = pmx_idx(data, bs); data += bs;
  442. m3d->bone[m3d->numbone + i].numweight = 1; /* ori is a bone index */
  443. if(verbose > 2) printf(" Tail Bone %d\n", m3d->bone[m3d->numbone + i].ori);
  444. }
  445. /* inherit bone */
  446. if(k & (3 << 8)) {
  447. data += bs + sizeof(float);
  448. if(verbose > 2) printf(" Inherit bone\n");
  449. }
  450. /* fixed axis */
  451. if(k & (1 << 10)) {
  452. data += 3 * sizeof(float);
  453. if(verbose > 2) printf(" Fixed axis\n");
  454. }
  455. /* local coordinate */
  456. if(k & (1 << 11)) {
  457. data += 6 * sizeof(float);
  458. if(verbose > 2) printf(" Local\n");
  459. }
  460. /* external parent */
  461. if(k & (1 << 12)) {
  462. data += bs;
  463. if(verbose > 2) printf(" External\n");
  464. }
  465. /* inverse kinematics */
  466. if(k & (1 << 5)) {
  467. data += bs + 4 + sizeof(float);
  468. n = data[0] | (data[1] << 8) | (data[2] << 16); data += 4;
  469. if(verbose > 2) printf(" IK %u\n", n);
  470. for(j = 0; j < n; j++) {
  471. data += bs;
  472. if(*data++) data += 6 * sizeof(float);
  473. }
  474. }
  475. }
  476. /* resolve orientations, we can't do this sooner because tail bone index might be a forward reference */
  477. /* also convert absolute positions to bone relative positions */
  478. if(verbose > 2) printf(" Bone Orientations\n");
  479. for(i = nb - 1; i >= 0; i--) {
  480. j = m3d->numvertex + 2 * (nv + i);
  481. if(m3d->bone[m3d->numbone + i].ori != -1U) {
  482. if(m3d->bone[m3d->numbone + i].numweight && m3d->bone[m3d->numbone + i].ori) {
  483. m3d->bone[m3d->numbone + i].numweight = 0;
  484. v = &m3d->vertex[m3d->bone[m3d->bone[m3d->numbone + i].ori].pos];
  485. } else
  486. v = &m3d->vertex[m3d->bone[m3d->numbone + i].ori];
  487. /* head in m3d->vertex[j], tail in v, convert to rotation quaternion */
  488. _m3d_euler_to_quat(v->x - m3d->vertex[j].x, v->y - m3d->vertex[j].y, v->z - m3d->vertex[j].z, &m3d->vertex[j + 1]);
  489. } else { m3d->vertex[j + 1].x = m3d->vertex[j + 1].y = m3d->vertex[j + 1].z = 0.0f; m3d->vertex[j + 1].w = 1.0f; }
  490. m3d->vertex[j + 1].skinid = -2U;
  491. m3d->vertex[j + 1].type = VT_QUATERN;
  492. m3d->bone[m3d->numbone + i].ori = j + 1;
  493. /*
  494. if(m3d->bone[m3d->numbone + i].parent != -1U) {
  495. v = &m3d->vertex[m3d->bone[m3d->bone[m3d->numbone + i].parent].pos];
  496. m3d->vertex[j].x -= v->x;
  497. m3d->vertex[j].y -= v->y;
  498. m3d->vertex[j].z -= v->z;
  499. m3d->vertex[j].type = VT_RELATIVE;
  500. }
  501. */
  502. }
  503. m3d->numvertex += 2 * (nv + nb);
  504. m3d->numtexture += nt;
  505. m3d->numtmap += nv;
  506. m3d->numskin += nv;
  507. m3d->numface += nf;
  508. m3d->numbone += nb;
  509. m3d->nummaterial += nm;
  510. return m3d;
  511. }