Home | History | Annotate | Download | only in WinQuake
      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