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