home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / gl_mesh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-28  |  8.0 KB  |  361 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.   mtriangle_t *last, *check;
  203.   int   m1, m2;
  204.   int   striplength;
  205.   trivertx_t  *v;
  206.   mtriangle_t *tv;
  207.   float s, t;
  208.   int   index;
  209.   int   len, bestlen, besttype;
  210.   int   bestverts[1024];
  211.   int   besttris[1024];
  212.   int   type;
  213.  
  214.   //
  215.   // build tristrips
  216.   //
  217.   numorder = 0;
  218.   numcommands = 0;
  219.   memset (used, 0, sizeof(used));
  220.   for (i=0 ; i<pheader->numtris ; i++)
  221.   {
  222.     // pick an unused triangle and start the trifan
  223.     if (used[i])
  224.       continue;
  225.  
  226.     bestlen = 0;
  227.     for (type = 0 ; type < 2 ; type++)
  228. //  type = 1;
  229.     {
  230.       for (startv =0 ; startv < 3 ; startv++)
  231.       {
  232.         if (type == 1)
  233.           len = StripLength (i, startv);
  234.         else
  235.           len = FanLength (i, startv);
  236.         if (len > bestlen)
  237.         {
  238.           besttype = type;
  239.           bestlen = len;
  240.           for (j=0 ; j<bestlen+2 ; j++)
  241.             bestverts[j] = stripverts[j];
  242.           for (j=0 ; j<bestlen ; j++)
  243.             besttris[j] = striptris[j];
  244.         }
  245.       }
  246.     }
  247.  
  248.     // mark the tris on the best strip as used
  249.     for (j=0 ; j<bestlen ; j++)
  250.       used[besttris[j]] = 1;
  251.  
  252.     if (besttype == 1)
  253.       commands[numcommands++] = (bestlen+2);
  254.     else
  255.       commands[numcommands++] = -(bestlen+2);
  256.  
  257.     for (j=0 ; j<bestlen+2 ; j++)
  258.     {
  259.       // emit a vertex into the reorder buffer
  260.       k = bestverts[j];
  261.       vertexorder[numorder++] = k;
  262.  
  263.       // emit s/t coords into the commands stream
  264.       s = stverts[k].s;
  265.       t = stverts[k].t;
  266.       if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
  267.         s += pheader->skinwidth / 2;  // on back side
  268.       s = (s + 0.5) / pheader->skinwidth;
  269.       t = (t + 0.5) / pheader->skinheight;
  270.  
  271.       *(float *)&commands[numcommands++] = s;
  272.       *(float *)&commands[numcommands++] = t;
  273.     }
  274.   }
  275.  
  276.   commands[numcommands++] = 0;    // end of list marker
  277.  
  278.   Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
  279.  
  280.   allverts += numorder;
  281.   alltris += pheader->numtris;
  282. }
  283.  
  284.  
  285. /*
  286. ================
  287. GL_MakeAliasModelDisplayLists
  288. ================
  289. */
  290. void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
  291. {
  292.   int   i, j;
  293.   maliasgroup_t *paliasgroup;
  294.   int     *cmds;
  295.   trivertx_t  *verts;
  296.   char  cache[MAX_QPATH], fullpath[MAX_OSPATH], *c;
  297.   FILE  *f;
  298.   int   len;
  299.   byte  *data;
  300.  
  301.   aliasmodel = m;
  302.   paliashdr = hdr;  // (aliashdr_t *)Mod_Extradata (m);
  303.  
  304.   //
  305.   // look for a cached version
  306.   //
  307.   strcpy (cache, "glquake/");
  308.   COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
  309.   strcat (cache, ".ms2");
  310.  
  311.   COM_FOpenFile (cache, &f);  
  312.   if (f)
  313.   {
  314.     fread (&numcommands, 4, 1, f);
  315.     fread (&numorder, 4, 1, f);
  316.     fread (&commands, numcommands * sizeof(commands[0]), 1, f);
  317.     fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  318.     fclose (f);
  319.   }
  320.   else
  321.   {
  322.     //
  323.     // build it from scratch
  324.     //
  325.     Con_Printf ("meshing %s...\n",m->name);
  326.  
  327.     BuildTris ();   // trifans or lists
  328.  
  329.     //
  330.     // save out the cached version
  331.     //
  332.     sprintf (fullpath, "%s/%s", com_gamedir, cache);
  333.     f = fopen (fullpath, "wb");
  334.     if (f)
  335.     {
  336.       fwrite (&numcommands, 4, 1, f);
  337.       fwrite (&numorder, 4, 1, f);
  338.       fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
  339.       fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  340.       fclose (f);
  341.     }
  342.   }
  343.  
  344.  
  345.   // save the data out
  346.  
  347.   paliashdr->poseverts = numorder;
  348.  
  349.   cmds = Hunk_Alloc (numcommands * 4);
  350.   paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
  351.   memcpy (cmds, commands, numcommands * 4);
  352.  
  353.   verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts 
  354.     * sizeof(trivertx_t) );
  355.   paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
  356.   for (i=0 ; i<paliashdr->numposes ; i++)
  357.     for (j=0 ; j<numorder ; j++)
  358.       *verts++ = poseverts[i][vertexorder[j]];
  359. }
  360.  
  361.