gl_mesh.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. float s, t;
  156. int len, bestlen, besttype;
  157. int bestverts[1024];
  158. int besttris[1024];
  159. int type;
  160. //
  161. // build tristrips
  162. //
  163. numorder = 0;
  164. numcommands = 0;
  165. memset (used, 0, sizeof(used));
  166. for (i=0 ; i<pheader->numtris ; i++)
  167. {
  168. // pick an unused triangle and start the trifan
  169. if (used[i])
  170. continue;
  171. bestlen = 0;
  172. for (type = 0 ; type < 2 ; type++)
  173. // type = 1;
  174. {
  175. for (startv =0 ; startv < 3 ; startv++)
  176. {
  177. if (type == 1)
  178. len = StripLength (i, startv);
  179. else
  180. len = FanLength (i, startv);
  181. if (len > bestlen)
  182. {
  183. besttype = type;
  184. bestlen = len;
  185. for (j=0 ; j<bestlen+2 ; j++)
  186. bestverts[j] = stripverts[j];
  187. for (j=0 ; j<bestlen ; j++)
  188. besttris[j] = striptris[j];
  189. }
  190. }
  191. }
  192. // mark the tris on the best strip as used
  193. for (j=0 ; j<bestlen ; j++)
  194. used[besttris[j]] = 1;
  195. if (besttype == 1)
  196. commands[numcommands++] = (bestlen+2);
  197. else
  198. commands[numcommands++] = -(bestlen+2);
  199. for (j=0 ; j<bestlen+2 ; j++)
  200. {
  201. // emit a vertex into the reorder buffer
  202. k = bestverts[j];
  203. vertexorder[numorder++] = k;
  204. // emit s/t coords into the commands stream
  205. s = stverts[k].s;
  206. t = stverts[k].t;
  207. if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
  208. s += pheader->skinwidth / 2; // on back side
  209. s = (s + 0.5) / pheader->skinwidth;
  210. t = (t + 0.5) / pheader->skinheight;
  211. *(float *)&commands[numcommands++] = s;
  212. *(float *)&commands[numcommands++] = t;
  213. }
  214. }
  215. commands[numcommands++] = 0; // end of list marker
  216. Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
  217. allverts += numorder;
  218. alltris += pheader->numtris;
  219. }
  220. /*
  221. ================
  222. GL_MakeAliasModelDisplayLists
  223. ================
  224. */
  225. void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
  226. {
  227. int i, j;
  228. int *cmds;
  229. trivertx_t *verts;
  230. char cache[MAX_QPATH], fullpath[MAX_OSPATH];
  231. FILE *f;
  232. aliasmodel = m;
  233. paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m);
  234. //
  235. // look for a cached version
  236. //
  237. strcpy (cache, "glquake/");
  238. COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
  239. strcat (cache, ".ms2");
  240. COM_FOpenFile (cache, &f);
  241. if (f)
  242. {
  243. fread (&numcommands, 4, 1, f);
  244. fread (&numorder, 4, 1, f);
  245. fread (&commands, numcommands * sizeof(commands[0]), 1, f);
  246. fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  247. fclose (f);
  248. }
  249. else
  250. {
  251. //
  252. // build it from scratch
  253. //
  254. Con_Printf ("meshing %s...\n",m->name);
  255. BuildTris (); // trifans or lists
  256. //
  257. // save out the cached version
  258. //
  259. sprintf (fullpath, "%s/%s", com_gamedir, cache);
  260. f = fopen (fullpath, "wb");
  261. if (!f) {
  262. char gldir[MAX_OSPATH];
  263. sprintf (gldir, "%s/glquake", com_gamedir);
  264. Sys_mkdir (gldir);
  265. f = fopen (fullpath, "wb");
  266. }
  267. if (f)
  268. {
  269. fwrite (&numcommands, 4, 1, f);
  270. fwrite (&numorder, 4, 1, f);
  271. fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
  272. fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  273. fclose (f);
  274. }
  275. }
  276. // save the data out
  277. paliashdr->poseverts = numorder;
  278. cmds = Hunk_Alloc (numcommands * 4);
  279. paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
  280. memcpy (cmds, commands, numcommands * 4);
  281. verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts
  282. * sizeof(trivertx_t) );
  283. paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
  284. for (i=0 ; i<paliashdr->numposes ; i++)
  285. for (j=0 ; j<numorder ; j++)
  286. *verts++ = poseverts[i][vertexorder[j]];
  287. }