Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_aclip.c (8958B)


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