xref: /reactos/dll/opengl/mesa/clip.c (revision 5f2bebf7)
1*5f2bebf7SJérôme Gardou /* $Id: clip.c,v 1.16 1998/02/03 23:45:36 brianp Exp $ */
2*5f2bebf7SJérôme Gardou 
3*5f2bebf7SJérôme Gardou /*
4*5f2bebf7SJérôme Gardou  * Mesa 3-D graphics library
5*5f2bebf7SJérôme Gardou  * Version:  2.6
6*5f2bebf7SJérôme Gardou  * Copyright (C) 1995-1997  Brian Paul
7*5f2bebf7SJérôme Gardou  *
8*5f2bebf7SJérôme Gardou  * This library is free software; you can redistribute it and/or
9*5f2bebf7SJérôme Gardou  * modify it under the terms of the GNU Library General Public
10*5f2bebf7SJérôme Gardou  * License as published by the Free Software Foundation; either
11*5f2bebf7SJérôme Gardou  * version 2 of the License, or (at your option) any later version.
12*5f2bebf7SJérôme Gardou  *
13*5f2bebf7SJérôme Gardou  * This library is distributed in the hope that it will be useful,
14*5f2bebf7SJérôme Gardou  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*5f2bebf7SJérôme Gardou  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*5f2bebf7SJérôme Gardou  * Library General Public License for more details.
17*5f2bebf7SJérôme Gardou  *
18*5f2bebf7SJérôme Gardou  * You should have received a copy of the GNU Library General Public
19*5f2bebf7SJérôme Gardou  * License along with this library; if not, write to the Free
20*5f2bebf7SJérôme Gardou  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*5f2bebf7SJérôme Gardou  */
22*5f2bebf7SJérôme Gardou 
23*5f2bebf7SJérôme Gardou 
24*5f2bebf7SJérôme Gardou /*
25*5f2bebf7SJérôme Gardou  * $Log: clip.c,v $
26*5f2bebf7SJérôme Gardou  * Revision 1.16  1998/02/03 23:45:36  brianp
27*5f2bebf7SJérôme Gardou  * added space parameter to clip interpolation functions
28*5f2bebf7SJérôme Gardou  *
29*5f2bebf7SJérôme Gardou  * Revision 1.15  1998/01/06 02:40:52  brianp
30*5f2bebf7SJérôme Gardou  * added DavidB's clipping interpolation optimization
31*5f2bebf7SJérôme Gardou  *
32*5f2bebf7SJérôme Gardou  * Revision 1.14  1997/07/24 01:24:45  brianp
33*5f2bebf7SJérôme Gardou  * changed precompiled header symbol from PCH to PC_HEADER
34*5f2bebf7SJérôme Gardou  *
35*5f2bebf7SJérôme Gardou  * Revision 1.13  1997/05/28 03:23:48  brianp
36*5f2bebf7SJérôme Gardou  * added precompiled header (PCH) support
37*5f2bebf7SJérôme Gardou  *
38*5f2bebf7SJérôme Gardou  * Revision 1.12  1997/04/02 03:10:06  brianp
39*5f2bebf7SJérôme Gardou  * call gl_analyze_modelview_matrix instead of gl_compute_modelview_inverse
40*5f2bebf7SJérôme Gardou  *
41*5f2bebf7SJérôme Gardou  * Revision 1.11  1997/02/13 21:16:09  brianp
42*5f2bebf7SJérôme Gardou  * if too many vertices in polygon return VB_SIZE-1, not VB_SIZE
43*5f2bebf7SJérôme Gardou  *
44*5f2bebf7SJérôme Gardou  * Revision 1.10  1997/02/10 21:16:12  brianp
45*5f2bebf7SJérôme Gardou  * added checks in polygon clippers to prevent array overflows
46*5f2bebf7SJérôme Gardou  *
47*5f2bebf7SJérôme Gardou  * Revision 1.9  1997/02/04 19:39:39  brianp
48*5f2bebf7SJérôme Gardou  * changed size of vlist2[] arrays to VB_SIZE per Randy Frank
49*5f2bebf7SJérôme Gardou  *
50*5f2bebf7SJérôme Gardou  * Revision 1.8  1996/12/02 20:10:07  brianp
51*5f2bebf7SJérôme Gardou  * changed the macros in gl_viewclip_polygon() to be like gl_viewclip_line()
52*5f2bebf7SJérôme Gardou  *
53*5f2bebf7SJérôme Gardou  * Revision 1.7  1996/10/29 02:55:02  brianp
54*5f2bebf7SJérôme Gardou  * fixed duplicate vertex bug in gl_viewclip_polygon()
55*5f2bebf7SJérôme Gardou  *
56*5f2bebf7SJérôme Gardou  * Revision 1.6  1996/10/07 23:48:33  brianp
57*5f2bebf7SJérôme Gardou  * changed temporaries to GLdouble in gl_viewclip_polygon()
58*5f2bebf7SJérôme Gardou  *
59*5f2bebf7SJérôme Gardou  * Revision 1.5  1996/10/03 01:43:45  brianp
60*5f2bebf7SJérôme Gardou  * changed INSIDE() macro in gl_viewclip_polygon() to work like other macros
61*5f2bebf7SJérôme Gardou  *
62*5f2bebf7SJérôme Gardou  * Revision 1.4  1996/10/03 01:36:33  brianp
63*5f2bebf7SJérôme Gardou  * changed COMPUTE_INTERSECTION macros in gl_viewclip_polygon to avoid
64*5f2bebf7SJérôme Gardou  * potential roundoff errors
65*5f2bebf7SJérôme Gardou  *
66*5f2bebf7SJérôme Gardou  * Revision 1.3  1996/09/27 01:24:23  brianp
67*5f2bebf7SJérôme Gardou  * removed unused variables
68*5f2bebf7SJérôme Gardou  *
69*5f2bebf7SJérôme Gardou  * Revision 1.2  1996/09/15 01:48:58  brianp
70*5f2bebf7SJérôme Gardou  * removed #define NULL 0
71*5f2bebf7SJérôme Gardou  *
72*5f2bebf7SJérôme Gardou  * Revision 1.1  1996/09/13 01:38:16  brianp
73*5f2bebf7SJérôme Gardou  * Initial revision
74*5f2bebf7SJérôme Gardou  *
75*5f2bebf7SJérôme Gardou  */
76*5f2bebf7SJérôme Gardou 
77*5f2bebf7SJérôme Gardou 
78*5f2bebf7SJérôme Gardou #ifdef PC_HEADER
79*5f2bebf7SJérôme Gardou #include "all.h"
80*5f2bebf7SJérôme Gardou #else
81*5f2bebf7SJérôme Gardou #include <string.h>
82*5f2bebf7SJérôme Gardou #include "clip.h"
83*5f2bebf7SJérôme Gardou #include "context.h"
84*5f2bebf7SJérôme Gardou #include "dlist.h"
85*5f2bebf7SJérôme Gardou #include "macros.h"
86*5f2bebf7SJérôme Gardou #include "matrix.h"
87*5f2bebf7SJérôme Gardou #include "types.h"
88*5f2bebf7SJérôme Gardou #include "vb.h"
89*5f2bebf7SJérôme Gardou #include "xform.h"
90*5f2bebf7SJérôme Gardou #endif
91*5f2bebf7SJérôme Gardou 
92*5f2bebf7SJérôme Gardou 
93*5f2bebf7SJérôme Gardou 
94*5f2bebf7SJérôme Gardou 
95*5f2bebf7SJérôme Gardou /* Linear interpolation between A and B: */
96*5f2bebf7SJérôme Gardou #define LINTERP( T, A, B )   ( (A) + (T) * ( (B) - (A) ) )
97*5f2bebf7SJérôme Gardou 
98*5f2bebf7SJérôme Gardou 
99*5f2bebf7SJérôme Gardou /* Clipping coordinate spaces */
100*5f2bebf7SJérôme Gardou #define EYE_SPACE 1
101*5f2bebf7SJérôme Gardou #define CLIP_SPACE 2
102*5f2bebf7SJérôme Gardou 
103*5f2bebf7SJérôme Gardou 
104*5f2bebf7SJérôme Gardou 
105*5f2bebf7SJérôme Gardou /*
106*5f2bebf7SJérôme Gardou  * This function is used to interpolate colors, indexes, and texture
107*5f2bebf7SJérôme Gardou  * coordinates when clipping has to be done.  In general, we compute
108*5f2bebf7SJérôme Gardou  *     aux[dst] = aux[in] + t * (aux[out] - aux[in])
109*5f2bebf7SJérôme Gardou  * where aux is the quantity to be interpolated.
110*5f2bebf7SJérôme Gardou  * Input:  space - either EYE_SPACE or CLIP_SPACE
111*5f2bebf7SJérôme Gardou  *         dst - index of array position to store interpolated value
112*5f2bebf7SJérôme Gardou  *         t - a value in [0,1]
113*5f2bebf7SJérôme Gardou  *         in - index of array position corresponding to 'inside' vertex
114*5f2bebf7SJérôme Gardou  *         out - index of array position corresponding to 'outside' vertex
115*5f2bebf7SJérôme Gardou  */
interpolate_aux(GLcontext * ctx,GLuint space,GLuint dst,GLfloat t,GLuint in,GLuint out)116*5f2bebf7SJérôme Gardou void interpolate_aux( GLcontext* ctx, GLuint space,
117*5f2bebf7SJérôme Gardou                       GLuint dst, GLfloat t, GLuint in, GLuint out )
118*5f2bebf7SJérôme Gardou {
119*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
120*5f2bebf7SJérôme Gardou 
121*5f2bebf7SJérôme Gardou    if (ctx->ClipMask & CLIP_FCOLOR_BIT) {
122*5f2bebf7SJérôme Gardou       VB->Fcolor[dst][0] = LINTERP( t, VB->Fcolor[in][0], VB->Fcolor[out][0] );
123*5f2bebf7SJérôme Gardou       VB->Fcolor[dst][1] = LINTERP( t, VB->Fcolor[in][1], VB->Fcolor[out][1] );
124*5f2bebf7SJérôme Gardou       VB->Fcolor[dst][2] = LINTERP( t, VB->Fcolor[in][2], VB->Fcolor[out][2] );
125*5f2bebf7SJérôme Gardou       VB->Fcolor[dst][3] = LINTERP( t, VB->Fcolor[in][3], VB->Fcolor[out][3] );
126*5f2bebf7SJérôme Gardou    }
127*5f2bebf7SJérôme Gardou    else if (ctx->ClipMask & CLIP_FINDEX_BIT) {
128*5f2bebf7SJérôme Gardou       VB->Findex[dst] = (GLuint) (GLint) LINTERP( t, (GLfloat) VB->Findex[in],
129*5f2bebf7SJérôme Gardou                                                  (GLfloat) VB->Findex[out] );
130*5f2bebf7SJérôme Gardou    }
131*5f2bebf7SJérôme Gardou 
132*5f2bebf7SJérôme Gardou    if (ctx->ClipMask & CLIP_BCOLOR_BIT) {
133*5f2bebf7SJérôme Gardou       VB->Bcolor[dst][0] = LINTERP( t, VB->Bcolor[in][0], VB->Bcolor[out][0] );
134*5f2bebf7SJérôme Gardou       VB->Bcolor[dst][1] = LINTERP( t, VB->Bcolor[in][1], VB->Bcolor[out][1] );
135*5f2bebf7SJérôme Gardou       VB->Bcolor[dst][2] = LINTERP( t, VB->Bcolor[in][2], VB->Bcolor[out][2] );
136*5f2bebf7SJérôme Gardou       VB->Bcolor[dst][3] = LINTERP( t, VB->Bcolor[in][3], VB->Bcolor[out][3] );
137*5f2bebf7SJérôme Gardou    }
138*5f2bebf7SJérôme Gardou    else if (ctx->ClipMask & CLIP_BINDEX_BIT) {
139*5f2bebf7SJérôme Gardou       VB->Bindex[dst] = (GLuint) (GLint) LINTERP( t, (GLfloat) VB->Bindex[in],
140*5f2bebf7SJérôme Gardou                                                  (GLfloat) VB->Bindex[out] );
141*5f2bebf7SJérôme Gardou    }
142*5f2bebf7SJérôme Gardou 
143*5f2bebf7SJérôme Gardou    if (ctx->ClipMask & CLIP_TEXTURE_BIT) {
144*5f2bebf7SJérôme Gardou       /* TODO: is more sophisticated texture coord interpolation needed?? */
145*5f2bebf7SJérôme Gardou       if (space==CLIP_SPACE) {
146*5f2bebf7SJérôme Gardou 	 /* also interpolate eye Z component */
147*5f2bebf7SJérôme Gardou 	 VB->Eye[dst][2] = LINTERP( t, VB->Eye[in][2], VB->Eye[out][2] );
148*5f2bebf7SJérôme Gardou       }
149*5f2bebf7SJérôme Gardou       VB->TexCoord[dst][0] = LINTERP(t,VB->TexCoord[in][0],VB->TexCoord[out][0]);
150*5f2bebf7SJérôme Gardou       VB->TexCoord[dst][1] = LINTERP(t,VB->TexCoord[in][1],VB->TexCoord[out][1]);
151*5f2bebf7SJérôme Gardou       VB->TexCoord[dst][2] = LINTERP(t,VB->TexCoord[in][2],VB->TexCoord[out][2]);
152*5f2bebf7SJérôme Gardou       VB->TexCoord[dst][3] = LINTERP(t,VB->TexCoord[in][3],VB->TexCoord[out][3]);
153*5f2bebf7SJérôme Gardou    }
154*5f2bebf7SJérôme Gardou 
155*5f2bebf7SJérôme Gardou }
156*5f2bebf7SJérôme Gardou 
157*5f2bebf7SJérôme Gardou 
158*5f2bebf7SJérôme Gardou /*
159*5f2bebf7SJérôme Gardou  * Some specialized version of the interpolate_aux
160*5f2bebf7SJérôme Gardou  *
161*5f2bebf7SJérôme Gardou  */
162*5f2bebf7SJérôme Gardou 
interpolate_aux_color_tex2(GLcontext * ctx,GLuint space,GLuint dst,GLfloat t,GLuint in,GLuint out)163*5f2bebf7SJérôme Gardou void interpolate_aux_color_tex2( GLcontext* ctx, GLuint space,
164*5f2bebf7SJérôme Gardou 				 GLuint dst, GLfloat t, GLuint in, GLuint out )
165*5f2bebf7SJérôme Gardou {
166*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
167*5f2bebf7SJérôme Gardou 
168*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][0] = LINTERP( t, VB->Fcolor[in][0], VB->Fcolor[out][0] );
169*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][1] = LINTERP( t, VB->Fcolor[in][1], VB->Fcolor[out][1] );
170*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][2] = LINTERP( t, VB->Fcolor[in][2], VB->Fcolor[out][2] );
171*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][3] = LINTERP( t, VB->Fcolor[in][3], VB->Fcolor[out][3] );
172*5f2bebf7SJérôme Gardou 
173*5f2bebf7SJérôme Gardou    VB->Eye[dst][2] = LINTERP( t, VB->Eye[in][2], VB->Eye[out][2] );
174*5f2bebf7SJérôme Gardou    VB->TexCoord[dst][0] = LINTERP(t,VB->TexCoord[in][0],VB->TexCoord[out][0]);
175*5f2bebf7SJérôme Gardou    VB->TexCoord[dst][1] = LINTERP(t,VB->TexCoord[in][1],VB->TexCoord[out][1]);
176*5f2bebf7SJérôme Gardou }
177*5f2bebf7SJérôme Gardou 
178*5f2bebf7SJérôme Gardou 
interpolate_aux_tex2(GLcontext * ctx,GLuint space,GLuint dst,GLfloat t,GLuint in,GLuint out)179*5f2bebf7SJérôme Gardou void interpolate_aux_tex2( GLcontext* ctx, GLuint space,
180*5f2bebf7SJérôme Gardou 			   GLuint dst, GLfloat t, GLuint in, GLuint out )
181*5f2bebf7SJérôme Gardou {
182*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
183*5f2bebf7SJérôme Gardou 
184*5f2bebf7SJérôme Gardou    VB->Eye[dst][2] = LINTERP( t, VB->Eye[in][2], VB->Eye[out][2] );
185*5f2bebf7SJérôme Gardou    VB->TexCoord[dst][0] = LINTERP(t,VB->TexCoord[in][0],VB->TexCoord[out][0]);
186*5f2bebf7SJérôme Gardou    VB->TexCoord[dst][1] = LINTERP(t,VB->TexCoord[in][1],VB->TexCoord[out][1]);
187*5f2bebf7SJérôme Gardou }
188*5f2bebf7SJérôme Gardou 
189*5f2bebf7SJérôme Gardou 
interpolate_aux_color(GLcontext * ctx,GLuint space,GLuint dst,GLfloat t,GLuint in,GLuint out)190*5f2bebf7SJérôme Gardou void interpolate_aux_color( GLcontext* ctx, GLuint space,
191*5f2bebf7SJérôme Gardou 			    GLuint dst, GLfloat t, GLuint in, GLuint out )
192*5f2bebf7SJérôme Gardou {
193*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
194*5f2bebf7SJérôme Gardou 
195*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][0] = LINTERP( t, VB->Fcolor[in][0], VB->Fcolor[out][0] );
196*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][1] = LINTERP( t, VB->Fcolor[in][1], VB->Fcolor[out][1] );
197*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][2] = LINTERP( t, VB->Fcolor[in][2], VB->Fcolor[out][2] );
198*5f2bebf7SJérôme Gardou    VB->Fcolor[dst][3] = LINTERP( t, VB->Fcolor[in][3], VB->Fcolor[out][3] );
199*5f2bebf7SJérôme Gardou }
200*5f2bebf7SJérôme Gardou 
201*5f2bebf7SJérôme Gardou 
202*5f2bebf7SJérôme Gardou 
203*5f2bebf7SJérôme Gardou 
gl_ClipPlane(GLcontext * ctx,GLenum plane,const GLfloat * equation)204*5f2bebf7SJérôme Gardou void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation )
205*5f2bebf7SJérôme Gardou {
206*5f2bebf7SJérôme Gardou    GLint p;
207*5f2bebf7SJérôme Gardou 
208*5f2bebf7SJérôme Gardou    p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
209*5f2bebf7SJérôme Gardou    if (p<0 || p>=MAX_CLIP_PLANES) {
210*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" );
211*5f2bebf7SJérôme Gardou       return;
212*5f2bebf7SJérôme Gardou    }
213*5f2bebf7SJérôme Gardou 
214*5f2bebf7SJérôme Gardou    /*
215*5f2bebf7SJérôme Gardou     * The equation is transformed by the transpose of the inverse of the
216*5f2bebf7SJérôme Gardou     * current modelview matrix and stored in the resulting eye coordinates.
217*5f2bebf7SJérôme Gardou     */
218*5f2bebf7SJérôme Gardou    if (ctx->NewModelViewMatrix) {
219*5f2bebf7SJérôme Gardou       gl_analyze_modelview_matrix(ctx);
220*5f2bebf7SJérôme Gardou    }
221*5f2bebf7SJérôme Gardou    gl_transform_vector( ctx->Transform.ClipEquation[p], equation,
222*5f2bebf7SJérôme Gardou 		        ctx->ModelViewInv );
223*5f2bebf7SJérôme Gardou }
224*5f2bebf7SJérôme Gardou 
225*5f2bebf7SJérôme Gardou 
226*5f2bebf7SJérôme Gardou 
gl_GetClipPlane(GLcontext * ctx,GLenum plane,GLdouble * equation)227*5f2bebf7SJérôme Gardou void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation )
228*5f2bebf7SJérôme Gardou {
229*5f2bebf7SJérôme Gardou    GLint p;
230*5f2bebf7SJérôme Gardou 
231*5f2bebf7SJérôme Gardou    if (INSIDE_BEGIN_END(ctx)) {
232*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glGetClipPlane" );
233*5f2bebf7SJérôme Gardou       return;
234*5f2bebf7SJérôme Gardou    }
235*5f2bebf7SJérôme Gardou 
236*5f2bebf7SJérôme Gardou    p = (GLint) (plane - GL_CLIP_PLANE0);
237*5f2bebf7SJérôme Gardou    if (p<0 || p>=MAX_CLIP_PLANES) {
238*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" );
239*5f2bebf7SJérôme Gardou       return;
240*5f2bebf7SJérôme Gardou    }
241*5f2bebf7SJérôme Gardou 
242*5f2bebf7SJérôme Gardou    equation[0] = (GLdouble) ctx->Transform.ClipEquation[p][0];
243*5f2bebf7SJérôme Gardou    equation[1] = (GLdouble) ctx->Transform.ClipEquation[p][1];
244*5f2bebf7SJérôme Gardou    equation[2] = (GLdouble) ctx->Transform.ClipEquation[p][2];
245*5f2bebf7SJérôme Gardou    equation[3] = (GLdouble) ctx->Transform.ClipEquation[p][3];
246*5f2bebf7SJérôme Gardou }
247*5f2bebf7SJérôme Gardou 
248*5f2bebf7SJérôme Gardou 
249*5f2bebf7SJérôme Gardou 
250*5f2bebf7SJérôme Gardou 
251*5f2bebf7SJérôme Gardou /**********************************************************************/
252*5f2bebf7SJérôme Gardou /*                         View volume clipping.                      */
253*5f2bebf7SJérôme Gardou /**********************************************************************/
254*5f2bebf7SJérôme Gardou 
255*5f2bebf7SJérôme Gardou 
256*5f2bebf7SJérôme Gardou /*
257*5f2bebf7SJérôme Gardou  * Clip a point against the view volume.
258*5f2bebf7SJérôme Gardou  * Input:  v - vertex-vector describing the point to clip
259*5f2bebf7SJérôme Gardou  * Return:  0 = outside view volume
260*5f2bebf7SJérôme Gardou  *          1 = inside view volume
261*5f2bebf7SJérôme Gardou  */
gl_viewclip_point(const GLfloat v[])262*5f2bebf7SJérôme Gardou GLuint gl_viewclip_point( const GLfloat v[] )
263*5f2bebf7SJérôme Gardou {
264*5f2bebf7SJérôme Gardou    if (   v[0] > v[3] || v[0] < -v[3]
265*5f2bebf7SJérôme Gardou        || v[1] > v[3] || v[1] < -v[3]
266*5f2bebf7SJérôme Gardou        || v[2] > v[3] || v[2] < -v[3] ) {
267*5f2bebf7SJérôme Gardou       return 0;
268*5f2bebf7SJérôme Gardou    }
269*5f2bebf7SJérôme Gardou    else {
270*5f2bebf7SJérôme Gardou       return 1;
271*5f2bebf7SJérôme Gardou    }
272*5f2bebf7SJérôme Gardou }
273*5f2bebf7SJérôme Gardou 
274*5f2bebf7SJérôme Gardou 
275*5f2bebf7SJérôme Gardou 
276*5f2bebf7SJérôme Gardou 
277*5f2bebf7SJérôme Gardou /*
278*5f2bebf7SJérôme Gardou  * Clip a line segment against the view volume defined by -w<=x,y,z<=w.
279*5f2bebf7SJérôme Gardou  * Input:  i, j - indexes into VB->V* of endpoints of the line
280*5f2bebf7SJérôme Gardou  * Return:  0 = line completely outside of view
281*5f2bebf7SJérôme Gardou  *          1 = line is inside view.
282*5f2bebf7SJérôme Gardou  */
gl_viewclip_line(GLcontext * ctx,GLuint * i,GLuint * j)283*5f2bebf7SJérôme Gardou GLuint gl_viewclip_line( GLcontext* ctx, GLuint *i, GLuint *j )
284*5f2bebf7SJérôme Gardou {
285*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
286*5f2bebf7SJérôme Gardou    GLfloat (*coord)[4] = VB->Clip;
287*5f2bebf7SJérôme Gardou 
288*5f2bebf7SJérôme Gardou    GLfloat t, dx, dy, dz, dw;
289*5f2bebf7SJérôme Gardou    register GLuint ii, jj;
290*5f2bebf7SJérôme Gardou 
291*5f2bebf7SJérôme Gardou    ii = *i;
292*5f2bebf7SJérôme Gardou    jj = *j;
293*5f2bebf7SJérôme Gardou 
294*5f2bebf7SJérôme Gardou /*
295*5f2bebf7SJérôme Gardou  * We use 6 instances of this code to clip agains the 6 planes.
296*5f2bebf7SJérôme Gardou  * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
297*5f2bebf7SJérôme Gardou  * macros apprpriately.
298*5f2bebf7SJérôme Gardou  */
299*5f2bebf7SJérôme Gardou #define GENERAL_CLIP							\
300*5f2bebf7SJérôme Gardou    if (OUTSIDE(ii)) {           	                        	\
301*5f2bebf7SJérôme Gardou       if (OUTSIDE(jj)) {                	                	\
302*5f2bebf7SJérôme Gardou          /* both verts are outside ==> return 0 */			\
303*5f2bebf7SJérôme Gardou          return 0;                                      		\
304*5f2bebf7SJérôme Gardou       }                                                 		\
305*5f2bebf7SJérôme Gardou       else {                                            		\
306*5f2bebf7SJérôme Gardou          /* ii is outside, jj is inside ==> clip */     		\
307*5f2bebf7SJérôme Gardou 	 /* new vertex put in position VB->Free */			\
308*5f2bebf7SJérôme Gardou          COMPUTE_INTERSECTION( VB->Free, jj, ii )             		\
309*5f2bebf7SJérôme Gardou 	 if (ctx->ClipMask)						\
310*5f2bebf7SJérôme Gardou             ctx->ClipInterpAuxFunc( ctx, CLIP_SPACE, VB->Free, t, jj, ii );\
311*5f2bebf7SJérôme Gardou 	 ii = VB->Free;							\
312*5f2bebf7SJérôme Gardou 	 VB->Free++;							\
313*5f2bebf7SJérôme Gardou 	 if (VB->Free==VB_SIZE)  VB->Free = 1;				\
314*5f2bebf7SJérôme Gardou       }                                                 		\
315*5f2bebf7SJérôme Gardou    }                                                    		\
316*5f2bebf7SJérôme Gardou    else {                                               		\
317*5f2bebf7SJérôme Gardou       if (OUTSIDE(jj)) {                                		\
318*5f2bebf7SJérôme Gardou          /* ii is inside, jj is outside ==> clip */     		\
319*5f2bebf7SJérôme Gardou 	 /* new vertex put in position VB->Free */			\
320*5f2bebf7SJérôme Gardou          COMPUTE_INTERSECTION( VB->Free, ii, jj );            		\
321*5f2bebf7SJérôme Gardou 	 if (ctx->ClipMask)						\
322*5f2bebf7SJérôme Gardou 	    ctx->ClipInterpAuxFunc( ctx, CLIP_SPACE, VB->Free, t, ii, jj );\
323*5f2bebf7SJérôme Gardou 	 jj = VB->Free;							\
324*5f2bebf7SJérôme Gardou 	 VB->Free++;							\
325*5f2bebf7SJérôme Gardou 	 if (VB->Free==VB_SIZE)  VB->Free = 1;				\
326*5f2bebf7SJérôme Gardou       }                                                 		\
327*5f2bebf7SJérôme Gardou       /* else both verts are inside ==> do nothing */   		\
328*5f2bebf7SJérôme Gardou    }
329*5f2bebf7SJérôme Gardou 
330*5f2bebf7SJérôme Gardou 
331*5f2bebf7SJérôme Gardou #define X(I)	coord[I][0]
332*5f2bebf7SJérôme Gardou #define Y(I)	coord[I][1]
333*5f2bebf7SJérôme Gardou #define Z(I)	coord[I][2]
334*5f2bebf7SJérôme Gardou #define W(I)	coord[I][3]
335*5f2bebf7SJérôme Gardou 
336*5f2bebf7SJérôme Gardou /*
337*5f2bebf7SJérôme Gardou  * Begin clipping
338*5f2bebf7SJérôme Gardou  */
339*5f2bebf7SJérôme Gardou 
340*5f2bebf7SJérôme Gardou    /*** Clip against +X side ***/
341*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (X(K) > W(K))
342*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
343*5f2bebf7SJérôme Gardou 	dx = X(out) - X(in);				\
344*5f2bebf7SJérôme Gardou 	dw = W(out) - W(in);				\
345*5f2bebf7SJérôme Gardou 	t = (X(in) - W(in)) / (dw-dx);			\
346*5f2bebf7SJérôme Gardou 	X(new) = X(in) + t * dx;			\
347*5f2bebf7SJérôme Gardou 	Y(new) = Y(in) + t * (Y(out) - Y(in));		\
348*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * (Z(out) - Z(in));		\
349*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
350*5f2bebf7SJérôme Gardou 
351*5f2bebf7SJérôme Gardou    GENERAL_CLIP
352*5f2bebf7SJérôme Gardou 
353*5f2bebf7SJérôme Gardou #undef OUTSIDE
354*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
355*5f2bebf7SJérôme Gardou 
356*5f2bebf7SJérôme Gardou 
357*5f2bebf7SJérôme Gardou    /*** Clip against -X side ***/
358*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (X(K) < -W(K))
359*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
360*5f2bebf7SJérôme Gardou 	dx = X(out) - X(in);				\
361*5f2bebf7SJérôme Gardou 	dw = W(out) - W(in);				\
362*5f2bebf7SJérôme Gardou         t = -(X(in) + W(in)) / (dw+dx);			\
363*5f2bebf7SJérôme Gardou 	X(new) = X(in) + t * dx;			\
364*5f2bebf7SJérôme Gardou 	Y(new) = Y(in) + t * (Y(out) - Y(in));		\
365*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * (Z(out) - Z(in));		\
366*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
367*5f2bebf7SJérôme Gardou 
368*5f2bebf7SJérôme Gardou    GENERAL_CLIP
369*5f2bebf7SJérôme Gardou 
370*5f2bebf7SJérôme Gardou #undef OUTSIDE
371*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
372*5f2bebf7SJérôme Gardou 
373*5f2bebf7SJérôme Gardou 
374*5f2bebf7SJérôme Gardou    /*** Clip against +Y side ***/
375*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (Y(K) > W(K))
376*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
377*5f2bebf7SJérôme Gardou 	dy = Y(out) - Y(in);				\
378*5f2bebf7SJérôme Gardou 	dw = W(out) - W(in);				\
379*5f2bebf7SJérôme Gardou         t = (Y(in) - W(in)) / (dw-dy);			\
380*5f2bebf7SJérôme Gardou 	X(new) = X(in) + t * (X(out) - X(in));		\
381*5f2bebf7SJérôme Gardou 	Y(new) = Y(in) + t * dy;			\
382*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * (Z(out) - Z(in));		\
383*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
384*5f2bebf7SJérôme Gardou 
385*5f2bebf7SJérôme Gardou    GENERAL_CLIP
386*5f2bebf7SJérôme Gardou 
387*5f2bebf7SJérôme Gardou #undef OUTSIDE
388*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
389*5f2bebf7SJérôme Gardou 
390*5f2bebf7SJérôme Gardou 
391*5f2bebf7SJérôme Gardou    /*** Clip against -Y side ***/
392*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (Y(K) < -W(K))
393*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
394*5f2bebf7SJérôme Gardou         dy = Y(out) - Y(in);				\
395*5f2bebf7SJérôme Gardou         dw = W(out) - W(in);				\
396*5f2bebf7SJérôme Gardou         t = -(Y(in) + W(in)) / (dw+dy);			\
397*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
398*5f2bebf7SJérôme Gardou 	Y(new) = Y(in) + t * dy;			\
399*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * (Z(out) - Z(in));		\
400*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
401*5f2bebf7SJérôme Gardou 
402*5f2bebf7SJérôme Gardou    GENERAL_CLIP
403*5f2bebf7SJérôme Gardou 
404*5f2bebf7SJérôme Gardou #undef OUTSIDE
405*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
406*5f2bebf7SJérôme Gardou 
407*5f2bebf7SJérôme Gardou 
408*5f2bebf7SJérôme Gardou    /*** Clip against +Z side ***/
409*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (Z(K) > W(K))
410*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
411*5f2bebf7SJérôme Gardou         dz = Z(out) - Z(in);				\
412*5f2bebf7SJérôme Gardou         dw = W(out) - W(in);				\
413*5f2bebf7SJérôme Gardou         t = (Z(in) - W(in)) / (dw-dz);			\
414*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
415*5f2bebf7SJérôme Gardou         Y(new) = Y(in) + t * (Y(out) - Y(in));		\
416*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * dz;			\
417*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
418*5f2bebf7SJérôme Gardou 
419*5f2bebf7SJérôme Gardou    GENERAL_CLIP
420*5f2bebf7SJérôme Gardou 
421*5f2bebf7SJérôme Gardou #undef OUTSIDE
422*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
423*5f2bebf7SJérôme Gardou 
424*5f2bebf7SJérôme Gardou 
425*5f2bebf7SJérôme Gardou    /*** Clip against -Z side ***/
426*5f2bebf7SJérôme Gardou #define OUTSIDE(K)      (Z(K) < -W(K))
427*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( new, in, out )		\
428*5f2bebf7SJérôme Gardou         dz = Z(out) - Z(in);				\
429*5f2bebf7SJérôme Gardou         dw = W(out) - W(in);				\
430*5f2bebf7SJérôme Gardou         t = -(Z(in) + W(in)) / (dw+dz);			\
431*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
432*5f2bebf7SJérôme Gardou         Y(new) = Y(in) + t * (Y(out) - Y(in));		\
433*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * dz;			\
434*5f2bebf7SJérôme Gardou 	W(new) = W(in) + t * dw;
435*5f2bebf7SJérôme Gardou 
436*5f2bebf7SJérôme Gardou    GENERAL_CLIP
437*5f2bebf7SJérôme Gardou 
438*5f2bebf7SJérôme Gardou #undef OUTSIDE
439*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
440*5f2bebf7SJérôme Gardou 
441*5f2bebf7SJérôme Gardou #undef GENERAL_CLIP
442*5f2bebf7SJérôme Gardou 
443*5f2bebf7SJérôme Gardou    *i = ii;
444*5f2bebf7SJérôme Gardou    *j = jj;
445*5f2bebf7SJérôme Gardou    return 1;
446*5f2bebf7SJérôme Gardou }
447*5f2bebf7SJérôme Gardou 
448*5f2bebf7SJérôme Gardou 
449*5f2bebf7SJérôme Gardou 
450*5f2bebf7SJérôme Gardou 
451*5f2bebf7SJérôme Gardou /*
452*5f2bebf7SJérôme Gardou  * Clip a polygon against the view volume defined by -w<=x,y,z<=w.
453*5f2bebf7SJérôme Gardou  * Input:  n - number of vertices in input polygon.
454*5f2bebf7SJérôme Gardou  *         vlist - list of indexes into VB->V* of polygon to clip.
455*5f2bebf7SJérôme Gardou  * Output:  vlist - modified list of vertex indexes
456*5f2bebf7SJérôme Gardou  * Return:  number of vertices in resulting polygon
457*5f2bebf7SJérôme Gardou  */
gl_viewclip_polygon(GLcontext * ctx,GLuint n,GLuint vlist[])458*5f2bebf7SJérôme Gardou GLuint gl_viewclip_polygon( GLcontext* ctx, GLuint n, GLuint vlist[] )
459*5f2bebf7SJérôme Gardou 
460*5f2bebf7SJérôme Gardou {
461*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
462*5f2bebf7SJérôme Gardou    GLfloat (*coord)[4] = VB->Clip;
463*5f2bebf7SJérôme Gardou 
464*5f2bebf7SJérôme Gardou    GLuint previ, prevj;
465*5f2bebf7SJérôme Gardou    GLuint curri, currj;
466*5f2bebf7SJérôme Gardou    GLuint vlist2[VB_SIZE];
467*5f2bebf7SJérôme Gardou    GLuint n2;
468*5f2bebf7SJérôme Gardou    GLdouble dx, dy, dz, dw, t, neww;
469*5f2bebf7SJérôme Gardou 
470*5f2bebf7SJérôme Gardou /*
471*5f2bebf7SJérôme Gardou  * We use 6 instances of this code to implement clipping against the
472*5f2bebf7SJérôme Gardou  * 6 sides of the view volume.  Prior to each we define the macros:
473*5f2bebf7SJérôme Gardou  *    INLIST = array which lists input vertices
474*5f2bebf7SJérôme Gardou  *    OUTLIST = array which lists output vertices
475*5f2bebf7SJérôme Gardou  *    INCOUNT = variable which is the number of vertices in INLIST[]
476*5f2bebf7SJérôme Gardou  *    OUTCOUNT = variable which is the number of vertices in OUTLIST[]
477*5f2bebf7SJérôme Gardou  *    INSIDE(i) = test if vertex v[i] is inside the view volume
478*5f2bebf7SJérôme Gardou  *    COMPUTE_INTERSECTION(in,out,new) = compute intersection of line
479*5f2bebf7SJérôme Gardou  *              from v[in] to v[out] with the clipping plane and store
480*5f2bebf7SJérôme Gardou  *              the result in v[new]
481*5f2bebf7SJérôme Gardou  */
482*5f2bebf7SJérôme Gardou 
483*5f2bebf7SJérôme Gardou #define GENERAL_CLIP                                                    \
484*5f2bebf7SJérôme Gardou    if (INCOUNT<3)  return 0;						\
485*5f2bebf7SJérôme Gardou    previ = INCOUNT-1;		/* let previous = last vertex */	\
486*5f2bebf7SJérôme Gardou    prevj = INLIST[previ];						\
487*5f2bebf7SJérôme Gardou    OUTCOUNT = 0;                                                        \
488*5f2bebf7SJérôme Gardou    for (curri=0;curri<INCOUNT;curri++) {				\
489*5f2bebf7SJérôme Gardou       currj = INLIST[curri];						\
490*5f2bebf7SJérôme Gardou       if (INSIDE(currj)) {						\
491*5f2bebf7SJérôme Gardou          if (INSIDE(prevj)) {						\
492*5f2bebf7SJérôme Gardou             /* both verts are inside ==> copy current to outlist */     \
493*5f2bebf7SJérôme Gardou 	    OUTLIST[OUTCOUNT] = currj;					\
494*5f2bebf7SJérôme Gardou 	    OUTCOUNT++;							\
495*5f2bebf7SJérôme Gardou          }                                                              \
496*5f2bebf7SJérôme Gardou          else {                                                         \
497*5f2bebf7SJérôme Gardou             /* current is inside and previous is outside ==> clip */	\
498*5f2bebf7SJérôme Gardou 	    COMPUTE_INTERSECTION( currj, prevj,	VB->Free )		\
499*5f2bebf7SJérôme Gardou 	    /* if new point not coincident with previous point... */	\
500*5f2bebf7SJérôme Gardou 	    if (t>0.0) {						\
501*5f2bebf7SJérôme Gardou 	       /* interpolate aux info using the value of t */		\
502*5f2bebf7SJérôme Gardou 	       if (ctx->ClipMask)					\
503*5f2bebf7SJérôme Gardou 		  ctx->ClipInterpAuxFunc( ctx, CLIP_SPACE, VB->Free, t, currj, prevj ); \
504*5f2bebf7SJérôme Gardou 	       VB->Edgeflag[VB->Free] = VB->Edgeflag[prevj];		\
505*5f2bebf7SJérôme Gardou 	       /* output new point */					\
506*5f2bebf7SJérôme Gardou 	       OUTLIST[OUTCOUNT] = VB->Free;				\
507*5f2bebf7SJérôme Gardou 	       VB->Free++;						\
508*5f2bebf7SJérôme Gardou 	       if (VB->Free==VB_SIZE)   VB->Free = 1;			\
509*5f2bebf7SJérôme Gardou 	       OUTCOUNT++;						\
510*5f2bebf7SJérôme Gardou 	    }								\
511*5f2bebf7SJérôme Gardou 	    /* Output current */					\
512*5f2bebf7SJérôme Gardou 	    OUTLIST[OUTCOUNT] = currj;					\
513*5f2bebf7SJérôme Gardou 	    OUTCOUNT++;							\
514*5f2bebf7SJérôme Gardou          }                                                              \
515*5f2bebf7SJérôme Gardou       }                                                                 \
516*5f2bebf7SJérôme Gardou       else {                                                            \
517*5f2bebf7SJérôme Gardou          if (INSIDE(prevj)) {						\
518*5f2bebf7SJérôme Gardou             /* current is outside and previous is inside ==> clip */	\
519*5f2bebf7SJérôme Gardou 	    COMPUTE_INTERSECTION( prevj, currj, VB->Free )		\
520*5f2bebf7SJérôme Gardou 	    /* if new point not coincident with previous point... */	\
521*5f2bebf7SJérôme Gardou 	    if (t>0.0) {						\
522*5f2bebf7SJérôme Gardou 	       /* interpolate aux info using the value of t */		\
523*5f2bebf7SJérôme Gardou 	       if (ctx->ClipMask)					\
524*5f2bebf7SJérôme Gardou 		  ctx->ClipInterpAuxFunc( ctx, CLIP_SPACE, VB->Free, t, prevj, currj ); \
525*5f2bebf7SJérôme Gardou 	       VB->Edgeflag[VB->Free] = VB->Edgeflag[prevj];		\
526*5f2bebf7SJérôme Gardou 	       /* output new point */					\
527*5f2bebf7SJérôme Gardou 	       OUTLIST[OUTCOUNT] = VB->Free;				\
528*5f2bebf7SJérôme Gardou 	       VB->Free++;						\
529*5f2bebf7SJérôme Gardou 	       if (VB->Free==VB_SIZE)   VB->Free = 1;			\
530*5f2bebf7SJérôme Gardou 	       OUTCOUNT++;						\
531*5f2bebf7SJérôme Gardou 	    }								\
532*5f2bebf7SJérôme Gardou          }								\
533*5f2bebf7SJérôme Gardou          /* else both verts are outside ==> do nothing */		\
534*5f2bebf7SJérôme Gardou       }									\
535*5f2bebf7SJérôme Gardou       /* let previous = current */					\
536*5f2bebf7SJérôme Gardou       previ = curri;							\
537*5f2bebf7SJérôme Gardou       prevj = currj;							\
538*5f2bebf7SJérôme Gardou       /* check for overflowing vertex buffer */				\
539*5f2bebf7SJérôme Gardou       if (OUTCOUNT>=VB_SIZE-1) {					\
540*5f2bebf7SJérôme Gardou 	 /* Too many vertices */					\
541*5f2bebf7SJérôme Gardou          if (OUTLIST==vlist2) {						\
542*5f2bebf7SJérôme Gardou 	    /* copy OUTLIST[] to vlist[] */				\
543*5f2bebf7SJérôme Gardou 	    int i;							\
544*5f2bebf7SJérôme Gardou 	    for (i=0;i<VB_SIZE;i++) {					\
545*5f2bebf7SJérôme Gardou 	       vlist[i] = OUTLIST[i];					\
546*5f2bebf7SJérôme Gardou 	    }								\
547*5f2bebf7SJérôme Gardou 	 }								\
548*5f2bebf7SJérôme Gardou 	 return VB_SIZE-1;						\
549*5f2bebf7SJérôme Gardou       }									\
550*5f2bebf7SJérôme Gardou    }
551*5f2bebf7SJérôme Gardou 
552*5f2bebf7SJérôme Gardou 
553*5f2bebf7SJérôme Gardou #define X(I)	coord[I][0]
554*5f2bebf7SJérôme Gardou #define Y(I)	coord[I][1]
555*5f2bebf7SJérôme Gardou #define Z(I)	coord[I][2]
556*5f2bebf7SJérôme Gardou #define W(I)	coord[I][3]
557*5f2bebf7SJérôme Gardou 
558*5f2bebf7SJérôme Gardou /*
559*5f2bebf7SJérôme Gardou  * Clip against +X
560*5f2bebf7SJérôme Gardou  */
561*5f2bebf7SJérôme Gardou #define INCOUNT n
562*5f2bebf7SJérôme Gardou #define OUTCOUNT n2
563*5f2bebf7SJérôme Gardou #define INLIST vlist
564*5f2bebf7SJérôme Gardou #define OUTLIST vlist2
565*5f2bebf7SJérôme Gardou #define INSIDE(K)      (X(K) <= W(K))
566*5f2bebf7SJérôme Gardou 
567*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
568*5f2bebf7SJérôme Gardou         dx = X(out) - X(in);				\
569*5f2bebf7SJérôme Gardou         dw = W(out) - W(in);				\
570*5f2bebf7SJérôme Gardou         t = (X(in)-W(in)) / (dw-dx);			\
571*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw;				\
572*5f2bebf7SJérôme Gardou 	X(new) = neww;					\
573*5f2bebf7SJérôme Gardou 	Y(new) = Y(in) + t * (Y(out) - Y(in));		\
574*5f2bebf7SJérôme Gardou 	Z(new) = Z(in) + t * (Z(out) - Z(in)); 		\
575*5f2bebf7SJérôme Gardou 	W(new) = neww;
576*5f2bebf7SJérôme Gardou 
577*5f2bebf7SJérôme Gardou    GENERAL_CLIP
578*5f2bebf7SJérôme Gardou 
579*5f2bebf7SJérôme Gardou #undef INCOUNT
580*5f2bebf7SJérôme Gardou #undef OUTCOUNT
581*5f2bebf7SJérôme Gardou #undef INLIST
582*5f2bebf7SJérôme Gardou #undef OUTLIST
583*5f2bebf7SJérôme Gardou #undef INSIDE
584*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
585*5f2bebf7SJérôme Gardou 
586*5f2bebf7SJérôme Gardou 
587*5f2bebf7SJérôme Gardou /*
588*5f2bebf7SJérôme Gardou  * Clip against -X
589*5f2bebf7SJérôme Gardou  */
590*5f2bebf7SJérôme Gardou #define INCOUNT n2
591*5f2bebf7SJérôme Gardou #define OUTCOUNT n
592*5f2bebf7SJérôme Gardou #define INLIST vlist2
593*5f2bebf7SJérôme Gardou #define OUTLIST vlist
594*5f2bebf7SJérôme Gardou #define INSIDE(K)       (X(K) >= -W(K))
595*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
596*5f2bebf7SJérôme Gardou         dx = X(out)-X(in);                      	\
597*5f2bebf7SJérôme Gardou         dw = W(out)-W(in);                      	\
598*5f2bebf7SJérôme Gardou         t = -(X(in)+W(in)) / (dw+dx);           	\
599*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw;				\
600*5f2bebf7SJérôme Gardou         X(new) = -neww;					\
601*5f2bebf7SJérôme Gardou         Y(new) = Y(in) + t * (Y(out) - Y(in));		\
602*5f2bebf7SJérôme Gardou         Z(new) = Z(in) + t * (Z(out) - Z(in));		\
603*5f2bebf7SJérôme Gardou         W(new) = neww;
604*5f2bebf7SJérôme Gardou 
605*5f2bebf7SJérôme Gardou    GENERAL_CLIP
606*5f2bebf7SJérôme Gardou 
607*5f2bebf7SJérôme Gardou #undef INCOUNT
608*5f2bebf7SJérôme Gardou #undef OUTCOUNT
609*5f2bebf7SJérôme Gardou #undef INLIST
610*5f2bebf7SJérôme Gardou #undef OUTLIST
611*5f2bebf7SJérôme Gardou #undef INSIDE
612*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
613*5f2bebf7SJérôme Gardou 
614*5f2bebf7SJérôme Gardou 
615*5f2bebf7SJérôme Gardou /*
616*5f2bebf7SJérôme Gardou  * Clip against +Y
617*5f2bebf7SJérôme Gardou  */
618*5f2bebf7SJérôme Gardou #define INCOUNT n
619*5f2bebf7SJérôme Gardou #define OUTCOUNT n2
620*5f2bebf7SJérôme Gardou #define INLIST vlist
621*5f2bebf7SJérôme Gardou #define OUTLIST vlist2
622*5f2bebf7SJérôme Gardou #define INSIDE(K)       (Y(K) <= W(K))
623*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
624*5f2bebf7SJérôme Gardou         dy = Y(out)-Y(in);                      	\
625*5f2bebf7SJérôme Gardou         dw = W(out)-W(in);                      	\
626*5f2bebf7SJérôme Gardou         t = (Y(in)-W(in)) / (dw-dy);            	\
627*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw; 				\
628*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
629*5f2bebf7SJérôme Gardou         Y(new) = neww;					\
630*5f2bebf7SJérôme Gardou         Z(new) = Z(in) + t * (Z(out) - Z(in));		\
631*5f2bebf7SJérôme Gardou         W(new) = neww;
632*5f2bebf7SJérôme Gardou 
633*5f2bebf7SJérôme Gardou    GENERAL_CLIP
634*5f2bebf7SJérôme Gardou 
635*5f2bebf7SJérôme Gardou #undef INCOUNT
636*5f2bebf7SJérôme Gardou #undef OUTCOUNT
637*5f2bebf7SJérôme Gardou #undef INLIST
638*5f2bebf7SJérôme Gardou #undef OUTLIST
639*5f2bebf7SJérôme Gardou #undef INSIDE
640*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
641*5f2bebf7SJérôme Gardou 
642*5f2bebf7SJérôme Gardou 
643*5f2bebf7SJérôme Gardou /*
644*5f2bebf7SJérôme Gardou  * Clip against -Y
645*5f2bebf7SJérôme Gardou  */
646*5f2bebf7SJérôme Gardou #define INCOUNT n2
647*5f2bebf7SJérôme Gardou #define OUTCOUNT n
648*5f2bebf7SJérôme Gardou #define INLIST vlist2
649*5f2bebf7SJérôme Gardou #define OUTLIST vlist
650*5f2bebf7SJérôme Gardou #define INSIDE(K)       (Y(K) >= -W(K))
651*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
652*5f2bebf7SJérôme Gardou         dy = Y(out)-Y(in);                      	\
653*5f2bebf7SJérôme Gardou         dw = W(out)-W(in);                      	\
654*5f2bebf7SJérôme Gardou         t = -(Y(in)+W(in)) / (dw+dy);           	\
655*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw;				\
656*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
657*5f2bebf7SJérôme Gardou         Y(new) = -neww;					\
658*5f2bebf7SJérôme Gardou         Z(new) = Z(in) + t * (Z(out) - Z(in));		\
659*5f2bebf7SJérôme Gardou         W(new) = neww;
660*5f2bebf7SJérôme Gardou 
661*5f2bebf7SJérôme Gardou    GENERAL_CLIP
662*5f2bebf7SJérôme Gardou 
663*5f2bebf7SJérôme Gardou #undef INCOUNT
664*5f2bebf7SJérôme Gardou #undef OUTCOUNT
665*5f2bebf7SJérôme Gardou #undef INLIST
666*5f2bebf7SJérôme Gardou #undef OUTLIST
667*5f2bebf7SJérôme Gardou #undef INSIDE
668*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
669*5f2bebf7SJérôme Gardou 
670*5f2bebf7SJérôme Gardou 
671*5f2bebf7SJérôme Gardou 
672*5f2bebf7SJérôme Gardou /*
673*5f2bebf7SJérôme Gardou  * Clip against +Z
674*5f2bebf7SJérôme Gardou  */
675*5f2bebf7SJérôme Gardou #define INCOUNT n
676*5f2bebf7SJérôme Gardou #define OUTCOUNT n2
677*5f2bebf7SJérôme Gardou #define INLIST vlist
678*5f2bebf7SJérôme Gardou #define OUTLIST vlist2
679*5f2bebf7SJérôme Gardou #define INSIDE(K)       (Z(K) <= W(K))
680*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
681*5f2bebf7SJérôme Gardou         dz = Z(out)-Z(in);                      	\
682*5f2bebf7SJérôme Gardou         dw = W(out)-W(in);                      	\
683*5f2bebf7SJérôme Gardou         t = (Z(in)-W(in)) / (dw-dz);            	\
684*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw;				\
685*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
686*5f2bebf7SJérôme Gardou         Y(new) = Y(in) + t * (Y(out) - Y(in));		\
687*5f2bebf7SJérôme Gardou         Z(new) = neww;					\
688*5f2bebf7SJérôme Gardou         W(new) = neww;
689*5f2bebf7SJérôme Gardou 
690*5f2bebf7SJérôme Gardou    GENERAL_CLIP
691*5f2bebf7SJérôme Gardou 
692*5f2bebf7SJérôme Gardou #undef INCOUNT
693*5f2bebf7SJérôme Gardou #undef OUTCOUNT
694*5f2bebf7SJérôme Gardou #undef INLIST
695*5f2bebf7SJérôme Gardou #undef OUTLIST
696*5f2bebf7SJérôme Gardou #undef INSIDE
697*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
698*5f2bebf7SJérôme Gardou 
699*5f2bebf7SJérôme Gardou 
700*5f2bebf7SJérôme Gardou /*
701*5f2bebf7SJérôme Gardou  * Clip against -Z
702*5f2bebf7SJérôme Gardou  */
703*5f2bebf7SJérôme Gardou #define INCOUNT n2
704*5f2bebf7SJérôme Gardou #define OUTCOUNT n
705*5f2bebf7SJérôme Gardou #define INLIST vlist2
706*5f2bebf7SJérôme Gardou #define OUTLIST vlist
707*5f2bebf7SJérôme Gardou #define INSIDE(K)       (Z(K) >= -W(K))
708*5f2bebf7SJérôme Gardou #define COMPUTE_INTERSECTION( in, out, new )		\
709*5f2bebf7SJérôme Gardou         dz = Z(out)-Z(in);                      	\
710*5f2bebf7SJérôme Gardou         dw = W(out)-W(in);                      	\
711*5f2bebf7SJérôme Gardou         t = -(Z(in)+W(in)) / (dw+dz);           	\
712*5f2bebf7SJérôme Gardou 	neww = W(in) + t * dw;				\
713*5f2bebf7SJérôme Gardou         X(new) = X(in) + t * (X(out) - X(in));		\
714*5f2bebf7SJérôme Gardou         Y(new) = Y(in) + t * (Y(out) - Y(in));		\
715*5f2bebf7SJérôme Gardou         Z(new) = -neww;					\
716*5f2bebf7SJérôme Gardou         W(new) = neww;
717*5f2bebf7SJérôme Gardou 
718*5f2bebf7SJérôme Gardou    GENERAL_CLIP
719*5f2bebf7SJérôme Gardou 
720*5f2bebf7SJérôme Gardou #undef INCOUNT
721*5f2bebf7SJérôme Gardou #undef INLIST
722*5f2bebf7SJérôme Gardou #undef OUTLIST
723*5f2bebf7SJérôme Gardou #undef INSIDE
724*5f2bebf7SJérôme Gardou #undef COMPUTE_INTERSECTION
725*5f2bebf7SJérôme Gardou 
726*5f2bebf7SJérôme Gardou    /* 'OUTCOUNT' clipped vertices are now back in v[] */
727*5f2bebf7SJérôme Gardou    return OUTCOUNT;
728*5f2bebf7SJérôme Gardou 
729*5f2bebf7SJérôme Gardou #undef GENERAL_CLIP
730*5f2bebf7SJérôme Gardou #undef OUTCOUNT
731*5f2bebf7SJérôme Gardou }
732*5f2bebf7SJérôme Gardou 
733*5f2bebf7SJérôme Gardou 
734*5f2bebf7SJérôme Gardou 
735*5f2bebf7SJérôme Gardou 
736*5f2bebf7SJérôme Gardou /**********************************************************************/
737*5f2bebf7SJérôme Gardou /*         Clipping against user-defined clipping planes.             */
738*5f2bebf7SJérôme Gardou /**********************************************************************/
739*5f2bebf7SJérôme Gardou 
740*5f2bebf7SJérôme Gardou 
741*5f2bebf7SJérôme Gardou 
742*5f2bebf7SJérôme Gardou /*
743*5f2bebf7SJérôme Gardou  * If the dot product of the eye coordinates of a vertex with the
744*5f2bebf7SJérôme Gardou  * stored plane equation components is positive or zero, the vertex
745*5f2bebf7SJérôme Gardou  * is in with respect to that clipping plane, otherwise it is out.
746*5f2bebf7SJérôme Gardou  */
747*5f2bebf7SJérôme Gardou 
748*5f2bebf7SJérôme Gardou 
749*5f2bebf7SJérôme Gardou 
750*5f2bebf7SJérôme Gardou /*
751*5f2bebf7SJérôme Gardou  * Clip a point against the user clipping planes.
752*5f2bebf7SJérôme Gardou  * Input:  v - vertex-vector describing the point to clip.
753*5f2bebf7SJérôme Gardou  * Return:  0 = point was clipped
754*5f2bebf7SJérôme Gardou  *          1 = point not clipped
755*5f2bebf7SJérôme Gardou  */
gl_userclip_point(GLcontext * ctx,const GLfloat v[])756*5f2bebf7SJérôme Gardou GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] )
757*5f2bebf7SJérôme Gardou {
758*5f2bebf7SJérôme Gardou    GLuint p;
759*5f2bebf7SJérôme Gardou 
760*5f2bebf7SJérôme Gardou    for (p=0;p<MAX_CLIP_PLANES;p++) {
761*5f2bebf7SJérôme Gardou       if (ctx->Transform.ClipEnabled[p]) {
762*5f2bebf7SJérôme Gardou 	 GLfloat dot = v[0] * ctx->Transform.ClipEquation[p][0]
763*5f2bebf7SJérôme Gardou 		     + v[1] * ctx->Transform.ClipEquation[p][1]
764*5f2bebf7SJérôme Gardou 		     + v[2] * ctx->Transform.ClipEquation[p][2]
765*5f2bebf7SJérôme Gardou 		     + v[3] * ctx->Transform.ClipEquation[p][3];
766*5f2bebf7SJérôme Gardou          if (dot < 0.0F) {
767*5f2bebf7SJérôme Gardou             return 0;
768*5f2bebf7SJérôme Gardou          }
769*5f2bebf7SJérôme Gardou       }
770*5f2bebf7SJérôme Gardou    }
771*5f2bebf7SJérôme Gardou 
772*5f2bebf7SJérôme Gardou    return 1;
773*5f2bebf7SJérôme Gardou }
774*5f2bebf7SJérôme Gardou 
775*5f2bebf7SJérôme Gardou 
776*5f2bebf7SJérôme Gardou #define MAGIC_NUMBER -0.8e-03F
777*5f2bebf7SJérôme Gardou 
778*5f2bebf7SJérôme Gardou 
779*5f2bebf7SJérôme Gardou /* Test if VB->Eye[J] is inside the clipping plane defined by A,B,C,D */
780*5f2bebf7SJérôme Gardou #define INSIDE( J, A, B, C, D )   				\
781*5f2bebf7SJérôme Gardou    ( (VB->Eye[J][0] * A + VB->Eye[J][1] * B			\
782*5f2bebf7SJérôme Gardou     + VB->Eye[J][2] * C + VB->Eye[J][3] * D) >= MAGIC_NUMBER )
783*5f2bebf7SJérôme Gardou 
784*5f2bebf7SJérôme Gardou 
785*5f2bebf7SJérôme Gardou /* Test if VB->Eye[J] is outside the clipping plane defined by A,B,C,D */
786*5f2bebf7SJérôme Gardou #define OUTSIDE( J, A, B, C, D )   				\
787*5f2bebf7SJérôme Gardou    ( (VB->Eye[J][0] * A + VB->Eye[J][1] * B			\
788*5f2bebf7SJérôme Gardou     + VB->Eye[J][2] * C + VB->Eye[J][3] * D) < MAGIC_NUMBER )
789*5f2bebf7SJérôme Gardou 
790*5f2bebf7SJérôme Gardou 
791*5f2bebf7SJérôme Gardou /*
792*5f2bebf7SJérôme Gardou  * Clip a line against the user clipping planes.
793*5f2bebf7SJérôme Gardou  * Input:  i, j - indexes into VB->V*[] of endpoints
794*5f2bebf7SJérôme Gardou  * Output:  i, j - indexes into VB->V*[] of (possibly clipped) endpoints
795*5f2bebf7SJérôme Gardou  * Return:  0 = line completely clipped
796*5f2bebf7SJérôme Gardou  *          1 = line is visible
797*5f2bebf7SJérôme Gardou  */
gl_userclip_line(GLcontext * ctx,GLuint * i,GLuint * j)798*5f2bebf7SJérôme Gardou GLuint gl_userclip_line( GLcontext* ctx, GLuint *i, GLuint *j )
799*5f2bebf7SJérôme Gardou {
800*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
801*5f2bebf7SJérôme Gardou 
802*5f2bebf7SJérôme Gardou    GLuint p, ii, jj;
803*5f2bebf7SJérôme Gardou 
804*5f2bebf7SJérôme Gardou    ii = *i;
805*5f2bebf7SJérôme Gardou    jj = *j;
806*5f2bebf7SJérôme Gardou 
807*5f2bebf7SJérôme Gardou    for (p=0;p<MAX_CLIP_PLANES;p++) {
808*5f2bebf7SJérôme Gardou       if (ctx->Transform.ClipEnabled[p]) {
809*5f2bebf7SJérôme Gardou 	 register GLfloat a, b, c, d;
810*5f2bebf7SJérôme Gardou 	 a = ctx->Transform.ClipEquation[p][0];
811*5f2bebf7SJérôme Gardou 	 b = ctx->Transform.ClipEquation[p][1];
812*5f2bebf7SJérôme Gardou 	 c = ctx->Transform.ClipEquation[p][2];
813*5f2bebf7SJérôme Gardou 	 d = ctx->Transform.ClipEquation[p][3];
814*5f2bebf7SJérôme Gardou 
815*5f2bebf7SJérôme Gardou          if (OUTSIDE( ii, a,b,c,d  )) {
816*5f2bebf7SJérôme Gardou             if (OUTSIDE( jj, a,b,c,d )) {
817*5f2bebf7SJérôme Gardou                /* ii and jj outside ==> quit */
818*5f2bebf7SJérôme Gardou                return 0;
819*5f2bebf7SJérôme Gardou             }
820*5f2bebf7SJérôme Gardou             else {
821*5f2bebf7SJérôme Gardou                /* ii is outside, jj is inside ==> clip */
822*5f2bebf7SJérôme Gardou                GLfloat dx, dy, dz, dw, t, denom;
823*5f2bebf7SJérôme Gardou                dx = VB->Eye[ii][0] - VB->Eye[jj][0];
824*5f2bebf7SJérôme Gardou                dy = VB->Eye[ii][1] - VB->Eye[jj][1];
825*5f2bebf7SJérôme Gardou                dz = VB->Eye[ii][2] - VB->Eye[jj][2];
826*5f2bebf7SJérôme Gardou                dw = VB->Eye[ii][3] - VB->Eye[jj][3];
827*5f2bebf7SJérôme Gardou 	       denom = dx*a + dy*b + dz*c + dw*d;
828*5f2bebf7SJérôme Gardou 	       if (denom==0.0) {
829*5f2bebf7SJérôme Gardou 		  t = 0.0;
830*5f2bebf7SJérôme Gardou 	       }
831*5f2bebf7SJérôme Gardou 	       else {
832*5f2bebf7SJérôme Gardou 		  t = -(VB->Eye[jj][0]*a+VB->Eye[jj][1]*b
833*5f2bebf7SJérôme Gardou 		       +VB->Eye[jj][2]*c+VB->Eye[jj][3]*d) / denom;
834*5f2bebf7SJérôme Gardou                   if (t>1.0F)  t = 1.0F;
835*5f2bebf7SJérôme Gardou 	       }
836*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][0] = VB->Eye[jj][0] + t * dx;
837*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][1] = VB->Eye[jj][1] + t * dy;
838*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][2] = VB->Eye[jj][2] + t * dz;
839*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][3] = VB->Eye[jj][3] + t * dw;
840*5f2bebf7SJérôme Gardou 
841*5f2bebf7SJérôme Gardou 	       /* Interpolate colors, indexes, and/or texture coords */
842*5f2bebf7SJérôme Gardou 	       if (ctx->ClipMask)
843*5f2bebf7SJérôme Gardou 		  interpolate_aux( ctx, EYE_SPACE, VB->Free, t, jj, ii );
844*5f2bebf7SJérôme Gardou 
845*5f2bebf7SJérôme Gardou 	       ii = VB->Free;
846*5f2bebf7SJérôme Gardou 	       VB->Free++;
847*5f2bebf7SJérôme Gardou 	       if (VB->Free==VB_SIZE)   VB->Free = 1;
848*5f2bebf7SJérôme Gardou             }
849*5f2bebf7SJérôme Gardou          }
850*5f2bebf7SJérôme Gardou          else {
851*5f2bebf7SJérôme Gardou             if (OUTSIDE( jj, a,b,c,d )) {
852*5f2bebf7SJérôme Gardou                /* ii is inside, jj is outside ==> clip */
853*5f2bebf7SJérôme Gardou                GLfloat dx, dy, dz, dw, t, denom;
854*5f2bebf7SJérôme Gardou                dx = VB->Eye[jj][0] - VB->Eye[ii][0];
855*5f2bebf7SJérôme Gardou                dy = VB->Eye[jj][1] - VB->Eye[ii][1];
856*5f2bebf7SJérôme Gardou                dz = VB->Eye[jj][2] - VB->Eye[ii][2];
857*5f2bebf7SJérôme Gardou                dw = VB->Eye[jj][3] - VB->Eye[ii][3];
858*5f2bebf7SJérôme Gardou 	       denom = dx*a + dy*b + dz*c + dw*d;
859*5f2bebf7SJérôme Gardou 	       if (denom==0.0) {
860*5f2bebf7SJérôme Gardou 		  t = 0.0;
861*5f2bebf7SJérôme Gardou 	       }
862*5f2bebf7SJérôme Gardou 	       else {
863*5f2bebf7SJérôme Gardou 		  t = -(VB->Eye[ii][0]*a+VB->Eye[ii][1]*b
864*5f2bebf7SJérôme Gardou 		       +VB->Eye[ii][2]*c+VB->Eye[ii][3]*d) / denom;
865*5f2bebf7SJérôme Gardou                   if (t>1.0F)  t = 1.0F;
866*5f2bebf7SJérôme Gardou 	       }
867*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][0] = VB->Eye[ii][0] + t * dx;
868*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][1] = VB->Eye[ii][1] + t * dy;
869*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][2] = VB->Eye[ii][2] + t * dz;
870*5f2bebf7SJérôme Gardou 	       VB->Eye[VB->Free][3] = VB->Eye[ii][3] + t * dw;
871*5f2bebf7SJérôme Gardou 
872*5f2bebf7SJérôme Gardou 	       /* Interpolate colors, indexes, and/or texture coords */
873*5f2bebf7SJérôme Gardou 	       if (ctx->ClipMask)
874*5f2bebf7SJérôme Gardou 		  interpolate_aux( ctx, EYE_SPACE, VB->Free, t, ii, jj );
875*5f2bebf7SJérôme Gardou 
876*5f2bebf7SJérôme Gardou 	       jj = VB->Free;
877*5f2bebf7SJérôme Gardou 	       VB->Free++;
878*5f2bebf7SJérôme Gardou 	       if (VB->Free==VB_SIZE)   VB->Free = 1;
879*5f2bebf7SJérôme Gardou             }
880*5f2bebf7SJérôme Gardou             else {
881*5f2bebf7SJérôme Gardou                /* ii and jj inside ==> do nothing */
882*5f2bebf7SJérôme Gardou             }
883*5f2bebf7SJérôme Gardou          }
884*5f2bebf7SJérôme Gardou       }
885*5f2bebf7SJérôme Gardou    }
886*5f2bebf7SJérôme Gardou 
887*5f2bebf7SJérôme Gardou    *i = ii;
888*5f2bebf7SJérôme Gardou    *j = jj;
889*5f2bebf7SJérôme Gardou    return 1;
890*5f2bebf7SJérôme Gardou }
891*5f2bebf7SJérôme Gardou 
892*5f2bebf7SJérôme Gardou 
893*5f2bebf7SJérôme Gardou 
894*5f2bebf7SJérôme Gardou 
895*5f2bebf7SJérôme Gardou /*
896*5f2bebf7SJérôme Gardou  * Clip a polygon against the user clipping planes defined in eye coordinates.
897*5f2bebf7SJérôme Gardou  * Input:  n - number of vertices.
898*5f2bebf7SJérôme Gardou  *         vlist - list of vertices in input polygon.
899*5f2bebf7SJérôme Gardou  * Output:  vlist - list of vertices in output polygon.
900*5f2bebf7SJérôme Gardou  * Return:  number of vertices after clipping.
901*5f2bebf7SJérôme Gardou  */
gl_userclip_polygon(GLcontext * ctx,GLuint n,GLuint vlist[])902*5f2bebf7SJérôme Gardou GLuint gl_userclip_polygon( GLcontext* ctx, GLuint n, GLuint vlist[] )
903*5f2bebf7SJérôme Gardou {
904*5f2bebf7SJérôme Gardou    struct vertex_buffer* VB = ctx->VB;
905*5f2bebf7SJérôme Gardou 
906*5f2bebf7SJérôme Gardou    GLuint vlist2[VB_SIZE];
907*5f2bebf7SJérôme Gardou    GLuint *inlist, *outlist;
908*5f2bebf7SJérôme Gardou    GLuint incount, outcount;
909*5f2bebf7SJérôme Gardou    GLuint curri, currj;
910*5f2bebf7SJérôme Gardou    GLuint previ, prevj;
911*5f2bebf7SJérôme Gardou    GLuint p;
912*5f2bebf7SJérôme Gardou 
913*5f2bebf7SJérôme Gardou    /* initialize input vertex list */
914*5f2bebf7SJérôme Gardou    incount = n;
915*5f2bebf7SJérôme Gardou    inlist = vlist;
916*5f2bebf7SJérôme Gardou    outlist = vlist2;
917*5f2bebf7SJérôme Gardou 
918*5f2bebf7SJérôme Gardou    for (p=0;p<MAX_CLIP_PLANES;p++) {
919*5f2bebf7SJérôme Gardou       if (ctx->Transform.ClipEnabled[p]) {
920*5f2bebf7SJérôme Gardou 	 register float a = ctx->Transform.ClipEquation[p][0];
921*5f2bebf7SJérôme Gardou 	 register float b = ctx->Transform.ClipEquation[p][1];
922*5f2bebf7SJérôme Gardou 	 register float c = ctx->Transform.ClipEquation[p][2];
923*5f2bebf7SJérôme Gardou 	 register float d = ctx->Transform.ClipEquation[p][3];
924*5f2bebf7SJérôme Gardou 
925*5f2bebf7SJérôme Gardou 	 if (incount<3)  return 0;
926*5f2bebf7SJérôme Gardou 
927*5f2bebf7SJérôme Gardou 	 /* initialize prev to be last in the input list */
928*5f2bebf7SJérôme Gardou 	 previ = incount - 1;
929*5f2bebf7SJérôme Gardou 	 prevj = inlist[previ];
930*5f2bebf7SJérôme Gardou 
931*5f2bebf7SJérôme Gardou          outcount = 0;
932*5f2bebf7SJérôme Gardou 
933*5f2bebf7SJérôme Gardou          for (curri=0;curri<incount;curri++) {
934*5f2bebf7SJérôme Gardou 	    currj = inlist[curri];
935*5f2bebf7SJérôme Gardou 
936*5f2bebf7SJérôme Gardou             if (INSIDE(currj, a,b,c,d)) {
937*5f2bebf7SJérôme Gardou                if (INSIDE(prevj, a,b,c,d)) {
938*5f2bebf7SJérôme Gardou                   /* both verts are inside ==> copy current to outlist */
939*5f2bebf7SJérôme Gardou 		  outlist[outcount++] = currj;
940*5f2bebf7SJérôme Gardou                }
941*5f2bebf7SJérôme Gardou                else {
942*5f2bebf7SJérôme Gardou                   /* current is inside and previous is outside ==> clip */
943*5f2bebf7SJérôme Gardou                   GLfloat dx, dy, dz, dw, t, denom;
944*5f2bebf7SJérôme Gardou 		  /* compute t */
945*5f2bebf7SJérôme Gardou 		  dx = VB->Eye[prevj][0] - VB->Eye[currj][0];
946*5f2bebf7SJérôme Gardou 		  dy = VB->Eye[prevj][1] - VB->Eye[currj][1];
947*5f2bebf7SJérôme Gardou 		  dz = VB->Eye[prevj][2] - VB->Eye[currj][2];
948*5f2bebf7SJérôme Gardou 		  dw = VB->Eye[prevj][3] - VB->Eye[currj][3];
949*5f2bebf7SJérôme Gardou 		  denom = dx*a + dy*b + dz*c + dw*d;
950*5f2bebf7SJérôme Gardou 		  if (denom==0.0) {
951*5f2bebf7SJérôme Gardou 		     t = 0.0;
952*5f2bebf7SJérôme Gardou 		  }
953*5f2bebf7SJérôme Gardou 		  else {
954*5f2bebf7SJérôme Gardou 		     t = -(VB->Eye[currj][0]*a+VB->Eye[currj][1]*b
955*5f2bebf7SJérôme Gardou 		       +VB->Eye[currj][2]*c+VB->Eye[currj][3]*d) / denom;
956*5f2bebf7SJérôme Gardou                      if (t>1.0F) {
957*5f2bebf7SJérôme Gardou                         t = 1.0F;
958*5f2bebf7SJérôme Gardou                      }
959*5f2bebf7SJérôme Gardou 		  }
960*5f2bebf7SJérôme Gardou 		  /* interpolate new vertex position */
961*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][0] = VB->Eye[currj][0] + t*dx;
962*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][1] = VB->Eye[currj][1] + t*dy;
963*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][2] = VB->Eye[currj][2] + t*dz;
964*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][3] = VB->Eye[currj][3] + t*dw;
965*5f2bebf7SJérôme Gardou 
966*5f2bebf7SJérôme Gardou 		  /* interpolate color, index, and/or texture coord */
967*5f2bebf7SJérôme Gardou 		  if (ctx->ClipMask) {
968*5f2bebf7SJérôme Gardou 		     interpolate_aux( ctx, EYE_SPACE, VB->Free, t, currj, prevj);
969*5f2bebf7SJérôme Gardou 		  }
970*5f2bebf7SJérôme Gardou 		  VB->Edgeflag[VB->Free] = VB->Edgeflag[prevj];
971*5f2bebf7SJérôme Gardou 
972*5f2bebf7SJérôme Gardou 		  /* output new vertex */
973*5f2bebf7SJérôme Gardou 		  outlist[outcount++] = VB->Free;
974*5f2bebf7SJérôme Gardou 		  VB->Free++;
975*5f2bebf7SJérôme Gardou 		  if (VB->Free==VB_SIZE)   VB->Free = 1;
976*5f2bebf7SJérôme Gardou 		  /* output current vertex */
977*5f2bebf7SJérôme Gardou 		  outlist[outcount++] = currj;
978*5f2bebf7SJérôme Gardou                }
979*5f2bebf7SJérôme Gardou             }
980*5f2bebf7SJérôme Gardou             else {
981*5f2bebf7SJérôme Gardou                if (INSIDE(prevj, a,b,c,d)) {
982*5f2bebf7SJérôme Gardou                   /* current is outside and previous is inside ==> clip */
983*5f2bebf7SJérôme Gardou                   GLfloat dx, dy, dz, dw, t, denom;
984*5f2bebf7SJérôme Gardou 		  /* compute t */
985*5f2bebf7SJérôme Gardou                   dx = VB->Eye[currj][0]-VB->Eye[prevj][0];
986*5f2bebf7SJérôme Gardou                   dy = VB->Eye[currj][1]-VB->Eye[prevj][1];
987*5f2bebf7SJérôme Gardou                   dz = VB->Eye[currj][2]-VB->Eye[prevj][2];
988*5f2bebf7SJérôme Gardou                   dw = VB->Eye[currj][3]-VB->Eye[prevj][3];
989*5f2bebf7SJérôme Gardou 		  denom = dx*a + dy*b + dz*c + dw*d;
990*5f2bebf7SJérôme Gardou 		  if (denom==0.0) {
991*5f2bebf7SJérôme Gardou 		     t = 0.0;
992*5f2bebf7SJérôme Gardou 		  }
993*5f2bebf7SJérôme Gardou 		  else {
994*5f2bebf7SJérôme Gardou 		     t = -(VB->Eye[prevj][0]*a+VB->Eye[prevj][1]*b
995*5f2bebf7SJérôme Gardou 		       +VB->Eye[prevj][2]*c+VB->Eye[prevj][3]*d) / denom;
996*5f2bebf7SJérôme Gardou                      if (t>1.0F) {
997*5f2bebf7SJérôme Gardou                         t = 1.0F;
998*5f2bebf7SJérôme Gardou                      }
999*5f2bebf7SJérôme Gardou 		  }
1000*5f2bebf7SJérôme Gardou 		  /* interpolate new vertex position */
1001*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][0] = VB->Eye[prevj][0] + t*dx;
1002*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][1] = VB->Eye[prevj][1] + t*dy;
1003*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][2] = VB->Eye[prevj][2] + t*dz;
1004*5f2bebf7SJérôme Gardou 		  VB->Eye[VB->Free][3] = VB->Eye[prevj][3] + t*dw;
1005*5f2bebf7SJérôme Gardou 
1006*5f2bebf7SJérôme Gardou 		  /* interpolate color, index, and/or texture coord */
1007*5f2bebf7SJérôme Gardou 		  if (ctx->ClipMask) {
1008*5f2bebf7SJérôme Gardou 		     interpolate_aux( ctx, EYE_SPACE, VB->Free, t, prevj, currj);
1009*5f2bebf7SJérôme Gardou 		  }
1010*5f2bebf7SJérôme Gardou 		  VB->Edgeflag[VB->Free] = VB->Edgeflag[prevj];
1011*5f2bebf7SJérôme Gardou 
1012*5f2bebf7SJérôme Gardou 		  /* output new vertex */
1013*5f2bebf7SJérôme Gardou 		  outlist[outcount++] = VB->Free;
1014*5f2bebf7SJérôme Gardou 		  VB->Free++;
1015*5f2bebf7SJérôme Gardou 		  if (VB->Free==VB_SIZE)   VB->Free = 1;
1016*5f2bebf7SJérôme Gardou 	       }
1017*5f2bebf7SJérôme Gardou                /* else  both verts are outside ==> do nothing */
1018*5f2bebf7SJérôme Gardou             }
1019*5f2bebf7SJérôme Gardou 
1020*5f2bebf7SJérôme Gardou 	    previ = curri;
1021*5f2bebf7SJérôme Gardou 	    prevj = currj;
1022*5f2bebf7SJérôme Gardou 
1023*5f2bebf7SJérôme Gardou 	    /* check for overflowing vertex buffer */
1024*5f2bebf7SJérôme Gardou             if (outcount>=VB_SIZE-1) {
1025*5f2bebf7SJérôme Gardou                /* Too many vertices */
1026*5f2bebf7SJérôme Gardou                if (outlist!=vlist2) {
1027*5f2bebf7SJérôme Gardou                   MEMCPY( vlist, vlist2, outcount * sizeof(GLuint) );
1028*5f2bebf7SJérôme Gardou                }
1029*5f2bebf7SJérôme Gardou                return VB_SIZE-1;
1030*5f2bebf7SJérôme Gardou             }
1031*5f2bebf7SJérôme Gardou 
1032*5f2bebf7SJérôme Gardou          }  /* for i */
1033*5f2bebf7SJérôme Gardou 
1034*5f2bebf7SJérôme Gardou          /* swap inlist and outlist pointers */
1035*5f2bebf7SJérôme Gardou          {
1036*5f2bebf7SJérôme Gardou             GLuint *tmp;
1037*5f2bebf7SJérôme Gardou             tmp = inlist;
1038*5f2bebf7SJérôme Gardou             inlist = outlist;
1039*5f2bebf7SJérôme Gardou             outlist = tmp;
1040*5f2bebf7SJérôme Gardou             incount = outcount;
1041*5f2bebf7SJérôme Gardou          }
1042*5f2bebf7SJérôme Gardou 
1043*5f2bebf7SJérôme Gardou       } /* if */
1044*5f2bebf7SJérôme Gardou    } /* for p */
1045*5f2bebf7SJérôme Gardou 
1046*5f2bebf7SJérôme Gardou    /* outlist points to the list of vertices resulting from the last */
1047*5f2bebf7SJérôme Gardou    /* clipping.  If outlist == vlist2 then we have to copy the vertices */
1048*5f2bebf7SJérôme Gardou    /* back to vlist */
1049*5f2bebf7SJérôme Gardou    if (outlist!=vlist2) {
1050*5f2bebf7SJérôme Gardou       MEMCPY( vlist, vlist2, outcount * sizeof(GLuint) );
1051*5f2bebf7SJérôme Gardou    }
1052*5f2bebf7SJérôme Gardou 
1053*5f2bebf7SJérôme Gardou    return outcount;
1054*5f2bebf7SJérôme Gardou }
1055*5f2bebf7SJérôme Gardou 
1056