1 /* $Id: clip.c,v 1.13 2000/11/05 18:40:57 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
46 #define CLIP_RGBA0 0x1
47 #define CLIP_RGBA1 0x2
50 #define CLIP_INDEX0 0x10
51 #define CLIP_INDEX1 0x20
52 #define CLIP_FOG_COORD 0x40
55 /* Linear interpolation between A and B: */
56 #define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
60 #define INTERP_SZ( t, vec, to, a, b, sz ) \
63 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
64 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
65 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
66 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
71 static clip_interp_func clip_interp_tab
[0x80];
75 #include "interp_tmp.h"
77 #define IND (CLIP_RGBA0)
78 #define NAME clipRGBA0
79 #include "interp_tmp.h"
81 #define IND (CLIP_RGBA0|CLIP_RGBA1)
82 #define NAME clipRGBA0_RGBA1
83 #include "interp_tmp.h"
85 #define IND (CLIP_TEX0|CLIP_RGBA0)
86 #define NAME clipTEX0_RGBA0
87 #include "interp_tmp.h"
89 #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
90 #define NAME clipTEX0_RGBA0_RGBA1
91 #include "interp_tmp.h"
93 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
94 #define NAME clipTEX1_TEX0_RGBA0
95 #include "interp_tmp.h"
97 #define IND (CLIP_TEX0)
99 #include "interp_tmp.h"
101 #define IND (CLIP_TEX1|CLIP_TEX0)
102 #define NAME clipTEX1_TEX0
103 #include "interp_tmp.h"
105 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
106 #define NAME clipTEX1_TEX0_RGBA0_RGBA1
107 #include "interp_tmp.h"
109 #define IND (CLIP_INDEX0)
110 #define NAME clipINDEX0
111 #include "interp_tmp.h"
113 #define IND (CLIP_INDEX0|CLIP_INDEX1)
114 #define NAME clipINDEX0_INDEX1
115 #include "interp_tmp.h"
117 #define IND (CLIP_FOG_COORD)
118 #define NAME clip_FOG
119 #include "interp_tmp.h"
121 #define IND (CLIP_RGBA0|CLIP_FOG_COORD)
122 #define NAME clipRGBA0_FOG
123 #include "interp_tmp.h"
125 #define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
126 #define NAME clipRGBA0_RGBA1_FOG
127 #include "interp_tmp.h"
129 #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
130 #define NAME clipTEX0_RGBA0_FOG
131 #include "interp_tmp.h"
133 #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
134 #define NAME clipTEX0_RGBA0_RGBA1_FOG
135 #include "interp_tmp.h"
137 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
138 #define NAME clipTEX1_TEX0_RGBA0_FOG
139 #include "interp_tmp.h"
141 #define IND (CLIP_TEX0|CLIP_FOG_COORD)
142 #define NAME clipTEX0_FOG
143 #include "interp_tmp.h"
145 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD)
146 #define NAME clipTEX1_TEX0_FOG
147 #include "interp_tmp.h"
149 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
150 #define NAME clipTEX1_TEX0_RGBA0_RGBA1_FOG
151 #include "interp_tmp.h"
153 #define IND (CLIP_INDEX0|CLIP_FOG_COORD)
154 #define NAME clipINDEX0_FOG
155 #include "interp_tmp.h"
157 #define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD)
158 #define NAME clipINDEX0_INDEX1_FOG
159 #include "interp_tmp.h"
164 /**********************************************************************/
165 /* Get/Set User clip-planes. */
166 /**********************************************************************/
171 _mesa_ClipPlane( GLenum plane
, const GLdouble
*eq
)
173 GET_CURRENT_CONTEXT(ctx
);
182 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClipPlane");
184 p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
185 if (p
<0 || p
>=MAX_CLIP_PLANES
) {
186 gl_error( ctx
, GL_INVALID_ENUM
, "glClipPlane" );
191 * The equation is transformed by the transpose of the inverse of the
192 * current modelview matrix and stored in the resulting eye coordinates.
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.
198 if (ctx
->ModelView
.flags
& MAT_DIRTY_ALL_OVER
) {
199 gl_matrix_analyze( &ctx
->ModelView
);
201 gl_transform_vector( ctx
->Transform
.EyeUserPlane
[p
], equation
,
202 ctx
->ModelView
.inv
);
205 if (ctx
->Transform
.ClipEnabled
[p
]) {
206 if (ctx
->ProjectionMatrix
.flags
& MAT_DIRTY_ALL_OVER
) {
207 gl_matrix_analyze( &ctx
->ProjectionMatrix
);
209 gl_transform_vector( ctx
->Transform
._ClipUserPlane
[p
],
210 ctx
->Transform
.EyeUserPlane
[p
],
211 ctx
->ProjectionMatrix
.inv
);
214 ctx
->NewState
|= _NEW_TRANSFORM
;
218 void gl_update_userclip( GLcontext
*ctx
)
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
);
232 _mesa_GetClipPlane( GLenum plane
, GLdouble
*equation
)
234 GET_CURRENT_CONTEXT(ctx
);
237 ASSERT_OUTSIDE_BEGIN_END(ctx
, "glGetClipPlane");
240 p
= (GLint
) (plane
- GL_CLIP_PLANE0
);
241 if (p
<0 || p
>=MAX_CLIP_PLANES
) {
242 gl_error( ctx
, GL_INVALID_ENUM
, "glGetClipPlane" );
246 equation
[0] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][0];
247 equation
[1] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][1];
248 equation
[2] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][2];
249 equation
[3] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][3];
255 /**********************************************************************/
256 /* View volume clipping. */
257 /**********************************************************************/
261 * Clip a point against the view volume.
262 * Input: v - vertex-vector describing the point to clip
263 * Return: 0 = outside view volume
264 * 1 = inside view volume
266 GLuint
gl_viewclip_point( const GLfloat v
[] )
268 if ( v
[0] > v
[3] || v
[0] < -v
[3]
269 || v
[1] > v
[3] || v
[1] < -v
[3]
270 || v
[2] > v
[3] || v
[2] < -v
[3] ) {
279 * Clip a point against the user clipping planes.
280 * Input: v - vertex-vector describing the point to clip.
281 * Return: 0 = point was clipped
282 * 1 = point not clipped
284 GLuint
gl_userclip_point( GLcontext
* ctx
, const GLfloat v
[] )
288 for (p
=0;p
<MAX_CLIP_PLANES
;p
++) {
289 if (ctx
->Transform
.ClipEnabled
[p
]) {
290 GLfloat dot
= v
[0] * ctx
->Transform
._ClipUserPlane
[p
][0]
291 + v
[1] * ctx
->Transform
._ClipUserPlane
[p
][1]
292 + v
[2] * ctx
->Transform
._ClipUserPlane
[p
][2]
293 + v
[3] * ctx
->Transform
._ClipUserPlane
[p
][3];
307 #define NEGATIVE(x) ((*(int *)&x)<0)
308 #define DIFFERENT_SIGNS(a,b) ((a*b) < 0)
310 #define NEGATIVE(x) (x < 0)
311 #define DIFFERENT_SIGNS(a,b) ((a*b) < 0)
315 static clip_poly_func gl_poly_clip_tab
[2][5];
316 static clip_line_func gl_line_clip_tab
[2][5];
318 #define W(i) coord[i][3]
319 #define Z(i) coord[i][2]
320 #define Y(i) coord[i][1]
321 #define X(i) coord[i][0]
325 #include "clip_funcs.h"
328 #define Z(i) coord[i][2]
329 #define Y(i) coord[i][1]
330 #define X(i) coord[i][0]
334 #include "clip_funcs.h"
338 #define Y(i) coord[i][1]
339 #define X(i) coord[i][0]
343 #include "clip_funcs.h"
345 #define W(i) coord[i][3]
346 #define Z(i) coord[i][2]
347 #define Y(i) coord[i][1]
348 #define X(i) coord[i][0]
350 #define IND CLIP_TAB_EDGEFLAG
351 #define TAG(x) x##_4_edgeflag
352 #include "clip_funcs.h"
355 #define Z(i) coord[i][2]
356 #define Y(i) coord[i][1]
357 #define X(i) coord[i][0]
359 #define IND CLIP_TAB_EDGEFLAG
360 #define TAG(x) x##_3_edgeflag
361 #include "clip_funcs.h"
365 #define Y(i) coord[i][1]
366 #define X(i) coord[i][0]
368 #define IND CLIP_TAB_EDGEFLAG
369 #define TAG(x) x##_2_edgeflag
370 #include "clip_funcs.h"
375 void gl_update_clipmask( GLcontext
*ctx
)
379 if (ctx
->Visual
.RGBAflag
)
383 if (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_SEPERATE_SPECULAR
))
386 if (ctx
->Texture
._ReallyEnabled
& 0xf0)
387 mask
|= CLIP_TEX1
|CLIP_TEX0
;
389 if (ctx
->Texture
._ReallyEnabled
& 0xf)
392 else if (ctx
->Light
.ShadeModel
==GL_SMOOTH
)
396 if (ctx
->_TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
)
400 if (ctx
->Fog
.Enabled
)
401 mask
|= CLIP_FOG_COORD
;
403 ctx
->_ClipInterpFunc
= clip_interp_tab
[mask
];
404 ctx
->_poly_clip_tab
= gl_poly_clip_tab
[0];
405 ctx
->_line_clip_tab
= gl_line_clip_tab
[0];
407 if (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) {
408 ctx
->_poly_clip_tab
= gl_poly_clip_tab
[1];
409 ctx
->_line_clip_tab
= gl_line_clip_tab
[0];
414 #define USER_CLIPTEST(NAME, SZ) \
415 static void NAME( struct vertex_buffer *VB ) \
417 GLcontext *ctx = VB->ctx; \
418 GLubyte *clipMask = VB->ClipMask; \
419 GLubyte *userClipMask = VB->UserClipMask; \
420 GLuint start = VB->Start; \
421 GLuint count = VB->Count; \
426 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \
427 if (ctx->Transform.ClipEnabled[p]) { \
429 const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \
430 const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \
431 const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \
432 const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \
433 GLfloat *coord = VB->ClipPtr->start; \
434 GLuint stride = VB->ClipPtr->stride; \
436 for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \
437 GLfloat dp = coord[0] * a + coord[1] * b; \
438 if (SZ > 2) dp += coord[2] * c; \
439 if (SZ > 3) dp += coord[3] * d; else dp += d; \
442 clipMask[i] |= CLIP_USER_BIT; \
443 userClipMask[i] |= bit; \
449 VB->ClipOrMask |= CLIP_USER_BIT; \
450 VB->CullMode |= CLIP_MASK_ACTIVE; \
451 if (nr == count - start) { \
452 VB->ClipAndMask |= CLIP_USER_BIT; \
461 USER_CLIPTEST(userclip2
, 2)
462 USER_CLIPTEST(userclip3
, 3)
463 USER_CLIPTEST(userclip4
, 4)
465 static void (*(usercliptab
[5]))( struct vertex_buffer
* ) = {
473 void gl_user_cliptest( struct vertex_buffer
*VB
)
475 usercliptab
[VB
->ClipPtr
->size
]( VB
);
479 void gl_init_clip(void)
485 init_clip_funcs_4_edgeflag();
486 init_clip_funcs_3_edgeflag();
487 init_clip_funcs_2_edgeflag();
489 clip_interp_tab
[0] = clip_nil
;
490 clip_interp_tab
[CLIP_RGBA0
] = clipRGBA0
;
491 clip_interp_tab
[CLIP_RGBA0
|CLIP_RGBA1
] = clipRGBA0_RGBA1
;
492 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
] = clipTEX0_RGBA0
;
493 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
] = clipTEX0_RGBA0_RGBA1
;
494 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
] = clipTEX1_TEX0_RGBA0
;
495 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
] =
496 clipTEX1_TEX0_RGBA0_RGBA1
;
497 clip_interp_tab
[CLIP_TEX0
] = clipTEX0
;
498 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
] = clipTEX1_TEX0
;
499 clip_interp_tab
[CLIP_INDEX0
] = clipINDEX0
;
500 clip_interp_tab
[CLIP_INDEX0
|CLIP_INDEX1
] = clipINDEX0_INDEX1
;
502 clip_interp_tab
[CLIP_FOG_COORD
] = clip_FOG
;
503 clip_interp_tab
[CLIP_RGBA0
|CLIP_FOG_COORD
] = clipRGBA0_FOG
;
504 clip_interp_tab
[CLIP_RGBA0
|CLIP_RGBA1
|CLIP_FOG_COORD
] = clipRGBA0_RGBA1_FOG
;
505 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
|CLIP_FOG_COORD
] = clipTEX0_RGBA0_FOG
;
506 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
|CLIP_FOG_COORD
] = clipTEX0_RGBA0_RGBA1_FOG
;
507 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
|CLIP_FOG_COORD
] = clipTEX1_TEX0_RGBA0_FOG
;
508 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
|CLIP_FOG_COORD
] =
509 clipTEX1_TEX0_RGBA0_RGBA1_FOG
;
510 clip_interp_tab
[CLIP_TEX0
|CLIP_FOG_COORD
] = clipTEX0_FOG
;
511 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_FOG_COORD
] = clipTEX1_TEX0_FOG
;
512 clip_interp_tab
[CLIP_INDEX0
|CLIP_FOG_COORD
] = clipINDEX0_FOG
;
513 clip_interp_tab
[CLIP_INDEX0
|CLIP_INDEX1
|CLIP_FOG_COORD
] = clipINDEX0_INDEX1_FOG
;