1 /*
2 r_aclip.c
3
4 clip routines for drawing Alias models directly to the screen
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include "QF/render.h"
32
33 #include "d_local.h"
34 #include "r_internal.h"
35
36 #ifdef PIC
37 # undef USE_INTEL_ASM //XXX asm pic hack
38 #endif
39
40 static finalvert_t fv[2][8];
41 static auxvert_t av[8];
42
43 /*
44 R_Alias_clip_z
45
46 pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
47 */
48 static void
R_Alias_clip_z(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)49 R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
50 {
51 float scale;
52 auxvert_t *pav0, *pav1, avout;
53
54 pav0 = &av[pfv0 - &fv[0][0]];
55 pav1 = &av[pfv1 - &fv[0][0]];
56
57 if (pfv0->v[1] >= pfv1->v[1]) {
58 scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
59 (pav1->fv[2] - pav0->fv[2]);
60
61 avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
62 avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
63 avout.fv[2] = ALIAS_Z_CLIP_PLANE;
64
65 out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
66 out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
67 out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
68 } else {
69 scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
70 (pav0->fv[2] - pav1->fv[2]);
71
72 avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
73 avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
74 avout.fv[2] = ALIAS_Z_CLIP_PLANE;
75
76 out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
77 out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
78 out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
79 }
80
81 R_AliasProjectFinalVert (out, &avout);
82
83 if (out->v[0] < r_refdef.aliasvrect.x)
84 out->flags |= ALIAS_LEFT_CLIP;
85 if (out->v[1] < r_refdef.aliasvrect.y)
86 out->flags |= ALIAS_TOP_CLIP;
87 if (out->v[0] > r_refdef.aliasvrectright)
88 out->flags |= ALIAS_RIGHT_CLIP;
89 if (out->v[1] > r_refdef.aliasvrectbottom)
90 out->flags |= ALIAS_BOTTOM_CLIP;
91 }
92
93 #ifndef USE_INTEL_ASM
94
95 void
R_Alias_clip_left(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)96 R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
97 {
98 float scale;
99 int i;
100
101 if (pfv0->v[1] >= pfv1->v[1]) {
102 scale = (float) (r_refdef.aliasvrect.x - pfv0->v[0]) /
103 (pfv1->v[0] - pfv0->v[0]);
104 for (i = 0; i < 6; i++)
105 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
106 } else {
107 scale = (float) (r_refdef.aliasvrect.x - pfv1->v[0]) /
108 (pfv0->v[0] - pfv1->v[0]);
109 for (i = 0; i < 6; i++)
110 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
111 }
112 }
113
114
115 void
R_Alias_clip_right(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)116 R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
117 {
118 float scale;
119 int i;
120
121 if (pfv0->v[1] >= pfv1->v[1]) {
122 scale = (float) (r_refdef.aliasvrectright - pfv0->v[0]) /
123 (pfv1->v[0] - pfv0->v[0]);
124 for (i = 0; i < 6; i++)
125 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
126 } else {
127 scale = (float) (r_refdef.aliasvrectright - pfv1->v[0]) /
128 (pfv0->v[0] - pfv1->v[0]);
129 for (i = 0; i < 6; i++)
130 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
131 }
132 }
133
134
135 void
R_Alias_clip_top(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)136 R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
137 {
138 float scale;
139 int i;
140
141 if (pfv0->v[1] >= pfv1->v[1]) {
142 scale = (float) (r_refdef.aliasvrect.y - pfv0->v[1]) /
143 (pfv1->v[1] - pfv0->v[1]);
144 for (i = 0; i < 6; i++)
145 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
146 } else {
147 scale = (float) (r_refdef.aliasvrect.y - pfv1->v[1]) /
148 (pfv0->v[1] - pfv1->v[1]);
149 for (i = 0; i < 6; i++)
150 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
151 }
152 }
153
154
155 void
R_Alias_clip_bottom(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out)156 R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
157 {
158 float scale;
159 int i;
160
161 if (pfv0->v[1] >= pfv1->v[1]) {
162 scale = (float) (r_refdef.aliasvrectbottom - pfv0->v[1]) /
163 (pfv1->v[1] - pfv0->v[1]);
164
165 for (i = 0; i < 6; i++)
166 out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5;
167 } else {
168 scale = (float) (r_refdef.aliasvrectbottom - pfv1->v[1]) /
169 (pfv0->v[1] - pfv1->v[1]);
170
171 for (i = 0; i < 6; i++)
172 out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5;
173 }
174 }
175
176 #endif
177
178
179 static int
R_AliasClip(finalvert_t * in,finalvert_t * out,int flag,int count,void (* clip)(finalvert_t * pfv0,finalvert_t * pfv1,finalvert_t * out))180 R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
181 void (*clip) (finalvert_t *pfv0, finalvert_t *pfv1,
182 finalvert_t *out))
183 {
184 int i, j, k;
185 int flags, oldflags;
186
187 j = count - 1;
188 k = 0;
189 for (i = 0; i < count; j = i, i++) {
190 oldflags = in[j].flags & flag;
191 flags = in[i].flags & flag;
192
193 if (flags && oldflags)
194 continue;
195 if (oldflags ^ flags) {
196 clip (&in[j], &in[i], &out[k]);
197 out[k].flags = 0;
198 if (out[k].v[0] < r_refdef.aliasvrect.x)
199 out[k].flags |= ALIAS_LEFT_CLIP;
200 if (out[k].v[1] < r_refdef.aliasvrect.y)
201 out[k].flags |= ALIAS_TOP_CLIP;
202 if (out[k].v[0] > r_refdef.aliasvrectright)
203 out[k].flags |= ALIAS_RIGHT_CLIP;
204 if (out[k].v[1] > r_refdef.aliasvrectbottom)
205 out[k].flags |= ALIAS_BOTTOM_CLIP;
206 k++;
207 }
208 if (!flags) {
209 out[k] = in[i];
210 k++;
211 }
212 }
213
214 return k;
215 }
216
217
218 void
R_AliasClipTriangle(mtriangle_t * ptri)219 R_AliasClipTriangle (mtriangle_t *ptri)
220 {
221 int i, k, pingpong;
222 mtriangle_t mtri;
223 unsigned int clipflags;
224
225 // copy vertexes and fix seam texture coordinates
226 if (ptri->facesfront) {
227 fv[0][0] = pfinalverts[ptri->vertindex[0]];
228 fv[0][1] = pfinalverts[ptri->vertindex[1]];
229 fv[0][2] = pfinalverts[ptri->vertindex[2]];
230 } else {
231 for (i = 0; i < 3; i++) {
232 fv[0][i] = pfinalverts[ptri->vertindex[i]];
233
234 if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM))
235 fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
236 }
237 }
238
239 // clip
240 clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
241
242 if (clipflags & ALIAS_Z_CLIP) {
243 for (i = 0; i < 3; i++)
244 av[i] = pauxverts[ptri->vertindex[i]];
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 } else {
253 pingpong = 0;
254 k = 3;
255 }
256
257 if (clipflags & ALIAS_LEFT_CLIP) {
258 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
259 ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
260 if (k == 0)
261 return;
262
263 pingpong ^= 1;
264 }
265
266 if (clipflags & ALIAS_RIGHT_CLIP) {
267 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
268 ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
269 if (k == 0)
270 return;
271
272 pingpong ^= 1;
273 }
274
275 if (clipflags & ALIAS_BOTTOM_CLIP) {
276 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
277 ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
278 if (k == 0)
279 return;
280
281 pingpong ^= 1;
282 }
283
284 if (clipflags & ALIAS_TOP_CLIP) {
285 k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
286 ALIAS_TOP_CLIP, k, R_Alias_clip_top);
287 if (k == 0)
288 return;
289
290 pingpong ^= 1;
291 }
292
293 for (i = 0; i < k; i++) {
294 if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
295 fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
296 else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
297 fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
298
299 if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
300 fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
301 else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
302 fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
303
304 fv[pingpong][i].flags = 0;
305 }
306
307 // draw triangles
308 mtri.facesfront = ptri->facesfront;
309 r_affinetridesc.ptriangles = &mtri;
310 r_affinetridesc.pfinalverts = fv[pingpong];
311
312 // FIXME: do all at once as trifan?
313 mtri.vertindex[0] = 0;
314 for (i = 1; i < k - 1; i++) {
315 mtri.vertindex[1] = i;
316 mtri.vertindex[2] = i + 1;
317 D_PolysetDraw ();
318 }
319 }
320