home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / gl_mesh.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  8.0 KB  |  360 lines

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