summaryrefslogtreecommitdiff
path: root/source/sw_aclip.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/sw_aclip.c')
-rw-r--r--source/sw_aclip.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/source/sw_aclip.c b/source/sw_aclip.c
new file mode 100644
index 0000000..9622d14
--- /dev/null
+++ b/source/sw_aclip.c
@@ -0,0 +1,323 @@
+/*
+Copyright (C) 1997-2001 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 "sw_local.h"
+
+static finalvert_t fv[2][8];
+
+void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
+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;
+
+ scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
+ (pfv1->xyz[2] - pfv0->xyz[2]);
+
+ out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
+ out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
+ out->xyz[2] = ALIAS_Z_CLIP_PLANE;
+
+ out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
+ out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
+ out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
+
+ R_AliasProjectAndClipTestFinalVert (out);
+}
+
+
+#if !USE_ASM
+
+void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v )
+ {
+ scale = (float)(r_refdef.aliasvrect.x - pfv0->u) /
+ (pfv1->u - pfv0->u);
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrect.x - pfv1->u) /
+ (pfv0->u - pfv1->u);
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if ( pfv0->v >= pfv1->v )
+ {
+ scale = (float)(r_refdef.aliasvrectright - pfv0->u ) /
+ (pfv1->u - pfv0->u );
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrectright - pfv1->u ) /
+ (pfv0->u - pfv1->u );
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v)
+ {
+ scale = (float)(r_refdef.aliasvrect.y - pfv0->v) /
+ (pfv1->v - pfv0->v);
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrect.y - pfv1->v) /
+ (pfv0->v - pfv1->v);
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v)
+ {
+ scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) /
+ (pfv1->v - pfv0->v);
+
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) /
+ (pfv0->v - pfv1->v);
+
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * 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].u < r_refdef.aliasvrect.x)
+ out[k].flags |= ALIAS_LEFT_CLIP;
+ if (out[k].v < r_refdef.aliasvrect.y)
+ out[k].flags |= ALIAS_TOP_CLIP;
+ if (out[k].u > r_refdef.aliasvrectright)
+ out[k].flags |= ALIAS_RIGHT_CLIP;
+ if (out[k].v > r_refdef.aliasvrectbottom)
+ out[k].flags |= ALIAS_BOTTOM_CLIP;
+ k++;
+ }
+ if (!flags)
+ {
+ out[k] = in[i];
+ k++;
+ }
+ }
+
+ return k;
+}
+
+
+/*
+================
+R_AliasClipTriangle
+================
+*/
+void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
+{
+ int i, k, pingpong;
+ unsigned clipflags;
+
+// copy vertexes and fix seam texture coordinates
+ fv[0][0] = *index0;
+ fv[0][1] = *index1;
+ fv[0][2] = *index2;
+
+// clip
+ clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
+
+ if (clipflags & ALIAS_Z_CLIP)
+ {
+ 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].u < r_refdef.aliasvrect.x)
+ fv[pingpong][i].u = r_refdef.aliasvrect.x;
+ else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
+ fv[pingpong][i].u = r_refdef.aliasvrectright;
+
+ if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
+ fv[pingpong][i].v = r_refdef.aliasvrect.y;
+ else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
+ fv[pingpong][i].v = r_refdef.aliasvrectbottom;
+
+ fv[pingpong][i].flags = 0;
+ }
+
+// draw triangles
+ for (i=1 ; i<k-1 ; i++)
+ {
+ aliastriangleparms.a = &fv[pingpong][0];
+ aliastriangleparms.b = &fv[pingpong][i];
+ aliastriangleparms.c = &fv[pingpong][i+1];
+ R_DrawTriangle();
+ }
+}
+