source: trunk/src/opengl/mesa/clip_funcs.h

Last change on this file was 3582, checked in by jeroen, 25 years ago

* empty log message *

File size: 16.0 KB
Line 
1/* $Id: clip_funcs.h,v 1.2 2000-05-21 20:15:38 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27/*
28 * New (3.1) transformation code written by Keith Whitwell.
29 */
30
31static GLuint TAG(userclip_line)( struct vertex_buffer *VB,
32 GLuint *i, GLuint *j );
33static GLuint TAG(userclip_polygon)( struct vertex_buffer *VB,
34 GLuint n, GLuint vlist[] );
35
36
37
38/* This now calls the user clip functions if required.
39 */
40static GLuint TAG(viewclip_line)( struct vertex_buffer *VB,
41 GLuint *i, GLuint *j,
42 GLubyte mask )
43{
44 GLfloat (*coord)[4] = VB->ClipPtr->data;
45 GLfloat t, dx, dy, dz, dw, neww;
46 GLuint ii = *i, jj = *j;
47 GLuint vlist[2];
48 GLuint n;
49 clip_interp_func interp = VB->ctx->ClipInterpFunc;
50 GLuint vb_free = VB->FirstFree;
51
52/*
53 * We use 6 instances of this code to clip agains the 6 planes.
54 * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
55 * macros apprpriately.
56 */
57#define GENERAL_CLIP \
58 if (mask & PLANE) { \
59 GLuint flagI = INSIDE( ii ); \
60 GLuint flagJ = INSIDE( jj ); \
61 \
62 if (!(flagI|flagJ)) \
63 return 0; \
64 \
65 if (flagI ^ flagJ) { \
66 COMPUTE_INTERSECTION( jj, ii, vb_free ); \
67 interp( VB, vb_free, t, jj, ii); \
68 \
69 if (flagI) { \
70 VB->ClipMask[jj] |= PLANE; \
71 jj = vb_free; \
72 } else { \
73 VB->ClipMask[ii] |= PLANE; \
74 ii = vb_free; \
75 } \
76 \
77 VB->ClipMask[vb_free++] = 0; \
78 } \
79 }
80
81#include "general_clip.h"
82
83 VB->Free = vb_free;
84
85 if (mask & CLIP_USER_BIT) {
86 if ( TAG(userclip_line)( VB, &ii, &jj ) == 0 )
87 return 0;
88 }
89
90 vlist[0] = ii;
91 vlist[1] = jj;
92 n = 2;
93
94 /* Should always be at least one new vertex.
95 */
96 {
97 const GLfloat *m = VB->ctx->Viewport.WindowMap.m;
98 GLfloat sx = m[MAT_SX];
99 GLfloat tx = m[MAT_TX];
100 GLfloat sy = m[MAT_SY];
101 GLfloat ty = m[MAT_TY];
102 GLfloat sz = m[MAT_SZ];
103 GLfloat tz = m[MAT_TZ];
104 GLuint i, j;
105 GLfloat (*win)[4] = VB->Win.data;
106 GLuint start = VB->FirstFree;
107
108 for (i = 0; i < n; i++) {
109 j = vlist[i];
110 if (j >= start) {
111 if (W(j) != 0.0F) {
112 GLfloat wInv = 1.0F / W(j);
113 win[j][0] = X(j) * wInv * sx + tx;
114 win[j][1] = Y(j) * wInv * sy + ty;
115 win[j][2] = Z(j) * wInv * sz + tz;
116 win[j][3] = wInv;
117 } else {
118 win[j][0] = win[j][1] = win[j][2] = 0.0F;
119 win[j][3] = 1.0F;
120 }
121 }
122 }
123 }
124
125 if (VB->ctx->Driver.RasterSetup)
126 VB->ctx->Driver.RasterSetup(VB, VB->FirstFree, VB->Free);
127
128 *i = ii;
129 *j = jj;
130 return 1;
131}
132
133/* We now clip polygon triangles individually. This is necessary to
134 * avoid artifacts dependent on where the boundary of the VB falls
135 * within the polygon. As a result, there is an upper bound on the
136 * number of vertices which may be created, and the test against VB_SIZE
137 * is redundant.
138 */
139static GLuint TAG(viewclip_polygon)( struct vertex_buffer *VB,
140 GLuint n, GLuint vlist[],
141 GLubyte mask )
142{
143 GLfloat (*coord)[4] = VB->ClipPtr->data;
144 GLuint vlist2[VB_SIZE-VB_MAX];
145 GLuint *inlist = vlist, *outlist = vlist2;
146 GLdouble dx, dy, dz, dw, t = 0, neww;
147 GLuint i;
148 GLuint vb_free = VB->FirstFree;
149 clip_interp_func interp = VB->ctx->ClipInterpFunc;
150
151 if (mask & CLIP_ALL_BITS) {
152
153#define GENERAL_CLIP \
154 if (mask & PLANE) { \
155 GLuint prevj = inlist[0]; \
156 GLuint prevflag = INSIDE(prevj); \
157 GLuint outcount = 0; \
158 GLuint i; \
159 \
160 inlist[n] = inlist[0]; \
161 \
162 for (i = 1; i < n+1; i++) { \
163 GLuint j = inlist[i]; \
164 GLuint flag = INSIDE(j); \
165 \
166 if (prevflag) { \
167 outlist[outcount++] = prevj; \
168 } else { \
169 VB->ClipMask[prevj] |= (PLANE&CLIP_ALL_BITS); \
170 } \
171 \
172 if (flag ^ prevflag) { \
173 if (flag) { \
174 /* Coming back in \
175 */ \
176 COMPUTE_INTERSECTION( j, prevj, vb_free ); \
177 interp( VB, vb_free, t, j, prevj ); \
178 \
179 if (IND&CLIP_TAB_EDGEFLAG) \
180 VB->EdgeFlagPtr->data[vb_free] = \
181 VB->EdgeFlagPtr->data[prevj]; \
182 \
183 \
184 } else { \
185 /* Going out of bounds \
186 */ \
187 COMPUTE_INTERSECTION( prevj, j, vb_free ); \
188 interp( VB, vb_free, t, prevj, j ); \
189 \
190 if (IND&CLIP_TAB_EDGEFLAG) { \
191 VB->EdgeFlagPtr->data[vb_free] = 3; \
192 } \
193 } \
194 \
195 if (IND&CLIP_TAB_EDGEFLAG) { \
196 /* Demote trailing edge to internal edge. \
197 */ \
198 if (outcount && \
199 (VB->EdgeFlagPtr->data[outlist[outcount-1]] & 0x2)) \
200 VB->EdgeFlagPtr->data[outlist[outcount-1]] = 1; \
201 } \
202 \
203 outlist[outcount++] = vb_free; \
204 VB->ClipMask[vb_free++] = 0; \
205 } \
206 \
207 prevj = j; \
208 prevflag = flag; \
209 } \
210 \
211 if (outcount < 3) \
212 return 0; \
213 else { \
214 GLuint *tmp = inlist; \
215 inlist = outlist; \
216 outlist = tmp; \
217 n = outcount; \
218 } \
219 }
220
221
222#include "general_clip.h"
223
224 if (inlist != vlist)
225 for (i = 0 ; i < n ; i++)
226 vlist[i] = inlist[i];
227 }
228
229 VB->Free = vb_free;
230
231 /* Clip against user clipping planes in clip space.
232 */
233 if (mask & CLIP_USER_BIT) {
234 n = TAG(userclip_polygon)( VB, n, vlist );
235 if (n < 3) return 0;
236 }
237
238
239 {
240 const GLfloat *m = VB->ctx->Viewport.WindowMap.m;
241 GLfloat sx = m[MAT_SX];
242 GLfloat tx = m[MAT_TX];
243 GLfloat sy = m[MAT_SY];
244 GLfloat ty = m[MAT_TY];
245 GLfloat sz = m[MAT_SZ];
246 GLfloat tz = m[MAT_TZ];
247 GLuint i;
248 GLfloat (*win)[4] = VB->Win.data;
249 GLuint first = VB->FirstFree;
250
251 for (i = 0; i < n; i++) {
252 GLuint j = vlist[i];
253 if (j >= first) {
254 if (W(j) != 0.0F) {
255 GLfloat wInv = 1.0F / W(j);
256 win[j][0] = X(j) * wInv * sx + tx;
257 win[j][1] = Y(j) * wInv * sy + ty;
258 win[j][2] = Z(j) * wInv * sz + tz;
259 win[j][3] = wInv;
260 } else {
261 win[j][0] = win[j][1] = win[j][2] = 0.0;
262 win[j][3] = 1.0F;
263 }
264 }
265 }
266 }
267
268 if (VB->ctx->Driver.RasterSetup)
269 VB->ctx->Driver.RasterSetup(VB, VB->FirstFree, VB->Free);
270
271 return n;
272}
273
274
275#define INSIDE( J ) !NEGATIVE(J)
276#define OUTSIDE( J ) NEGATIVE(J)
277
278
279
280
281static GLuint TAG(userclip_line)( struct vertex_buffer *VB,
282 GLuint *i, GLuint *j )
283{
284 GLcontext *ctx = VB->ctx;
285 GLfloat (*coord)[4] = VB->ClipPtr->data;
286 clip_interp_func interp = ctx->ClipInterpFunc;
287 GLuint ii = *i;
288 GLuint jj = *j;
289 GLuint p;
290 GLuint vb_free = VB->Free;
291
292 for (p=0;p<MAX_CLIP_PLANES;p++) {
293 if (ctx->Transform.ClipEnabled[p]) {
294 GLfloat a = ctx->Transform.ClipUserPlane[p][0];
295 GLfloat b = ctx->Transform.ClipUserPlane[p][1];
296 GLfloat c = ctx->Transform.ClipUserPlane[p][2];
297 GLfloat d = ctx->Transform.ClipUserPlane[p][3];
298
299 GLfloat dpI = d*W(ii) + c*Z(ii) + b*Y(ii) + a*X(ii);
300 GLfloat dpJ = d*W(jj) + c*Z(jj) + b*Y(jj) + a*X(jj);
301
302 GLuint flagI = OUTSIDE( dpI );
303 GLuint flagJ = OUTSIDE( dpJ );
304
305 if (flagI & flagJ)
306 return 0;
307
308 if (flagI ^ flagJ) {
309 GLfloat t = -dpI/(dpJ-dpI);
310
311 INTERP_SZ( t, coord, vb_free, ii, jj, SIZE );
312 interp( VB, vb_free, t, ii, jj );
313
314 if (flagI) {
315 VB->ClipMask[ii] |= CLIP_USER_BIT;
316 ii = vb_free;
317 } else {
318 VB->ClipMask[jj] |= CLIP_USER_BIT;
319 jj = vb_free;
320 }
321
322 VB->ClipMask[vb_free++] = 0;
323 }
324 }
325 }
326
327 VB->Free = vb_free;
328 *i = ii;
329 *j = jj;
330 return 1;
331}
332
333
334static GLuint TAG(userclip_polygon)( struct vertex_buffer *VB,
335 GLuint n, GLuint vlist[] )
336{
337 GLcontext *ctx = VB->ctx;
338 GLfloat (*coord)[4] = VB->ClipPtr->data;
339 clip_interp_func interp = ctx->ClipInterpFunc;
340 GLuint vlist2[VB_SIZE];
341 GLuint *inlist = vlist, *outlist = vlist2;
342 GLuint vb_free = VB->Free;
343 GLuint p;
344
345 for (p=0;p<MAX_CLIP_PLANES;p++) {
346 if (ctx->Transform.ClipEnabled[p]) {
347 register float a = ctx->Transform.ClipUserPlane[p][0];
348 register float b = ctx->Transform.ClipUserPlane[p][1];
349 register float c = ctx->Transform.ClipUserPlane[p][2];
350 register float d = ctx->Transform.ClipUserPlane[p][3];
351
352 /* initialize prev to be last in the input list */
353 GLuint prevj = inlist[0];
354 GLfloat dpJ = d*W(prevj) + c*Z(prevj) + b*Y(prevj) + a*X(prevj);
355 GLuint flagJ = INSIDE(dpJ);
356 GLuint outcount = 0;
357 GLuint curri;
358
359 inlist[n] = inlist[0];
360
361
362 for (curri=1;curri<n+1;curri++) {
363 GLuint currj = inlist[curri];
364 GLfloat dpI = d*W(currj) + c*Z(currj) + b*Y(currj) + a*X(currj);
365 GLuint flagI = INSIDE(dpI);
366
367 if (flagJ) {
368 outlist[outcount++] = prevj;
369 } else {
370 VB->ClipMask[prevj] |= CLIP_USER_BIT;
371 }
372
373 if (flagI ^ flagJ) {
374 GLfloat t;
375 GLuint in;
376 GLuint out;
377
378 if (flagI) {
379 out = prevj;
380 in = currj;
381 t = dpI/(dpI-dpJ);
382
383 if (IND&CLIP_TAB_EDGEFLAG)
384 VB->EdgeFlagPtr->data[vb_free] =
385 VB->EdgeFlagPtr->data[prevj];
386 } else {
387 in = prevj;
388 out = currj;
389 t = dpJ/(dpJ-dpI);
390
391 if (IND&CLIP_TAB_EDGEFLAG)
392 VB->EdgeFlagPtr->data[vb_free] = 1;
393 }
394
395 if (IND&CLIP_TAB_EDGEFLAG) {
396 /* Demote trailing edge to internal edge.
397 */
398 if (outcount &&
399 (VB->EdgeFlagPtr->data[outlist[outcount-1]] & 0x2))
400 VB->EdgeFlagPtr->data[outlist[outcount-1]] = 1;
401 }
402
403 INTERP_SZ( t, coord, vb_free, in, out, SIZE );
404 interp( VB, vb_free, t, in, out);
405 outlist[outcount++] = vb_free;
406 VB->ClipMask[vb_free++] = 0;
407 }
408
409 prevj = currj;
410 flagJ = flagI;
411 dpJ = dpI;
412 }
413
414 if (outcount < 3)
415 return 0;
416 else {
417 GLuint *tmp;
418 tmp = inlist;
419 inlist = outlist;
420 outlist = tmp;
421 n = outcount;
422 }
423
424 } /* if */
425 } /* for p */
426
427 if (inlist!=vlist) {
428 GLuint i;
429 for (i = 0 ; i < n ; i++)
430 vlist[i] = inlist[i];
431 }
432
433 VB->Free = vb_free;
434 return n;
435}
436
437
438static void TAG(init_clip_funcs)(void)
439{
440 gl_poly_clip_tab[IND][SIZE] = TAG(viewclip_polygon);
441 gl_line_clip_tab[IND][SIZE] = TAG(viewclip_line);
442}
443
444#undef W
445#undef Z
446#undef Y
447#undef X
448#undef SIZE
449#undef TAG
450#undef INSIDE
451#undef OUTSIDE
452#undef IND
Note: See TracBrowser for help on using the repository browser.