1 /* $Id: t_vb_cliptmp.h,v 1.12 2001/05/09 12:25:40 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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.
27 * Keith Whitwell <keithw@valinux.com>
31 #define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
33 #define POLY_CLIP( PLANE, A, B, C, D ) \
36 GLuint idxPrev = inlist[0]; \
37 GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
38 GLuint outcount = 0; \
41 inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
42 for (i = 1; i <= n; i++) { \
43 GLuint idx = inlist[i]; \
44 GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
46 clipmask[idxPrev] |= PLANE; \
47 if (!NEGATIVE(dpPrev)) { \
48 outlist[outcount++] = idxPrev; \
49 clipmask[idxPrev] &= ~PLANE; \
52 if (DIFFERENT_SIGNS(dp, dpPrev)) { \
53 GLuint newvert = VB->LastClipped++; \
54 VB->ClipMask[newvert] = 0; \
55 outlist[outcount++] = newvert; \
57 /* Going out of bounds. Avoid division by zero as we \
58 * know dp != dpPrev from DIFFERENT_SIGNS, above. \
60 GLfloat t = dp / (dp - dpPrev); \
61 INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
62 interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
66 GLfloat t = dpPrev / (dpPrev - dp); \
67 INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
68 interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
80 GLuint *tmp = inlist; \
89 #define LINE_CLIP(PLANE, A, B, C, D ) \
92 GLfloat dpI = CLIP_DOTPROD( ii, A, B, C, D ); \
93 GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \
95 if (DIFFERENT_SIGNS(dpI, dpJ)) { \
96 GLuint newvert = VB->LastClipped++; \
97 VB->ClipMask[newvert] = 0; \
98 if (NEGATIVE(dpJ)) { \
99 GLfloat t = dpI / (dpI - dpJ); \
100 VB->ClipMask[jj] |= PLANE; \
101 INTERP_4F( t, coord[newvert], coord[ii], coord[jj] ); \
102 interp( ctx, t, newvert, ii, jj, GL_FALSE ); \
105 GLfloat t = dpJ / (dpJ - dpI); \
106 VB->ClipMask[ii] |= PLANE; \
107 INTERP_4F( t, coord[newvert], coord[jj], coord[ii] ); \
108 interp( ctx, t, newvert, jj, ii, GL_FALSE ); \
112 else if (NEGATIVE(dpI)) \
119 /* Clip a line against the viewport and user clip planes.
121 static __inline
void TAG(clip_line
)( GLcontext
*ctx
,
125 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
126 struct vertex_buffer
*VB
= &tnl
->vb
;
127 interp_func interp
= tnl
->Driver
.RenderInterp
;
128 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
129 GLuint ii
= i
, jj
= j
, p
;
131 VB
->LastClipped
= VB
->FirstClipped
;
134 LINE_CLIP( CLIP_RIGHT_BIT
, -1, 0, 0, 1 );
135 LINE_CLIP( CLIP_LEFT_BIT
, 1, 0, 0, 1 );
136 LINE_CLIP( CLIP_TOP_BIT
, 0, -1, 0, 1 );
137 LINE_CLIP( CLIP_BOTTOM_BIT
, 0, 1, 0, 1 );
138 LINE_CLIP( CLIP_FAR_BIT
, 0, 0, -1, 1 );
139 LINE_CLIP( CLIP_NEAR_BIT
, 0, 0, 1, 1 );
142 if (mask
& CLIP_USER_BIT
) {
143 for (p
=0;p
<MAX_CLIP_PLANES
;p
++) {
144 if (ctx
->Transform
.ClipEnabled
[p
]) {
145 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
146 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
147 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
148 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
149 LINE_CLIP( CLIP_USER_BIT
, a
, b
, c
, d
);
154 if ((ctx
->_TriangleCaps
& DD_FLATSHADE
) && j
!= jj
)
155 tnl
->Driver
.RenderCopyPV( ctx
, jj
, j
);
157 tnl
->Driver
.RenderClippedLine( ctx
, ii
, jj
);
161 /* Clip a triangle against the viewport and user clip planes.
163 static __inline
void TAG(clip_tri
)( GLcontext
*ctx
,
164 GLuint v0
, GLuint v1
, GLuint v2
,
167 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
168 struct vertex_buffer
*VB
= &tnl
->vb
;
169 interp_func interp
= tnl
->Driver
.RenderInterp
;
170 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
172 GLuint vlist
[2][MAX_CLIPPED_VERTICES
];
173 GLuint
*inlist
= vlist
[0], *outlist
= vlist
[1];
175 GLubyte
*clipmask
= VB
->ClipMask
;
178 ASSIGN_3V(inlist
, v2
, v0
, v1
); /* pv rotated to slot zero */
180 VB
->LastClipped
= VB
->FirstClipped
;
183 POLY_CLIP( CLIP_RIGHT_BIT
, -1, 0, 0, 1 );
184 POLY_CLIP( CLIP_LEFT_BIT
, 1, 0, 0, 1 );
185 POLY_CLIP( CLIP_TOP_BIT
, 0, -1, 0, 1 );
186 POLY_CLIP( CLIP_BOTTOM_BIT
, 0, 1, 0, 1 );
187 POLY_CLIP( CLIP_FAR_BIT
, 0, 0, -1, 1 );
188 POLY_CLIP( CLIP_NEAR_BIT
, 0, 0, 1, 1 );
191 if (mask
& CLIP_USER_BIT
) {
192 for (p
=0;p
<MAX_CLIP_PLANES
;p
++) {
193 if (ctx
->Transform
.ClipEnabled
[p
]) {
194 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
195 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
196 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
197 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
198 POLY_CLIP( CLIP_USER_BIT
, a
, b
, c
, d
);
203 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
204 if (pv
!= inlist
[0]) {
205 ASSERT( inlist
[0] >= VB
->FirstClipped
);
206 tnl
->Driver
.RenderCopyPV( ctx
, inlist
[0], pv
);
210 tnl
->Driver
.RenderClippedPolygon( ctx
, inlist
, n
);
214 /* Clip a quad against the viewport and user clip planes.
216 static __inline
void TAG(clip_quad
)( GLcontext
*ctx
,
217 GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
,
220 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
221 struct vertex_buffer
*VB
= &tnl
->vb
;
222 interp_func interp
= tnl
->Driver
.RenderInterp
;
223 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
225 GLuint vlist
[2][MAX_CLIPPED_VERTICES
];
226 GLuint
*inlist
= vlist
[0], *outlist
= vlist
[1];
228 GLubyte
*clipmask
= VB
->ClipMask
;
231 ASSIGN_4V(inlist
, v3
, v0
, v1
, v2
); /* pv rotated to slot zero */
233 VB
->LastClipped
= VB
->FirstClipped
;
236 POLY_CLIP( CLIP_RIGHT_BIT
, -1, 0, 0, 1 );
237 POLY_CLIP( CLIP_LEFT_BIT
, 1, 0, 0, 1 );
238 POLY_CLIP( CLIP_TOP_BIT
, 0, -1, 0, 1 );
239 POLY_CLIP( CLIP_BOTTOM_BIT
, 0, 1, 0, 1 );
240 POLY_CLIP( CLIP_FAR_BIT
, 0, 0, -1, 1 );
241 POLY_CLIP( CLIP_NEAR_BIT
, 0, 0, 1, 1 );
244 if (mask
& CLIP_USER_BIT
) {
245 for (p
=0;p
<MAX_CLIP_PLANES
;p
++) {
246 if (ctx
->Transform
.ClipEnabled
[p
]) {
247 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
248 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
249 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
250 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
251 POLY_CLIP( CLIP_USER_BIT
, a
, b
, c
, d
);
256 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
257 if (pv
!= inlist
[0]) {
258 ASSERT( inlist
[0] >= VB
->FirstClipped
);
259 tnl
->Driver
.RenderCopyPV( ctx
, inlist
[0], pv
);
263 tnl
->Driver
.RenderClippedPolygon( ctx
, inlist
, n
);