1 /* $Id: clip.c,v 1.3 1999/10/08 09:27:10 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.
38 #include "GL/xf86glx.h"
49 #include "GL/xf86glx.h"
56 /* Linear interpolation between A and B: */
57 #define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
61 #define INTERP_SZ( t, vec, to, a, b, sz ) \
64 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
65 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
66 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
67 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
74 #define CLIP_RGBA0 0x1
75 #define CLIP_RGBA1 0x2
78 #define CLIP_INDEX0 0x10
79 #define CLIP_INDEX1 0x20
81 static clip_interp_func clip_interp_tab
[0x40];
85 #include "interp_tmp.h"
87 #define IND (CLIP_RGBA0)
88 #define NAME clipRGBA0
89 #include "interp_tmp.h"
91 #define IND (CLIP_RGBA0|CLIP_RGBA1)
92 #define NAME clipRGBA0_RGBA1
93 #include "interp_tmp.h"
95 #define IND (CLIP_TEX0|CLIP_RGBA0)
96 #define NAME clipTEX0_RGBA0
97 #include "interp_tmp.h"
99 #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
100 #define NAME clipTEX0_RGBA0_RGBA1
101 #include "interp_tmp.h"
103 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
104 #define NAME clipTEX1_TEX0_RGBA0
105 #include "interp_tmp.h"
107 #define IND (CLIP_TEX0)
108 #define NAME clipTEX0
109 #include "interp_tmp.h"
111 #define IND (CLIP_TEX1|CLIP_TEX0)
112 #define NAME clipTEX1_TEX0
113 #include "interp_tmp.h"
115 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
116 #define NAME clipTEX1_TEX0_RGBA0_RGBA1
117 #include "interp_tmp.h"
119 #define IND (CLIP_INDEX0)
120 #define NAME clipINDEX0
121 #include "interp_tmp.h"
123 #define IND (CLIP_INDEX0|CLIP_INDEX1)
124 #define NAME clipINDEX0_INDEX1
125 #include "interp_tmp.h"
130 /**********************************************************************/
131 /* Get/Set User clip-planes. */
132 /**********************************************************************/
136 void gl_ClipPlane( GLcontext
* ctx
, GLenum plane
, const GLfloat
*equation
)
140 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClipPlane");
142 p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
143 if (p
<0 || p
>=MAX_CLIP_PLANES
) {
144 gl_error( ctx
, GL_INVALID_ENUM
, "glClipPlane" );
149 * The equation is transformed by the transpose of the inverse of the
150 * current modelview matrix and stored in the resulting eye coordinates.
152 * KW: Eqn is then transformed to the current clip space, where user
153 * clipping now takes place. The clip-space equations are recalculated
154 * whenever the projection matrix changes.
156 if (ctx
->ModelView
.flags
& MAT_DIRTY_ALL_OVER
) {
157 gl_matrix_analyze( &ctx
->ModelView
);
159 gl_transform_vector( ctx
->Transform
.EyeUserPlane
[p
], equation
,
160 ctx
->ModelView
.inv
);
163 if (ctx
->Transform
.ClipEnabled
[p
]) {
164 ctx
->NewState
|= NEW_USER_CLIP
;
166 if (ctx
->ProjectionMatrix
.flags
& MAT_DIRTY_ALL_OVER
) {
167 gl_matrix_analyze( &ctx
->ProjectionMatrix
);
169 gl_transform_vector( ctx
->Transform
.ClipUserPlane
[p
],
170 ctx
->Transform
.EyeUserPlane
[p
],
171 ctx
->ProjectionMatrix
.inv
);
176 void gl_update_userclip( GLcontext
*ctx
)
180 for (p
= 0 ; p
< MAX_CLIP_PLANES
; p
++) {
181 if (ctx
->Transform
.ClipEnabled
[p
]) {
182 gl_transform_vector( ctx
->Transform
.ClipUserPlane
[p
],
183 ctx
->Transform
.EyeUserPlane
[p
],
184 ctx
->ProjectionMatrix
.inv
);
189 void gl_GetClipPlane( GLcontext
* ctx
, GLenum plane
, GLdouble
*equation
)
193 ASSERT_OUTSIDE_BEGIN_END(ctx
, "glGetClipPlane");
196 p
= (GLint
) (plane
- GL_CLIP_PLANE0
);
197 if (p
<0 || p
>=MAX_CLIP_PLANES
) {
198 gl_error( ctx
, GL_INVALID_ENUM
, "glGetClipPlane" );
202 equation
[0] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][0];
203 equation
[1] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][1];
204 equation
[2] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][2];
205 equation
[3] = (GLdouble
) ctx
->Transform
.EyeUserPlane
[p
][3];
211 /**********************************************************************/
212 /* View volume clipping. */
213 /**********************************************************************/
217 * Clip a point against the view volume.
218 * Input: v - vertex-vector describing the point to clip
219 * Return: 0 = outside view volume
220 * 1 = inside view volume
222 GLuint
gl_viewclip_point( const GLfloat v
[] )
224 if ( v
[0] > v
[3] || v
[0] < -v
[3]
225 || v
[1] > v
[3] || v
[1] < -v
[3]
226 || v
[2] > v
[3] || v
[2] < -v
[3] ) {
235 * Clip a point against the user clipping planes.
236 * Input: v - vertex-vector describing the point to clip.
237 * Return: 0 = point was clipped
238 * 1 = point not clipped
240 GLuint
gl_userclip_point( GLcontext
* ctx
, const GLfloat v
[] )
244 for (p
=0;p
<MAX_CLIP_PLANES
;p
++) {
245 if (ctx
->Transform
.ClipEnabled
[p
]) {
246 GLfloat dot
= v
[0] * ctx
->Transform
.ClipUserPlane
[p
][0]
247 + v
[1] * ctx
->Transform
.ClipUserPlane
[p
][1]
248 + v
[2] * ctx
->Transform
.ClipUserPlane
[p
][2]
249 + v
[3] * ctx
->Transform
.ClipUserPlane
[p
][3];
262 #if defined(__i386__)
263 #define NEGATIVE(x) ((*(int *)&x)<0)
265 #define NEGATIVE(x) (x < 0)
269 static clip_poly_func gl_poly_clip_tab
[2][5];
270 static clip_line_func gl_line_clip_tab
[2][5];
272 #define W(i) coord[i][3]
273 #define Z(i) coord[i][2]
274 #define Y(i) coord[i][1]
275 #define X(i) coord[i][0]
279 #include "clip_funcs.h"
282 #define Z(i) coord[i][2]
283 #define Y(i) coord[i][1]
284 #define X(i) coord[i][0]
288 #include "clip_funcs.h"
292 #define Y(i) coord[i][1]
293 #define X(i) coord[i][0]
297 #include "clip_funcs.h"
299 #define W(i) coord[i][3]
300 #define Z(i) coord[i][2]
301 #define Y(i) coord[i][1]
302 #define X(i) coord[i][0]
304 #define IND CLIP_TAB_EDGEFLAG
305 #define TAG(x) x##_4_edgeflag
306 #include "clip_funcs.h"
309 #define Z(i) coord[i][2]
310 #define Y(i) coord[i][1]
311 #define X(i) coord[i][0]
313 #define IND CLIP_TAB_EDGEFLAG
314 #define TAG(x) x##_3_edgeflag
315 #include "clip_funcs.h"
319 #define Y(i) coord[i][1]
320 #define X(i) coord[i][0]
322 #define IND CLIP_TAB_EDGEFLAG
323 #define TAG(x) x##_2_edgeflag
324 #include "clip_funcs.h"
329 void gl_update_clipmask( GLcontext
*ctx
)
333 if (ctx
->Visual
->RGBAflag
)
335 if (ctx
->Light
.ShadeModel
==GL_SMOOTH
)
339 if (ctx
->TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_SEPERATE_SPECULAR
))
343 if (ctx
->Texture
.ReallyEnabled
& 0xf0)
344 mask
|= CLIP_TEX1
|CLIP_TEX0
;
346 if (ctx
->Texture
.ReallyEnabled
& 0xf)
349 else if (ctx
->Light
.ShadeModel
==GL_SMOOTH
)
353 if (ctx
->TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
)
358 ctx
->ClipInterpFunc
= clip_interp_tab
[mask
];
359 ctx
->poly_clip_tab
= gl_poly_clip_tab
[0];
360 ctx
->line_clip_tab
= gl_line_clip_tab
[0];
362 if (ctx
->TriangleCaps
& DD_TRI_UNFILLED
) {
363 ctx
->poly_clip_tab
= gl_poly_clip_tab
[1];
364 ctx
->line_clip_tab
= gl_line_clip_tab
[0];
369 #define USER_CLIPTEST(NAME, SZ) \
370 static void NAME( struct vertex_buffer *VB ) \
372 GLcontext *ctx = VB->ctx; \
373 GLubyte *clipMask = VB->ClipMask; \
374 GLubyte *userClipMask = VB->UserClipMask; \
375 GLuint start = VB->Start; \
376 GLuint count = VB->Count; \
381 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \
382 if (ctx->Transform.ClipEnabled[p]) { \
384 const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \
385 const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \
386 const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \
387 const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \
388 GLfloat *coord = VB->ClipPtr->start; \
389 GLuint stride = VB->ClipPtr->stride; \
391 for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \
392 GLfloat dp = coord[0] * a + coord[1] * b; \
393 if (SZ > 2) dp += coord[2] * c; \
394 if (SZ > 3) dp += coord[3] * d; else dp += d; \
397 clipMask[i] |= CLIP_USER_BIT; \
398 userClipMask[i] |= bit; \
404 VB->ClipOrMask |= CLIP_USER_BIT; \
405 VB->CullMode |= CLIP_MASK_ACTIVE; \
406 if (nr == count - start) { \
407 VB->ClipAndMask |= CLIP_USER_BIT; \
416 USER_CLIPTEST(userclip2
, 2)
417 USER_CLIPTEST(userclip3
, 3)
418 USER_CLIPTEST(userclip4
, 4)
420 static void (*(usercliptab
[5]))( struct vertex_buffer
* ) = {
428 void gl_user_cliptest( struct vertex_buffer
*VB
)
430 usercliptab
[VB
->ClipPtr
->size
]( VB
);
434 void gl_init_clip(void)
440 init_clip_funcs_4_edgeflag();
441 init_clip_funcs_3_edgeflag();
442 init_clip_funcs_2_edgeflag();
444 clip_interp_tab
[0] = clip_nil
;
445 clip_interp_tab
[CLIP_RGBA0
] = clipRGBA0
;
446 clip_interp_tab
[CLIP_RGBA0
|CLIP_RGBA1
] = clipRGBA0_RGBA1
;
447 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
] = clipTEX0_RGBA0
;
448 clip_interp_tab
[CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
] = clipTEX0_RGBA0_RGBA1
;
449 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
] = clipTEX1_TEX0_RGBA0
;
450 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
|CLIP_RGBA0
|CLIP_RGBA1
] =
451 clipTEX1_TEX0_RGBA0_RGBA1
;
453 clip_interp_tab
[CLIP_TEX0
] = clipTEX0
;
454 clip_interp_tab
[CLIP_TEX1
|CLIP_TEX0
] = clipTEX1_TEX0
;
456 clip_interp_tab
[CLIP_INDEX0
] = clipINDEX0
;
457 clip_interp_tab
[CLIP_INDEX0
|CLIP_INDEX1
] = clipINDEX0_INDEX1
;