source: trunk/src/opengl/mesa/clip.c@ 2963

Last change on this file since 2963 was 2962, checked in by jeroen, 25 years ago

* empty log message *

File size: 13.5 KB
Line 
1/* $Id: clip.c,v 1.2 2000-03-01 18:49:24 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
29
30
31#ifdef PC_HEADER
32#include "all.h"
33#else
34#ifndef XFree86Server
35#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38#else
39#include "GL/xf86glx.h"
40#endif
41#include "clip.h"
42#include "types.h"
43#include "context.h"
44#include "macros.h"
45#include "matrix.h"
46#include "mmath.h"
47#include "vb.h"
48#include "xform.h"
49#endif
50
51
52
53
54#define CLIP_RGBA0 0x1
55#define CLIP_RGBA1 0x2
56#define CLIP_TEX0 0x4
57#define CLIP_TEX1 0x8
58#define CLIP_INDEX0 0x10
59#define CLIP_INDEX1 0x20
60#define CLIP_FOG_COORD 0x40
61
62
63/* Linear interpolation between A and B: */
64#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
65
66
67
68#define INTERP_SZ( t, vec, to, a, b, sz ) \
69do { \
70 switch (sz) { \
71 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
72 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
73 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
74 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
75 } \
76} while(0)
77
78
79static clip_interp_func clip_interp_tab[0x80];
80
81#define IND 0
82#define NAME clip_nil
83#include "interp_tmp.h"
84
85#define IND (CLIP_RGBA0)
86#define NAME clipRGBA0
87#include "interp_tmp.h"
88
89#define IND (CLIP_RGBA0|CLIP_RGBA1)
90#define NAME clipRGBA0_RGBA1
91#include "interp_tmp.h"
92
93#define IND (CLIP_TEX0|CLIP_RGBA0)
94#define NAME clipTEX0_RGBA0
95#include "interp_tmp.h"
96
97#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
98#define NAME clipTEX0_RGBA0_RGBA1
99#include "interp_tmp.h"
100
101#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
102#define NAME clipTEX1_TEX0_RGBA0
103#include "interp_tmp.h"
104
105#define IND (CLIP_TEX0)
106#define NAME clipTEX0
107#include "interp_tmp.h"
108
109#define IND (CLIP_TEX1|CLIP_TEX0)
110#define NAME clipTEX1_TEX0
111#include "interp_tmp.h"
112
113#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
114#define NAME clipTEX1_TEX0_RGBA0_RGBA1
115#include "interp_tmp.h"
116
117#define IND (CLIP_INDEX0)
118#define NAME clipINDEX0
119#include "interp_tmp.h"
120
121#define IND (CLIP_INDEX0|CLIP_INDEX1)
122#define NAME clipINDEX0_INDEX1
123#include "interp_tmp.h"
124
125#define IND (CLIP_FOG_COORD)
126#define NAME clip_FOG
127#include "interp_tmp.h"
128
129#define IND (CLIP_RGBA0|CLIP_FOG_COORD)
130#define NAME clipRGBA0_FOG
131#include "interp_tmp.h"
132
133#define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
134#define NAME clipRGBA0_RGBA1_FOG
135#include "interp_tmp.h"
136
137#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
138#define NAME clipTEX0_RGBA0_FOG
139#include "interp_tmp.h"
140
141#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
142#define NAME clipTEX0_RGBA0_RGBA1_FOG
143#include "interp_tmp.h"
144
145#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
146#define NAME clipTEX1_TEX0_RGBA0_FOG
147#include "interp_tmp.h"
148
149#define IND (CLIP_TEX0|CLIP_FOG_COORD)
150#define NAME clipTEX0_FOG
151#include "interp_tmp.h"
152
153#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD)
154#define NAME clipTEX1_TEX0_FOG
155#include "interp_tmp.h"
156
157#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
158#define NAME clipTEX1_TEX0_RGBA0_RGBA1_FOG
159#include "interp_tmp.h"
160
161#define IND (CLIP_INDEX0|CLIP_FOG_COORD)
162#define NAME clipINDEX0_FOG
163#include "interp_tmp.h"
164
165#define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD)
166#define NAME clipINDEX0_INDEX1_FOG
167#include "interp_tmp.h"
168
169
170
171
172/**********************************************************************/
173/* Get/Set User clip-planes. */
174/**********************************************************************/
175
176
177
178void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation )
179{
180 GLint p;
181
182 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClipPlane");
183
184 p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
185 if (p<0 || p>=MAX_CLIP_PLANES) {
186 gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" );
187 return;
188 }
189
190 /*
191 * The equation is transformed by the transpose of the inverse of the
192 * current modelview matrix and stored in the resulting eye coordinates.
193 *
194 * KW: Eqn is then transformed to the current clip space, where user
195 * clipping now takes place. The clip-space equations are recalculated
196 * whenever the projection matrix changes.
197 */
198 if (ctx->ModelView.flags & MAT_DIRTY_ALL_OVER) {
199 gl_matrix_analyze( &ctx->ModelView );
200 }
201 gl_transform_vector( ctx->Transform.EyeUserPlane[p], equation,
202 ctx->ModelView.inv );
203
204
205 if (ctx->Transform.ClipEnabled[p]) {
206 ctx->NewState |= NEW_USER_CLIP;
207
208 if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) {
209 gl_matrix_analyze( &ctx->ProjectionMatrix );
210 }
211 gl_transform_vector( ctx->Transform.ClipUserPlane[p],
212 ctx->Transform.EyeUserPlane[p],
213 ctx->ProjectionMatrix.inv );
214 }
215}
216
217
218void gl_update_userclip( GLcontext *ctx )
219{
220 GLuint p;
221
222 for (p = 0 ; p < MAX_CLIP_PLANES ; p++) {
223 if (ctx->Transform.ClipEnabled[p]) {
224 gl_transform_vector( ctx->Transform.ClipUserPlane[p],
225 ctx->Transform.EyeUserPlane[p],
226 ctx->ProjectionMatrix.inv );
227 }
228 }
229}
230
231void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation )
232{
233 GLint p;
234
235 ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane");
236
237
238 p = (GLint) (plane - GL_CLIP_PLANE0);
239 if (p<0 || p>=MAX_CLIP_PLANES) {
240 gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" );
241 return;
242 }
243
244 equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0];
245 equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1];
246 equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2];
247 equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3];
248}
249
250
251
252
253/**********************************************************************/
254/* View volume clipping. */
255/**********************************************************************/
256
257
258/*
259 * Clip a point against the view volume.
260 * Input: v - vertex-vector describing the point to clip
261 * Return: 0 = outside view volume
262 * 1 = inside view volume
263 */
264GLuint gl_viewclip_point( const GLfloat v[] )
265{
266 if ( v[0] > v[3] || v[0] < -v[3]
267 || v[1] > v[3] || v[1] < -v[3]
268 || v[2] > v[3] || v[2] < -v[3] ) {
269 return 0;
270 }
271 else {
272 return 1;
273 }
274}
275
276/*
277 * Clip a point against the user clipping planes.
278 * Input: v - vertex-vector describing the point to clip.
279 * Return: 0 = point was clipped
280 * 1 = point not clipped
281 */
282GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] )
283{
284 GLuint p;
285
286 for (p=0;p<MAX_CLIP_PLANES;p++) {
287 if (ctx->Transform.ClipEnabled[p]) {
288 GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0]
289 + v[1] * ctx->Transform.ClipUserPlane[p][1]
290 + v[2] * ctx->Transform.ClipUserPlane[p][2]
291 + v[3] * ctx->Transform.ClipUserPlane[p][3];
292 if (dot < 0.0F) {
293 return 0;
294 }
295 }
296 }
297
298 return 1;
299}
300
301
302
303
304#if defined(__i386__)
305#define NEGATIVE(x) ((*(int *)&x)<0)
306#else
307#define NEGATIVE(x) (x < 0)
308#endif
309
310
311static clip_poly_func gl_poly_clip_tab[2][5];
312static clip_line_func gl_line_clip_tab[2][5];
313
314#define W(i) coord[i][3]
315#define Z(i) coord[i][2]
316#define Y(i) coord[i][1]
317#define X(i) coord[i][0]
318#define SIZE 4
319#define IND 0
320#define TAG(x) x##_4
321#include "clip_funcs.h"
322
323#define W(i) 1.0
324#define Z(i) coord[i][2]
325#define Y(i) coord[i][1]
326#define X(i) coord[i][0]
327#define SIZE 3
328#define IND 0
329#define TAG(x) x##_3
330#include "clip_funcs.h"
331
332#define W(i) 1.0
333#define Z(i) 0.0
334#define Y(i) coord[i][1]
335#define X(i) coord[i][0]
336#define SIZE 2
337#define IND 0
338#define TAG(x) x##_2
339#include "clip_funcs.h"
340
341#define W(i) coord[i][3]
342#define Z(i) coord[i][2]
343#define Y(i) coord[i][1]
344#define X(i) coord[i][0]
345#define SIZE 4
346#define IND CLIP_TAB_EDGEFLAG
347#define TAG(x) x##_4_edgeflag
348#include "clip_funcs.h"
349
350#define W(i) 1.0
351#define Z(i) coord[i][2]
352#define Y(i) coord[i][1]
353#define X(i) coord[i][0]
354#define SIZE 3
355#define IND CLIP_TAB_EDGEFLAG
356#define TAG(x) x##_3_edgeflag
357#include "clip_funcs.h"
358
359#define W(i) 1.0
360#define Z(i) 0.0
361#define Y(i) coord[i][1]
362#define X(i) coord[i][0]
363#define SIZE 2
364#define IND CLIP_TAB_EDGEFLAG
365#define TAG(x) x##_2_edgeflag
366#include "clip_funcs.h"
367
368
369
370
371void gl_update_clipmask( GLcontext *ctx )
372{
373 GLuint mask = 0;
374
375 if (ctx->Visual->RGBAflag)
376 {
377 if (ctx->Light.ShadeModel==GL_SMOOTH)
378 {
379 mask |= CLIP_RGBA0;
380
381 if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR))
382 mask |= CLIP_RGBA1;
383 }
384
385 if (ctx->Texture.ReallyEnabled & 0xf0)
386 mask |= CLIP_TEX1|CLIP_TEX0;
387
388 if (ctx->Texture.ReallyEnabled & 0xf)
389 mask |= CLIP_TEX0;
390 }
391 else if (ctx->Light.ShadeModel==GL_SMOOTH)
392 {
393 mask |= CLIP_INDEX0;
394
395 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
396 mask |= CLIP_INDEX1;
397 }
398
399 if (ctx->FogMode == FOG_FRAGMENT && (ctx->TriangleCaps & DD_CLIP_FOG_COORD))
400 mask |= CLIP_FOG_COORD;
401
402 ctx->ClipInterpFunc = clip_interp_tab[mask];
403 ctx->poly_clip_tab = gl_poly_clip_tab[0];
404 ctx->line_clip_tab = gl_line_clip_tab[0];
405
406 if (ctx->TriangleCaps & DD_TRI_UNFILLED) {
407 ctx->poly_clip_tab = gl_poly_clip_tab[1];
408 ctx->line_clip_tab = gl_line_clip_tab[0];
409 }
410}
411
412
413#define USER_CLIPTEST(NAME, SZ) \
414static void NAME( struct vertex_buffer *VB ) \
415{ \
416 GLcontext *ctx = VB->ctx; \
417 GLubyte *clipMask = VB->ClipMask; \
418 GLubyte *userClipMask = VB->UserClipMask; \
419 GLuint start = VB->Start; \
420 GLuint count = VB->Count; \
421 GLuint p, i; \
422 GLubyte bit; \
423 \
424 \
425 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \
426 if (ctx->Transform.ClipEnabled[p]) { \
427 GLuint nr = 0; \
428 const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \
429 const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \
430 const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \
431 const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \
432 GLfloat *coord = VB->ClipPtr->start; \
433 GLuint stride = VB->ClipPtr->stride; \
434 \
435 for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \
436 GLfloat dp = coord[0] * a + coord[1] * b; \
437 if (SZ > 2) dp += coord[2] * c; \
438 if (SZ > 3) dp += coord[3] * d; else dp += d; \
439 \
440 if (dp < 0) { \
441 clipMask[i] |= CLIP_USER_BIT; \
442 userClipMask[i] |= bit; \
443 nr++; \
444 } \
445 } \
446 \
447 if (nr > 0) { \
448 VB->ClipOrMask |= CLIP_USER_BIT; \
449 VB->CullMode |= CLIP_MASK_ACTIVE; \
450 if (nr == count - start) { \
451 VB->ClipAndMask |= CLIP_USER_BIT; \
452 VB->Culled = 1; \
453 return; \
454 } \
455 } \
456 } \
457}
458
459
460USER_CLIPTEST(userclip2, 2)
461USER_CLIPTEST(userclip3, 3)
462USER_CLIPTEST(userclip4, 4)
463
464static void (*(usercliptab[5]))( struct vertex_buffer * ) = {
465 0,
466 0,
467 userclip2,
468 userclip3,
469 userclip4
470};
471
472void gl_user_cliptest( struct vertex_buffer *VB )
473{
474 usercliptab[VB->ClipPtr->size]( VB );
475}
476
477
478void gl_init_clip(void)
479{
480 init_clip_funcs_4();
481 init_clip_funcs_3();
482 init_clip_funcs_2();
483
484 init_clip_funcs_4_edgeflag();
485 init_clip_funcs_3_edgeflag();
486 init_clip_funcs_2_edgeflag();
487
488 clip_interp_tab[0] = clip_nil;
489 clip_interp_tab[CLIP_RGBA0] = clipRGBA0;
490 clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1] = clipRGBA0_RGBA1;
491 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0] = clipTEX0_RGBA0;
492 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX0_RGBA0_RGBA1;
493 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0] = clipTEX1_TEX0_RGBA0;
494 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] =
495 clipTEX1_TEX0_RGBA0_RGBA1;
496 clip_interp_tab[CLIP_TEX0] = clipTEX0;
497 clip_interp_tab[CLIP_TEX1|CLIP_TEX0] = clipTEX1_TEX0;
498 clip_interp_tab[CLIP_INDEX0] = clipINDEX0;
499 clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1] = clipINDEX0_INDEX1;
500
501 clip_interp_tab[CLIP_FOG_COORD] = clip_FOG;
502 clip_interp_tab[CLIP_RGBA0|CLIP_FOG_COORD] = clipRGBA0_FOG;
503 clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] = clipRGBA0_RGBA1_FOG;
504 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD] = clipTEX0_RGBA0_FOG;
505 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] = clipTEX0_RGBA0_RGBA1_FOG;
506 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD] = clipTEX1_TEX0_RGBA0_FOG;
507 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] =
508 clipTEX1_TEX0_RGBA0_RGBA1_FOG;
509 clip_interp_tab[CLIP_TEX0|CLIP_FOG_COORD] = clipTEX0_FOG;
510 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD] = clipTEX1_TEX0_FOG;
511 clip_interp_tab[CLIP_INDEX0|CLIP_FOG_COORD] = clipINDEX0_FOG;
512 clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD] = clipINDEX0_INDEX1_FOG;
513}
514
Note: See TracBrowser for help on using the repository browser.