Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.