Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. // r_aclip.c: clip routines for drawing Alias models directly to the screen
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24. #include "d_local.h"
  25.  
  26. static finalvert_t              fv[2][8];
  27. static auxvert_t                av[8];
  28.  
  29. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
  30. void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
  31.         finalvert_t *out);
  32. void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
  33.         finalvert_t *out);
  34. void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
  35.         finalvert_t *out);
  36. void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
  37.         finalvert_t *out);
  38.  
  39.  
  40. /*
  41. ================
  42. R_Alias_clip_z
  43.  
  44. pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
  45. ================
  46. */
  47. void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
  48. {
  49.         float           scale;
  50.         auxvert_t       *pav0, *pav1, avout;
  51.  
  52.         pav0 = &av[pfv0 - &fv[0][0]];
  53.         pav1 = &av[pfv1 - &fv[0][0]];
  54.  
  55.         if (pfv0->v[1] >= pfv1->v[1])
  56.         {
  57.                 scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
  58.                                 (pav1->fv[2] - pav0->fv[2]);
  59.        
  60.                 avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
  61.                 avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
  62.                 avout.fv[2] = ALIAS_Z_CLIP_PLANE;
  63.        
  64.                 out->v[2] =     pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
  65.                 out->v[3] =     pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
  66.                 out->v[4] =     pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
  67.         }
  68.         else
  69.         {
  70.                 scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
  71.                                 (pav0->fv[2] - pav1->fv[2]);
  72.        
  73.                 avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
  74.                 avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
  75.                 avout.fv[2] = ALIAS_Z_CLIP_PLANE;
  76.        
  77.                 out->v[2] =     pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
  78.                 out->v[3] =     pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
  79.                 out->v[4] =     pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
  80.         }
  81.  
  82.         R_AliasProjectFinalVert (out, &avout);
  83.  
  84.         if (out->v[0] < r_refdef.aliasvrect.x)
  85.                 out->flags |= ALIAS_LEFT_CLIP;
  86.         if (out->v[1] < r_refdef.aliasvrect.y)
  87.                 out->flags |= ALIAS_TOP_CLIP;
  88.         if (out->v[0] > r_refdef.aliasvrectright)
  89.                 out->flags |= ALIAS_RIGHT_CLIP;
  90.         if (out->v[1] > r_refdef.aliasvrectbottom)
  91.                 out->flags |= ALIAS_BOTTOM_CLIP;       
  92. }
  93.  
  94.  
  95. #if     !id386
  96.  
  97. void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
  98. {
  99.         float           scale;
  100.         int                     i;
  101.  
  102.         if (pfv0->v[1] >= pfv1->v[1])
  103.         {
  104.                 scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
  105.                                 (pfv1->v[0] - pfv0->v[0]);
  106.                 for (i=0 ; i<6 ; i++)
  107.                         out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
  108.         }
  109.         else
  110.         {
  111.                 scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
  112.                                 (pfv0->v[0] - pfv1->v[0]);
  113.                 for (i=0 ; i<6 ; i++)
  114.                         out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
  115.         }
  116. }
  117.  
  118.  
  119. void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
  120.         finalvert_t *out)
  121. {
  122.         float           scale;
  123.         int                     i;
  124.  
  125.         if (pfv0->v[1] >= pfv1->v[1])
  126.         {
  127.                 scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
  128.                                 (pfv1->v[0] - pfv0->v[0]);
  129.                 for (i=0 ; i<6 ; i++)
  130.                         out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
  131.         }
  132.         else
  133.         {
  134.                 scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
  135.                                 (pfv0->v[0] - pfv1->v[0]);
  136.                 for (i=0 ; i<6 ; i++)
  137.                         out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
  138.         }
  139. }
  140.  
  141.  
  142. void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
  143. {
  144.         float           scale;
  145.         int                     i;
  146.  
  147.         if (pfv0->v[1] >= pfv1->v[1])
  148.         {
  149.                 scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
  150.                                 (pfv1->v[1] - pfv0->v[1]);
  151.                 for (i=0 ; i<6 ; i++)
  152.                         out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
  153.         }
  154.         else
  155.         {
  156.                 scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
  157.                                 (pfv0->v[1] - pfv1->v[1]);
  158.                 for (i=0 ; i<6 ; i++)
  159.                         out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
  160.         }
  161. }
  162.  
  163.  
  164. void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
  165.         finalvert_t *out)
  166. {
  167.         float           scale;
  168.         int                     i;
  169.  
  170.         if (pfv0->v[1] >= pfv1->v[1])
  171.         {
  172.                 scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
  173.                                 (pfv1->v[1] - pfv0->v[1]);
  174.  
  175.                 for (i=0 ; i<6 ; i++)
  176.                         out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
  177.         }
  178.         else
  179.         {
  180.                 scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
  181.                                 (pfv0->v[1] - pfv1->v[1]);
  182.  
  183.                 for (i=0 ; i<6 ; i++)
  184.                         out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
  185.         }
  186. }
  187.  
  188. #endif
  189.  
  190.  
  191. int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
  192.         void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
  193. {
  194.         int                     i,j,k;
  195.         int                     flags, oldflags;
  196.        
  197.         j = count-1;
  198.         k = 0;
  199.         for (i=0 ; i<count ; j = i, i++)
  200.         {
  201.                 oldflags = in[j].flags & flag;
  202.                 flags = in[i].flags & flag;
  203.  
  204.                 if (flags && oldflags)
  205.                         continue;
  206.                 if (oldflags ^ flags)
  207.                 {
  208.                         clip (&in[j], &in[i], &out[k]);
  209.                         out[k].flags = 0;
  210.                         if (out[k].v[0] < r_refdef.aliasvrect.x)
  211.                                 out[k].flags |= ALIAS_LEFT_CLIP;
  212.                         if (out[k].v[1] < r_refdef.aliasvrect.y)
  213.                                 out[k].flags |= ALIAS_TOP_CLIP;
  214.                         if (out[k].v[0] > r_refdef.aliasvrectright)
  215.                                 out[k].flags |= ALIAS_RIGHT_CLIP;
  216.                         if (out[k].v[1] > r_refdef.aliasvrectbottom)
  217.                                 out[k].flags |= ALIAS_BOTTOM_CLIP;     
  218.                         k++;
  219.                 }
  220.                 if (!flags)
  221.                 {
  222.                         out[k] = in[i];
  223.                         k++;
  224.                 }
  225.         }
  226.        
  227.         return k;
  228. }
  229.  
  230.  
  231. /*
  232. ================
  233. R_AliasClipTriangle
  234. ================
  235. */
  236. void R_AliasClipTriangle (mtriangle_t *ptri)
  237. {
  238.         int                             i, k, pingpong;
  239.         mtriangle_t             mtri;
  240.         unsigned                clipflags;
  241.  
  242. // copy vertexes and fix seam texture coordinates
  243.         if (ptri->facesfront)
  244.         {
  245.                 fv[0][0] = pfinalverts[ptri->vertindex[0]];
  246.                 fv[0][1] = pfinalverts[ptri->vertindex[1]];
  247.                 fv[0][2] = pfinalverts[ptri->vertindex[2]];
  248.         }
  249.         else
  250.         {
  251.                 for (i=0 ; i<3 ; i++)
  252.                 {
  253.                         fv[0][i] = pfinalverts[ptri->vertindex[i]];
  254.        
  255.                         if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
  256.                                 fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
  257.                 }
  258.         }
  259.  
  260. // clip
  261.         clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
  262.  
  263.         if (clipflags & ALIAS_Z_CLIP)
  264.         {
  265.                 for (i=0 ; i<3 ; i++)
  266.                         av[i] = pauxverts[ptri->vertindex[i]];
  267.  
  268.                 k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
  269.                 if (k == 0)
  270.                         return;
  271.  
  272.                 pingpong = 1;
  273.                 clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
  274.         }
  275.         else
  276.         {
  277.                 pingpong = 0;
  278.                 k = 3;
  279.         }
  280.  
  281.         if (clipflags & ALIAS_LEFT_CLIP)
  282.         {
  283.                 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
  284.                                                         ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
  285.                 if (k == 0)
  286.                         return;
  287.  
  288.                 pingpong ^= 1;
  289.         }
  290.  
  291.         if (clipflags & ALIAS_RIGHT_CLIP)
  292.         {
  293.                 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
  294.                                                         ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
  295.                 if (k == 0)
  296.                         return;
  297.  
  298.                 pingpong ^= 1;
  299.         }
  300.  
  301.         if (clipflags & ALIAS_BOTTOM_CLIP)
  302.         {
  303.                 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
  304.                                                         ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
  305.                 if (k == 0)
  306.                         return;
  307.  
  308.                 pingpong ^= 1;
  309.         }
  310.  
  311.         if (clipflags & ALIAS_TOP_CLIP)
  312.         {
  313.                 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
  314.                                                         ALIAS_TOP_CLIP, k, R_Alias_clip_top);
  315.                 if (k == 0)
  316.                         return;
  317.  
  318.                 pingpong ^= 1;
  319.         }
  320.  
  321.         for (i=0 ; i<k ; i++)
  322.         {
  323.                 if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
  324.                         fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
  325.                 else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
  326.                         fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
  327.  
  328.                 if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
  329.                         fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
  330.                 else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
  331.                         fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
  332.  
  333.                 fv[pingpong][i].flags = 0;
  334.         }
  335.  
  336. // draw triangles
  337.         mtri.facesfront = ptri->facesfront;
  338.         r_affinetridesc.ptriangles = &mtri;
  339.         r_affinetridesc.pfinalverts = fv[pingpong];
  340.  
  341. // FIXME: do all at once as trifan?
  342.         mtri.vertindex[0] = 0;
  343.         for (i=1 ; i<k-1 ; i++)
  344.         {
  345.                 mtri.vertindex[1] = i;
  346.                 mtri.vertindex[2] = i+1;
  347.                 D_PolysetDraw ();
  348.         }
  349. }
  350.  
  351.