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 "sw_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 */
R_Alias_clip_z(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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 
R_Alias_clip_left(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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 
R_Alias_clip_right(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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 
R_Alias_clip_top(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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 
R_Alias_clip_bottom(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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 
R_AliasClip(finalvert_t * in,finalvert_t * out,int flag,int count,void (* clip)(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out))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 */
R_AliasClipTriangle(finalvert_t * index0,finalvert_t * index1,finalvert_t * index2)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 
324