models.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "qdata.h"
  19. //=================================================================
  20. typedef struct
  21. {
  22. int numnormals;
  23. vec3_t normalsum;
  24. } vertexnormals_t;
  25. typedef struct
  26. {
  27. vec3_t v;
  28. int lightnormalindex;
  29. } trivert_t;
  30. typedef struct
  31. {
  32. vec3_t mins, maxs;
  33. char name[16];
  34. trivert_t v[MAX_VERTS];
  35. } frame_t;
  36. //================================================================
  37. frame_t g_frames[MAX_FRAMES];
  38. dmdl_t model;
  39. float scale_up; // set by $scale
  40. vec3_t adjust; // set by $origin
  41. int g_fixedwidth, g_fixedheight; // set by $skinsize
  42. //
  43. // base frame info
  44. //
  45. vec3_t base_xyz[MAX_VERTS];
  46. dstvert_t base_st[MAX_VERTS];
  47. dtriangle_t triangles[MAX_TRIANGLES];
  48. int triangle_st[MAX_TRIANGLES][3][2];
  49. // the command list holds counts, s/t values, and xyz indexes
  50. // that are valid for every frame
  51. int commands[16384];
  52. int numcommands;
  53. int numglverts;
  54. int used[MAX_TRIANGLES];
  55. char g_skins[MAX_MD2SKINS][64];
  56. char cdarchive[1024];
  57. char cdpartial[1024];
  58. char cddir[1024];
  59. char modelname[64]; // empty unless $modelname issued (players)
  60. #define NUMVERTEXNORMALS 162
  61. float avertexnormals[NUMVERTEXNORMALS][3] = {
  62. #include "anorms.h"
  63. };
  64. FILE *headerouthandle = NULL;
  65. //==============================================================
  66. /*
  67. ===============
  68. ClearModel
  69. ===============
  70. */
  71. void ClearModel (void)
  72. {
  73. memset (&model, 0, sizeof(model));
  74. modelname[0] = 0;
  75. scale_up = 1.0;
  76. VectorCopy (vec3_origin, adjust);
  77. g_fixedwidth = g_fixedheight = 0;
  78. g_skipmodel = false;
  79. }
  80. void H_printf(char *fmt, ...)
  81. {
  82. va_list argptr;
  83. char name[1024];
  84. if (!headerouthandle)
  85. {
  86. sprintf (name, "%s/tris.h", cddir);
  87. headerouthandle = SafeOpenWrite (name);
  88. fprintf(headerouthandle, "// %s\n\n", cddir);
  89. fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
  90. }
  91. va_start (argptr, fmt);
  92. vfprintf (headerouthandle, fmt, argptr);
  93. va_end (argptr);
  94. }
  95. /*
  96. ============
  97. WriteModelFile
  98. ============
  99. */
  100. void WriteModelFile (FILE *modelouthandle)
  101. {
  102. int i;
  103. dmdl_t modeltemp;
  104. int j, k;
  105. frame_t *in;
  106. daliasframe_t *out;
  107. byte buffer[MAX_VERTS*4+128];
  108. float v;
  109. int c_on, c_off;
  110. model.ident = IDALIASHEADER;
  111. model.version = ALIAS_VERSION;
  112. model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
  113. model.num_glcmds = numcommands;
  114. model.ofs_skins = sizeof(dmdl_t);
  115. model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
  116. model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
  117. model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
  118. model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
  119. model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
  120. //
  121. // write out the model header
  122. //
  123. for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
  124. ((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
  125. SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
  126. //
  127. // write out the skin names
  128. //
  129. SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
  130. //
  131. // write out the texture coordinates
  132. //
  133. c_on = c_off = 0;
  134. for (i=0 ; i<model.num_st ; i++)
  135. {
  136. base_st[i].s = LittleShort (base_st[i].s);
  137. base_st[i].t = LittleShort (base_st[i].t);
  138. }
  139. SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
  140. //
  141. // write out the triangles
  142. //
  143. for (i=0 ; i<model.num_tris ; i++)
  144. {
  145. int j;
  146. dtriangle_t tri;
  147. for (j=0 ; j<3 ; j++)
  148. {
  149. tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
  150. tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
  151. }
  152. SafeWrite (modelouthandle, &tri, sizeof(tri));
  153. }
  154. //
  155. // write out the frames
  156. //
  157. for (i=0 ; i<model.num_frames ; i++)
  158. {
  159. in = &g_frames[i];
  160. out = (daliasframe_t *)buffer;
  161. strcpy (out->name, in->name);
  162. for (j=0 ; j<3 ; j++)
  163. {
  164. out->scale[j] = (in->maxs[j] - in->mins[j])/255;
  165. out->translate[j] = in->mins[j];
  166. }
  167. for (j=0 ; j<model.num_xyz ; j++)
  168. {
  169. // all of these are byte values, so no need to deal with endianness
  170. out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
  171. for (k=0 ; k<3 ; k++)
  172. {
  173. // scale to byte values & min/max check
  174. v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
  175. // clamp, so rounding doesn't wrap from 255.6 to 0
  176. if (v > 255.0)
  177. v = 255.0;
  178. if (v < 0)
  179. v = 0;
  180. out->verts[j].v[k] = v;
  181. }
  182. }
  183. for (j=0 ; j<3 ; j++)
  184. {
  185. out->scale[j] = LittleFloat (out->scale[j]);
  186. out->translate[j] = LittleFloat (out->translate[j]);
  187. }
  188. SafeWrite (modelouthandle, out, model.framesize);
  189. }
  190. //
  191. // write out glcmds
  192. //
  193. SafeWrite (modelouthandle, commands, numcommands*4);
  194. }
  195. /*
  196. ===============
  197. FinishModel
  198. ===============
  199. */
  200. void FinishModel (void)
  201. {
  202. FILE *modelouthandle;
  203. int i;
  204. char name[1024];
  205. if (!model.num_frames)
  206. return;
  207. //
  208. // copy to release directory tree if doing a release build
  209. //
  210. if (g_release)
  211. {
  212. if (modelname[0])
  213. sprintf (name, "%s", modelname);
  214. else
  215. sprintf (name, "%s/tris.md2", cdpartial);
  216. ReleaseFile (name);
  217. for (i=0 ; i<model.num_skins ; i++)
  218. {
  219. ReleaseFile (g_skins[i]);
  220. }
  221. model.num_frames = 0;
  222. return;
  223. }
  224. //
  225. // write the model output file
  226. //
  227. if (modelname[0])
  228. sprintf (name, "%s%s", gamedir, modelname);
  229. else
  230. sprintf (name, "%s/tris.md2", cddir);
  231. printf ("saving to %s\n", name);
  232. CreatePath (name);
  233. modelouthandle = SafeOpenWrite (name);
  234. WriteModelFile (modelouthandle);
  235. printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
  236. printf ("%4d vertexes\n", model.num_xyz);
  237. printf ("%4d triangles\n", model.num_tris);
  238. printf ("%4d frame\n", model.num_frames);
  239. printf ("%4d glverts\n", numglverts);
  240. printf ("%4d glcmd\n", model.num_glcmds);
  241. printf ("%4d skins\n", model.num_skins);
  242. printf ("file size: %d\n", (int)ftell (modelouthandle) );
  243. printf ("---------------------\n");
  244. fclose (modelouthandle);
  245. // finish writing header file
  246. H_printf("\n");
  247. // scale_up is usefull to allow step distances to be adjusted
  248. H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
  249. fclose (headerouthandle);
  250. headerouthandle = NULL;
  251. }
  252. /*
  253. =================================================================
  254. ALIAS MODEL DISPLAY LIST GENERATION
  255. =================================================================
  256. */
  257. int strip_xyz[128];
  258. int strip_st[128];
  259. int strip_tris[128];
  260. int stripcount;
  261. /*
  262. ================
  263. StripLength
  264. ================
  265. */
  266. int StripLength (int starttri, int startv)
  267. {
  268. int m1, m2;
  269. int st1, st2;
  270. int j;
  271. dtriangle_t *last, *check;
  272. int k;
  273. used[starttri] = 2;
  274. last = &triangles[starttri];
  275. strip_xyz[0] = last->index_xyz[(startv)%3];
  276. strip_xyz[1] = last->index_xyz[(startv+1)%3];
  277. strip_xyz[2] = last->index_xyz[(startv+2)%3];
  278. strip_st[0] = last->index_st[(startv)%3];
  279. strip_st[1] = last->index_st[(startv+1)%3];
  280. strip_st[2] = last->index_st[(startv+2)%3];
  281. strip_tris[0] = starttri;
  282. stripcount = 1;
  283. m1 = last->index_xyz[(startv+2)%3];
  284. st1 = last->index_st[(startv+2)%3];
  285. m2 = last->index_xyz[(startv+1)%3];
  286. st2 = last->index_st[(startv+1)%3];
  287. // look for a matching triangle
  288. nexttri:
  289. for (j=starttri+1, check=&triangles[starttri+1]
  290. ; j<model.num_tris ; j++, check++)
  291. {
  292. for (k=0 ; k<3 ; k++)
  293. {
  294. if (check->index_xyz[k] != m1)
  295. continue;
  296. if (check->index_st[k] != st1)
  297. continue;
  298. if (check->index_xyz[ (k+1)%3 ] != m2)
  299. continue;
  300. if (check->index_st[ (k+1)%3 ] != st2)
  301. continue;
  302. // this is the next part of the fan
  303. // if we can't use this triangle, this tristrip is done
  304. if (used[j])
  305. goto done;
  306. // the new edge
  307. if (stripcount & 1)
  308. {
  309. m2 = check->index_xyz[ (k+2)%3 ];
  310. st2 = check->index_st[ (k+2)%3 ];
  311. }
  312. else
  313. {
  314. m1 = check->index_xyz[ (k+2)%3 ];
  315. st1 = check->index_st[ (k+2)%3 ];
  316. }
  317. strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
  318. strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
  319. strip_tris[stripcount] = j;
  320. stripcount++;
  321. used[j] = 2;
  322. goto nexttri;
  323. }
  324. }
  325. done:
  326. // clear the temp used flags
  327. for (j=starttri+1 ; j<model.num_tris ; j++)
  328. if (used[j] == 2)
  329. used[j] = 0;
  330. return stripcount;
  331. }
  332. /*
  333. ===========
  334. FanLength
  335. ===========
  336. */
  337. int FanLength (int starttri, int startv)
  338. {
  339. int m1, m2;
  340. int st1, st2;
  341. int j;
  342. dtriangle_t *last, *check;
  343. int k;
  344. used[starttri] = 2;
  345. last = &triangles[starttri];
  346. strip_xyz[0] = last->index_xyz[(startv)%3];
  347. strip_xyz[1] = last->index_xyz[(startv+1)%3];
  348. strip_xyz[2] = last->index_xyz[(startv+2)%3];
  349. strip_st[0] = last->index_st[(startv)%3];
  350. strip_st[1] = last->index_st[(startv+1)%3];
  351. strip_st[2] = last->index_st[(startv+2)%3];
  352. strip_tris[0] = starttri;
  353. stripcount = 1;
  354. m1 = last->index_xyz[(startv+0)%3];
  355. st1 = last->index_st[(startv+0)%3];
  356. m2 = last->index_xyz[(startv+2)%3];
  357. st2 = last->index_st[(startv+2)%3];
  358. // look for a matching triangle
  359. nexttri:
  360. for (j=starttri+1, check=&triangles[starttri+1]
  361. ; j<model.num_tris ; j++, check++)
  362. {
  363. for (k=0 ; k<3 ; k++)
  364. {
  365. if (check->index_xyz[k] != m1)
  366. continue;
  367. if (check->index_st[k] != st1)
  368. continue;
  369. if (check->index_xyz[ (k+1)%3 ] != m2)
  370. continue;
  371. if (check->index_st[ (k+1)%3 ] != st2)
  372. continue;
  373. // this is the next part of the fan
  374. // if we can't use this triangle, this tristrip is done
  375. if (used[j])
  376. goto done;
  377. // the new edge
  378. m2 = check->index_xyz[ (k+2)%3 ];
  379. st2 = check->index_st[ (k+2)%3 ];
  380. strip_xyz[stripcount+2] = m2;
  381. strip_st[stripcount+2] = st2;
  382. strip_tris[stripcount] = j;
  383. stripcount++;
  384. used[j] = 2;
  385. goto nexttri;
  386. }
  387. }
  388. done:
  389. // clear the temp used flags
  390. for (j=starttri+1 ; j<model.num_tris ; j++)
  391. if (used[j] == 2)
  392. used[j] = 0;
  393. return stripcount;
  394. }
  395. /*
  396. ================
  397. BuildGlCmds
  398. Generate a list of trifans or strips
  399. for the model, which holds for all frames
  400. ================
  401. */
  402. void BuildGlCmds (void)
  403. {
  404. int i, j, k;
  405. int startv;
  406. float s, t;
  407. int len, bestlen, besttype;
  408. int best_xyz[1024];
  409. int best_st[1024];
  410. int best_tris[1024];
  411. int type;
  412. //
  413. // build tristrips
  414. //
  415. numcommands = 0;
  416. numglverts = 0;
  417. memset (used, 0, sizeof(used));
  418. for (i=0 ; i<model.num_tris ; i++)
  419. {
  420. // pick an unused triangle and start the trifan
  421. if (used[i])
  422. continue;
  423. bestlen = 0;
  424. for (type = 0 ; type < 2 ; type++)
  425. // type = 1;
  426. {
  427. for (startv =0 ; startv < 3 ; startv++)
  428. {
  429. if (type == 1)
  430. len = StripLength (i, startv);
  431. else
  432. len = FanLength (i, startv);
  433. if (len > bestlen)
  434. {
  435. besttype = type;
  436. bestlen = len;
  437. for (j=0 ; j<bestlen+2 ; j++)
  438. {
  439. best_st[j] = strip_st[j];
  440. best_xyz[j] = strip_xyz[j];
  441. }
  442. for (j=0 ; j<bestlen ; j++)
  443. best_tris[j] = strip_tris[j];
  444. }
  445. }
  446. }
  447. // mark the tris on the best strip/fan as used
  448. for (j=0 ; j<bestlen ; j++)
  449. used[best_tris[j]] = 1;
  450. if (besttype == 1)
  451. commands[numcommands++] = (bestlen+2);
  452. else
  453. commands[numcommands++] = -(bestlen+2);
  454. numglverts += bestlen+2;
  455. for (j=0 ; j<bestlen+2 ; j++)
  456. {
  457. // emit a vertex into the reorder buffer
  458. k = best_st[j];
  459. // emit s/t coords into the commands stream
  460. s = base_st[k].s;
  461. t = base_st[k].t;
  462. s = (s + 0.5) / model.skinwidth;
  463. t = (t + 0.5) / model.skinheight;
  464. *(float *)&commands[numcommands++] = s;
  465. *(float *)&commands[numcommands++] = t;
  466. *(int *)&commands[numcommands++] = best_xyz[j];
  467. }
  468. }
  469. commands[numcommands++] = 0; // end of list marker
  470. }
  471. /*
  472. ===============================================================
  473. BASE FRAME SETUP
  474. ===============================================================
  475. */
  476. /*
  477. ============
  478. BuildST
  479. Builds the triangle_st array for the base frame and
  480. model.skinwidth / model.skinheight
  481. FIXME: allow this to be loaded from a file for
  482. arbitrary mappings
  483. ============
  484. */
  485. void BuildST (triangle_t *ptri, int numtri)
  486. {
  487. int i, j;
  488. int width, height, iwidth, iheight, swidth;
  489. float basex, basey;
  490. float s_scale, t_scale;
  491. float scale;
  492. vec3_t mins, maxs;
  493. float *pbasevert;
  494. vec3_t vtemp1, vtemp2, normal;
  495. //
  496. // find bounds of all the verts on the base frame
  497. //
  498. ClearBounds (mins, maxs);
  499. for (i=0 ; i<numtri ; i++)
  500. for (j=0 ; j<3 ; j++)
  501. AddPointToBounds (ptri[i].verts[j], mins, maxs);
  502. for (i=0 ; i<3 ; i++)
  503. {
  504. mins[i] = floor(mins[i]);
  505. maxs[i] = ceil(maxs[i]);
  506. }
  507. width = maxs[0] - mins[0];
  508. height = maxs[2] - mins[2];
  509. if (!g_fixedwidth)
  510. { // old style
  511. scale = 8;
  512. if (width*scale >= 150)
  513. scale = 150.0 / width;
  514. if (height*scale >= 190)
  515. scale = 190.0 / height;
  516. s_scale = t_scale = scale;
  517. iwidth = ceil(width*s_scale);
  518. iheight = ceil(height*t_scale);
  519. iwidth += 4;
  520. iheight += 4;
  521. }
  522. else
  523. { // new style
  524. iwidth = g_fixedwidth / 2;
  525. iheight = g_fixedheight;
  526. s_scale = (float)(iwidth-4) / width;
  527. t_scale = (float)(iheight-4) / height;
  528. }
  529. //
  530. // determine which side of each triangle to map the texture to
  531. //
  532. for (i=0 ; i<numtri ; i++)
  533. {
  534. VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
  535. VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
  536. CrossProduct (vtemp1, vtemp2, normal);
  537. if (normal[1] > 0)
  538. {
  539. basex = iwidth + 2;
  540. }
  541. else
  542. {
  543. basex = 2;
  544. }
  545. basey = 2;
  546. for (j=0 ; j<3 ; j++)
  547. {
  548. pbasevert = ptri[i].verts[j];
  549. triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
  550. triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
  551. }
  552. }
  553. // make the width a multiple of 4; some hardware requires this, and it ensures
  554. // dword alignment for each scan
  555. swidth = iwidth*2;
  556. model.skinwidth = (swidth + 3) & ~3;
  557. model.skinheight = iheight;
  558. }
  559. /*
  560. =================
  561. Cmd_Base
  562. =================
  563. */
  564. void Cmd_Base (void)
  565. {
  566. triangle_t *ptri;
  567. int i, j, k;
  568. int time1;
  569. char file1[1024];
  570. GetToken (false);
  571. if (g_skipmodel || g_release || g_archive)
  572. return;
  573. printf ("---------------------\n");
  574. sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
  575. printf ("%s\n", file1);
  576. ExpandPathAndArchive (file1);
  577. sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
  578. time1 = FileTime (file1);
  579. if (time1 == -1)
  580. Error ("%s doesn't exist", file1);
  581. //
  582. // load the base triangles
  583. //
  584. if (do3ds)
  585. Load3DSTriangleList (file1, &ptri, &model.num_tris);
  586. else
  587. LoadTriangleList (file1, &ptri, &model.num_tris);
  588. //
  589. // get the ST values
  590. //
  591. BuildST (ptri, model.num_tris);
  592. //
  593. // run through all the base triangles, storing each unique vertex in the
  594. // base vertex list and setting the indirect triangles to point to the base
  595. // vertices
  596. //
  597. for (i=0 ; i<model.num_tris ; i++)
  598. {
  599. for (j=0 ; j<3 ; j++)
  600. {
  601. // get the xyz index
  602. for (k=0 ; k<model.num_xyz ; k++)
  603. if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
  604. break; // this vertex is already in the base vertex list
  605. if (k == model.num_xyz)
  606. { // new index
  607. VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
  608. model.num_xyz++;
  609. }
  610. triangles[i].index_xyz[j] = k;
  611. // get the st index
  612. for (k=0 ; k<model.num_st ; k++)
  613. if (triangle_st[i][j][0] == base_st[k].s
  614. && triangle_st[i][j][1] == base_st[k].t)
  615. break; // this vertex is already in the base vertex list
  616. if (k == model.num_st)
  617. { // new index
  618. base_st[model.num_st].s = triangle_st[i][j][0];
  619. base_st[model.num_st].t = triangle_st[i][j][1];
  620. model.num_st++;
  621. }
  622. triangles[i].index_st[j] = k;
  623. }
  624. }
  625. // build triangle strips / fans
  626. BuildGlCmds ();
  627. }
  628. //===============================================================
  629. char *FindFrameFile (char *frame)
  630. {
  631. int time1;
  632. char file1[1024];
  633. static char retname[1024];
  634. char base[32];
  635. char suffix[32];
  636. char *s;
  637. if (strstr (frame, "."))
  638. return frame; // allready in dot format
  639. // split 'run1' into 'run' and '1'
  640. s = frame + strlen(frame)-1;
  641. while (s != frame && *s >= '0' && *s <= '9')
  642. s--;
  643. strcpy (suffix, s+1);
  644. strcpy (base, frame);
  645. base[s-frame+1] = 0;
  646. // check for 'run1.tri'
  647. sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, trifileext);
  648. time1 = FileTime (file1);
  649. if (time1 != -1)
  650. {
  651. sprintf (retname, "%s%s.%s", base, suffix, trifileext);
  652. return retname;
  653. }
  654. // check for 'run.1'
  655. sprintf (file1, "%s/%s.%s",cddir, base, suffix);
  656. time1 = FileTime (file1);
  657. if (time1 != -1)
  658. {
  659. sprintf (retname, "%s.%s", base, suffix);
  660. return retname;
  661. }
  662. Error ("frame %s could not be found",frame);
  663. return NULL;
  664. }
  665. /*
  666. ===============
  667. GrabFrame
  668. ===============
  669. */
  670. void GrabFrame (char *frame)
  671. {
  672. triangle_t *ptri;
  673. int i, j;
  674. trivert_t *ptrivert;
  675. int num_tris;
  676. char file1[1024];
  677. frame_t *fr;
  678. vertexnormals_t vnorms[MAX_VERTS];
  679. int index_xyz;
  680. char *framefile;
  681. // the frame 'run1' will be looked for as either
  682. // run.1 or run1.tri, so the new alias sequence save
  683. // feature an be used
  684. framefile = FindFrameFile (frame);
  685. sprintf (file1, "%s/%s", cdarchive, framefile);
  686. ExpandPathAndArchive (file1);
  687. sprintf (file1, "%s/%s",cddir, framefile);
  688. printf ("grabbing %s\n", file1);
  689. if (model.num_frames >= MAX_FRAMES)
  690. Error ("model.num_frames >= MAX_FRAMES");
  691. fr = &g_frames[model.num_frames];
  692. model.num_frames++;
  693. strcpy (fr->name, frame);
  694. //
  695. // load the frame
  696. //
  697. if (do3ds)
  698. Load3DSTriangleList (file1, &ptri, &num_tris);
  699. else
  700. LoadTriangleList (file1, &ptri, &num_tris);
  701. if (num_tris != model.num_tris)
  702. Error ("%s: number of triangles doesn't match base frame\n", file1);
  703. //
  704. // allocate storage for the frame's vertices
  705. //
  706. ptrivert = fr->v;
  707. for (i=0 ; i<model.num_xyz ; i++)
  708. {
  709. vnorms[i].numnormals = 0;
  710. VectorClear (vnorms[i].normalsum);
  711. }
  712. ClearBounds (fr->mins, fr->maxs);
  713. //
  714. // store the frame's vertices in the same order as the base. This assumes the
  715. // triangles and vertices in this frame are in exactly the same order as in the
  716. // base
  717. //
  718. for (i=0 ; i<num_tris ; i++)
  719. {
  720. vec3_t vtemp1, vtemp2, normal;
  721. float ftemp;
  722. VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
  723. VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
  724. CrossProduct (vtemp1, vtemp2, normal);
  725. VectorNormalize (normal, normal);
  726. // rotate the normal so the model faces down the positive x axis
  727. ftemp = normal[0];
  728. normal[0] = -normal[1];
  729. normal[1] = ftemp;
  730. for (j=0 ; j<3 ; j++)
  731. {
  732. index_xyz = triangles[i].index_xyz[j];
  733. // rotate the vertices so the model faces down the positive x axis
  734. // also adjust the vertices to the desired origin
  735. ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
  736. adjust[0];
  737. ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
  738. adjust[1];
  739. ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
  740. adjust[2];
  741. AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
  742. VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
  743. vnorms[index_xyz].numnormals++;
  744. }
  745. }
  746. //
  747. // calculate the vertex normals, match them to the template list, and store the
  748. // index of the best match
  749. //
  750. for (i=0 ; i<model.num_xyz ; i++)
  751. {
  752. int j;
  753. vec3_t v;
  754. float maxdot;
  755. int maxdotindex;
  756. int c;
  757. c = vnorms[i].numnormals;
  758. if (!c)
  759. Error ("Vertex with no triangles attached");
  760. VectorScale (vnorms[i].normalsum, 1.0/c, v);
  761. VectorNormalize (v, v);
  762. maxdot = -999999.0;
  763. maxdotindex = -1;
  764. for (j=0 ; j<NUMVERTEXNORMALS ; j++)
  765. {
  766. float dot;
  767. dot = DotProduct (v, avertexnormals[j]);
  768. if (dot > maxdot)
  769. {
  770. maxdot = dot;
  771. maxdotindex = j;
  772. }
  773. }
  774. ptrivert[i].lightnormalindex = maxdotindex;
  775. }
  776. free (ptri);
  777. }
  778. /*
  779. ===============
  780. Cmd_Frame
  781. ===============
  782. */
  783. void Cmd_Frame (void)
  784. {
  785. while (TokenAvailable())
  786. {
  787. GetToken (false);
  788. if (g_skipmodel)
  789. continue;
  790. if (g_release || g_archive)
  791. {
  792. model.num_frames = 1; // don't skip the writeout
  793. continue;
  794. }
  795. H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
  796. GrabFrame (token);
  797. }
  798. }
  799. /*
  800. ===============
  801. Cmd_Skin
  802. Skins aren't actually stored in the file, only a reference
  803. is saved out to the header file.
  804. ===============
  805. */
  806. void Cmd_Skin (void)
  807. {
  808. byte *palette;
  809. byte *pixels;
  810. int width, height;
  811. byte *cropped;
  812. int y;
  813. char name[1024], savename[1024];
  814. GetToken (false);
  815. if (model.num_skins == MAX_MD2SKINS)
  816. Error ("model.num_skins == MAX_MD2SKINS");
  817. if (g_skipmodel)
  818. return;
  819. sprintf (name, "%s/%s.lbm", cdarchive, token);
  820. strcpy (name, ExpandPathAndArchive( name ) );
  821. // sprintf (name, "%s/%s.lbm", cddir, token);
  822. if (TokenAvailable())
  823. {
  824. GetToken (false);
  825. sprintf (g_skins[model.num_skins], "%s.pcx", token);
  826. sprintf (savename, "%s%s.pcx", gamedir, g_skins[model.num_skins]);
  827. }
  828. else
  829. {
  830. sprintf (savename, "%s/%s.pcx", cddir, token);
  831. sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
  832. }
  833. model.num_skins++;
  834. if (g_skipmodel || g_release || g_archive)
  835. return;
  836. // load the image
  837. printf ("loading %s\n", name);
  838. Load256Image (name, &pixels, &palette, &width, &height);
  839. RemapZero (pixels, palette, width, height);
  840. // crop it to the proper size
  841. cropped = malloc (model.skinwidth*model.skinheight);
  842. for (y=0 ; y<model.skinheight ; y++)
  843. {
  844. memcpy (cropped+y*model.skinwidth,
  845. pixels+y*width, model.skinwidth);
  846. }
  847. // save off the new image
  848. printf ("saving %s\n", savename);
  849. CreatePath (savename);
  850. WritePCXfile (savename, cropped, model.skinwidth,
  851. model.skinheight, palette);
  852. free (pixels);
  853. free (palette);
  854. free (cropped);
  855. }
  856. /*
  857. =================
  858. Cmd_Origin
  859. =================
  860. */
  861. void Cmd_Origin (void)
  862. {
  863. // rotate points into frame of reference so model points down the
  864. // positive x axis
  865. GetToken (false);
  866. adjust[1] = -atof (token);
  867. GetToken (false);
  868. adjust[0] = atof (token);
  869. GetToken (false);
  870. adjust[2] = -atof (token);
  871. }
  872. /*
  873. =================
  874. Cmd_ScaleUp
  875. =================
  876. */
  877. void Cmd_ScaleUp (void)
  878. {
  879. GetToken (false);
  880. scale_up = atof (token);
  881. if (g_skipmodel || g_release || g_archive)
  882. return;
  883. printf ("Scale up: %f\n", scale_up);
  884. }
  885. /*
  886. =================
  887. Cmd_Skinsize
  888. Set a skin size other than the default
  889. =================
  890. */
  891. void Cmd_Skinsize (void)
  892. {
  893. GetToken (false);
  894. g_fixedwidth = atoi(token);
  895. GetToken (false);
  896. g_fixedheight = atoi(token);
  897. }
  898. /*
  899. =================
  900. Cmd_Modelname
  901. Gives a different name/location for the file, instead of the cddir
  902. =================
  903. */
  904. void Cmd_Modelname (void)
  905. {
  906. GetToken (false);
  907. strcpy (modelname, token);
  908. }
  909. /*
  910. ===============
  911. Cmd_Cd
  912. ===============
  913. */
  914. void Cmd_Cd (void)
  915. {
  916. FinishModel ();
  917. ClearModel ();
  918. GetToken (false);
  919. // this is a silly mess...
  920. sprintf (cdpartial, "models/%s", token);
  921. sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token);
  922. sprintf (cddir, "%s%s", gamedir, cdpartial);
  923. // if -only was specified and this cd doesn't match,
  924. // skip the model (you only need to match leading chars,
  925. // so you could regrab all monsters with -only monsters)
  926. if (!g_only[0])
  927. return;
  928. if (strncmp(token, g_only, strlen(g_only)))
  929. {
  930. g_skipmodel = true;
  931. printf ("skipping %s\n", cdpartial);
  932. }
  933. }