gl_mesh.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // gl_mesh.c: triangle model functions
  16. #include "quakedef.h"
  17. /*
  18. =================================================================
  19. ALIAS MODEL DISPLAY LIST GENERATION
  20. =================================================================
  21. */
  22. model_t *aliasmodel;
  23. aliashdr_t *paliashdr;
  24. qboolean used[8192];
  25. // the command list holds counts and s/t values that are valid for
  26. // every frame
  27. int commands[8192];
  28. int numcommands;
  29. // all frames will have their vertexes rearranged and expanded
  30. // so they are in the order expected by the command list
  31. int vertexorder[8192];
  32. int numorder;
  33. int allverts, alltris;
  34. int stripverts[128];
  35. int striptris[128];
  36. int stripcount;
  37. /*
  38. ================
  39. StripLength
  40. ================
  41. */
  42. int StripLength (int starttri, int startv)
  43. {
  44. int m1, m2;
  45. int j;
  46. mtriangle_t *last, *check;
  47. int k;
  48. used[starttri] = 2;
  49. last = &triangles[starttri];
  50. stripverts[0] = last->vertindex[(startv)%3];
  51. stripverts[1] = last->vertindex[(startv+1)%3];
  52. stripverts[2] = last->vertindex[(startv+2)%3];
  53. striptris[0] = starttri;
  54. stripcount = 1;
  55. m1 = last->vertindex[(startv+2)%3];
  56. m2 = last->vertindex[(startv+1)%3];
  57. // look for a matching triangle
  58. nexttri:
  59. for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
  60. {
  61. if (check->facesfront != last->facesfront)
  62. continue;
  63. for (k=0 ; k<3 ; k++)
  64. {
  65. if (check->vertindex[k] != m1)
  66. continue;
  67. if (check->vertindex[ (k+1)%3 ] != m2)
  68. continue;
  69. // this is the next part of the fan
  70. // if we can't use this triangle, this tristrip is done
  71. if (used[j])
  72. goto done;
  73. // the new edge
  74. if (stripcount & 1)
  75. m2 = check->vertindex[ (k+2)%3 ];
  76. else
  77. m1 = check->vertindex[ (k+2)%3 ];
  78. stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
  79. striptris[stripcount] = j;
  80. stripcount++;
  81. used[j] = 2;
  82. goto nexttri;
  83. }
  84. }
  85. done:
  86. // clear the temp used flags
  87. for (j=starttri+1 ; j<pheader->numtris ; j++)
  88. if (used[j] == 2)
  89. used[j] = 0;
  90. return stripcount;
  91. }
  92. /*
  93. ===========
  94. FanLength
  95. ===========
  96. */
  97. int FanLength (int starttri, int startv)
  98. {
  99. int m1, m2;
  100. int j;
  101. mtriangle_t *last, *check;
  102. int k;
  103. used[starttri] = 2;
  104. last = &triangles[starttri];
  105. stripverts[0] = last->vertindex[(startv)%3];
  106. stripverts[1] = last->vertindex[(startv+1)%3];
  107. stripverts[2] = last->vertindex[(startv+2)%3];
  108. striptris[0] = starttri;
  109. stripcount = 1;
  110. m1 = last->vertindex[(startv+0)%3];
  111. m2 = last->vertindex[(startv+2)%3];
  112. // look for a matching triangle
  113. nexttri:
  114. for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
  115. {
  116. if (check->facesfront != last->facesfront)
  117. continue;
  118. for (k=0 ; k<3 ; k++)
  119. {
  120. if (check->vertindex[k] != m1)
  121. continue;
  122. if (check->vertindex[ (k+1)%3 ] != m2)
  123. continue;
  124. // this is the next part of the fan
  125. // if we can't use this triangle, this tristrip is done
  126. if (used[j])
  127. goto done;
  128. // the new edge
  129. m2 = check->vertindex[ (k+2)%3 ];
  130. stripverts[stripcount+2] = m2;
  131. striptris[stripcount] = j;
  132. stripcount++;
  133. used[j] = 2;
  134. goto nexttri;
  135. }
  136. }
  137. done:
  138. // clear the temp used flags
  139. for (j=starttri+1 ; j<pheader->numtris ; j++)
  140. if (used[j] == 2)
  141. used[j] = 0;
  142. return stripcount;
  143. }
  144. /*
  145. ================
  146. BuildTris
  147. Generate a list of trifans or strips
  148. for the model, which holds for all frames
  149. ================
  150. */
  151. void BuildTris (void)
  152. {
  153. int i, j, k;
  154. int startv;
  155. mtriangle_t *last, *check;
  156. int m1, m2;
  157. int striplength;
  158. trivertx_t *v;
  159. mtriangle_t *tv;
  160. float s, t;
  161. int index;
  162. int len, bestlen, besttype;
  163. int bestverts[1024];
  164. int besttris[1024];
  165. int type;
  166. //
  167. // build tristrips
  168. //
  169. numorder = 0;
  170. numcommands = 0;
  171. memset (used, 0, sizeof(used));
  172. for (i=0 ; i<pheader->numtris ; i++)
  173. {
  174. // pick an unused triangle and start the trifan
  175. if (used[i])
  176. continue;
  177. bestlen = 0;
  178. for (type = 0 ; type < 2 ; type++)
  179. // type = 1;
  180. {
  181. for (startv =0 ; startv < 3 ; startv++)
  182. {
  183. if (type == 1)
  184. len = StripLength (i, startv);
  185. else
  186. len = FanLength (i, startv);
  187. if (len > bestlen)
  188. {
  189. besttype = type;
  190. bestlen = len;
  191. for (j=0 ; j<bestlen+2 ; j++)
  192. bestverts[j] = stripverts[j];
  193. for (j=0 ; j<bestlen ; j++)
  194. besttris[j] = striptris[j];
  195. }
  196. }
  197. }
  198. // mark the tris on the best strip as used
  199. for (j=0 ; j<bestlen ; j++)
  200. used[besttris[j]] = 1;
  201. if (besttype == 1)
  202. commands[numcommands++] = (bestlen+2);
  203. else
  204. commands[numcommands++] = -(bestlen+2);
  205. for (j=0 ; j<bestlen+2 ; j++)
  206. {
  207. // emit a vertex into the reorder buffer
  208. k = bestverts[j];
  209. vertexorder[numorder++] = k;
  210. // emit s/t coords into the commands stream
  211. s = stverts[k].s;
  212. t = stverts[k].t;
  213. if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
  214. s += pheader->skinwidth / 2; // on back side
  215. s = (s + 0.5) / pheader->skinwidth;
  216. t = (t + 0.5) / pheader->skinheight;
  217. *(float *)&commands[numcommands++] = s;
  218. *(float *)&commands[numcommands++] = t;
  219. }
  220. }
  221. commands[numcommands++] = 0; // end of list marker
  222. Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
  223. allverts += numorder;
  224. alltris += pheader->numtris;
  225. }
  226. /*
  227. ================
  228. GL_MakeAliasModelDisplayLists
  229. ================
  230. */
  231. void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
  232. {
  233. int i, j;
  234. maliasgroup_t *paliasgroup;
  235. int *cmds;
  236. trivertx_t *verts;
  237. char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c;
  238. FILE *f;
  239. int len;
  240. byte *data;
  241. aliasmodel = m;
  242. paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m);
  243. //
  244. // look for a cached version
  245. //
  246. strcpy (cache, "glquake/");
  247. COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
  248. strcat (cache, ".ms2");
  249. COM_FOpenFile (cache, &f);
  250. if (f)
  251. {
  252. fread (&numcommands, 4, 1, f);
  253. fread (&numorder, 4, 1, f);
  254. fread (&commands, numcommands * sizeof(commands[0]), 1, f);
  255. fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  256. fclose (f);
  257. }
  258. else
  259. {
  260. //
  261. // build it from scratch
  262. //
  263. Con_Printf ("meshing %s...\n",m->name);
  264. BuildTris (); // trifans or lists
  265. //
  266. // save out the cached version
  267. //
  268. sprintf (fullpath, "%s/%s", com_gamedir, cache);
  269. f = fopen (fullpath, "wb");
  270. if (f)
  271. {
  272. fwrite (&numcommands, 4, 1, f);
  273. fwrite (&numorder, 4, 1, f);
  274. fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
  275. fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  276. fclose (f);
  277. }
  278. }
  279. // save the data out
  280. paliashdr->poseverts = numorder;
  281. cmds = Hunk_Alloc (numcommands * 4);
  282. paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
  283. memcpy (cmds, commands, numcommands * 4);
  284. verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts
  285. * sizeof(trivertx_t) );
  286. paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
  287. for (i=0 ; i<paliashdr->numposes ; i++)
  288. for (j=0 ; j<numorder ; j++)
  289. *verts++ = poseverts[i][vertexorder[j]];
  290. }