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 */
R_Alias_clip_z(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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
R_Alias_clip_left(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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
R_Alias_clip_right(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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
R_Alias_clip_top(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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
R_Alias_clip_bottom(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)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
R_AliasClip(finalvert_t * in,finalvert_t * out,int flag,int count,void (* clip)(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out))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 */
R_AliasClipTriangle(mtriangle_t * ptri)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