home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / gl_mesh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  7.8 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.