123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // r_aclip.c: clip routines for drawing Alias models directly to the screen
- #include "quakedef.h"
- #include "r_local.h"
- #include "d_local.h"
- static finalvert_t fv[2][8];
- static auxvert_t av[8];
- void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
- void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
- void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
- void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
- void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
- /*
- ================
- R_Alias_clip_z
- pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
- ================
- */
- void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
- {
- float scale;
- auxvert_t *pav0, *pav1, avout;
- pav0 = &av[pfv0 - &fv[0][0]];
- pav1 = &av[pfv1 - &fv[0][0]];
- if (pfv0->v[1] >= pfv1->v[1])
- {
- scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
- (pav1->fv[2] - pav0->fv[2]);
-
- avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
- avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
- avout.fv[2] = ALIAS_Z_CLIP_PLANE;
-
- out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
- out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
- out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
- }
- else
- {
- scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
- (pav0->fv[2] - pav1->fv[2]);
-
- avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
- avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
- avout.fv[2] = ALIAS_Z_CLIP_PLANE;
-
- out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
- out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
- out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
- }
- R_AliasProjectFinalVert (out, &avout);
- if (out->v[0] < r_refdef.aliasvrect.x)
- out->flags |= ALIAS_LEFT_CLIP;
- if (out->v[1] < r_refdef.aliasvrect.y)
- out->flags |= ALIAS_TOP_CLIP;
- if (out->v[0] > r_refdef.aliasvrectright)
- out->flags |= ALIAS_RIGHT_CLIP;
- if (out->v[1] > r_refdef.aliasvrectbottom)
- out->flags |= ALIAS_BOTTOM_CLIP;
- }
- #if !id386
- void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
- {
- float scale;
- int i;
- if (pfv0->v[1] >= pfv1->v[1])
- {
- scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
- (pfv1->v[0] - pfv0->v[0]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
- (pfv0->v[0] - pfv1->v[0]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
- }
- }
- void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out)
- {
- float scale;
- int i;
- if (pfv0->v[1] >= pfv1->v[1])
- {
- scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
- (pfv1->v[0] - pfv0->v[0]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
- (pfv0->v[0] - pfv1->v[0]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
- }
- }
- void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
- {
- float scale;
- int i;
- if (pfv0->v[1] >= pfv1->v[1])
- {
- scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
- (pfv1->v[1] - pfv0->v[1]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
- (pfv0->v[1] - pfv1->v[1]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
- }
- }
- void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out)
- {
- float scale;
- int i;
- if (pfv0->v[1] >= pfv1->v[1])
- {
- scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
- (pfv1->v[1] - pfv0->v[1]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
- (pfv0->v[1] - pfv1->v[1]);
- for (i=0 ; i<6 ; i++)
- out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
- }
- }
- #endif
- int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
- void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
- {
- int i,j,k;
- int flags, oldflags;
-
- j = count-1;
- k = 0;
- for (i=0 ; i<count ; j = i, i++)
- {
- oldflags = in[j].flags & flag;
- flags = in[i].flags & flag;
- if (flags && oldflags)
- continue;
- if (oldflags ^ flags)
- {
- clip (&in[j], &in[i], &out[k]);
- out[k].flags = 0;
- if (out[k].v[0] < r_refdef.aliasvrect.x)
- out[k].flags |= ALIAS_LEFT_CLIP;
- if (out[k].v[1] < r_refdef.aliasvrect.y)
- out[k].flags |= ALIAS_TOP_CLIP;
- if (out[k].v[0] > r_refdef.aliasvrectright)
- out[k].flags |= ALIAS_RIGHT_CLIP;
- if (out[k].v[1] > r_refdef.aliasvrectbottom)
- out[k].flags |= ALIAS_BOTTOM_CLIP;
- k++;
- }
- if (!flags)
- {
- out[k] = in[i];
- k++;
- }
- }
-
- return k;
- }
- /*
- ================
- R_AliasClipTriangle
- ================
- */
- void R_AliasClipTriangle (mtriangle_t *ptri)
- {
- int i, k, pingpong;
- mtriangle_t mtri;
- unsigned clipflags;
- // copy vertexes and fix seam texture coordinates
- if (ptri->facesfront)
- {
- fv[0][0] = pfinalverts[ptri->vertindex[0]];
- fv[0][1] = pfinalverts[ptri->vertindex[1]];
- fv[0][2] = pfinalverts[ptri->vertindex[2]];
- }
- else
- {
- for (i=0 ; i<3 ; i++)
- {
- fv[0][i] = pfinalverts[ptri->vertindex[i]];
-
- if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
- fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
- }
- }
- // clip
- clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
- if (clipflags & ALIAS_Z_CLIP)
- {
- for (i=0 ; i<3 ; i++)
- av[i] = pauxverts[ptri->vertindex[i]];
- k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
- if (k == 0)
- return;
- pingpong = 1;
- clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
- }
- else
- {
- pingpong = 0;
- k = 3;
- }
- if (clipflags & ALIAS_LEFT_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
- if (k == 0)
- return;
- pingpong ^= 1;
- }
- if (clipflags & ALIAS_RIGHT_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
- if (k == 0)
- return;
- pingpong ^= 1;
- }
- if (clipflags & ALIAS_BOTTOM_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
- if (k == 0)
- return;
- pingpong ^= 1;
- }
- if (clipflags & ALIAS_TOP_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_TOP_CLIP, k, R_Alias_clip_top);
- if (k == 0)
- return;
- pingpong ^= 1;
- }
- for (i=0 ; i<k ; i++)
- {
- if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
- fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
- else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
- fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
- if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
- fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
- else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
- fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
- fv[pingpong][i].flags = 0;
- }
- // draw triangles
- mtri.facesfront = ptri->facesfront;
- r_affinetridesc.ptriangles = &mtri;
- r_affinetridesc.pfinalverts = fv[pingpong];
- // FIXME: do all at once as trifan?
- mtri.vertindex[0] = 0;
- for (i=1 ; i<k-1 ; i++)
- {
- mtri.vertindex[1] = i;
- mtri.vertindex[2] = i+1;
- D_PolysetDraw ();
- }
- }
|