clip.c revision c893a015d8a50a38cd3f727d99835e7e7e2ccea9
1/* $Id: clip.c,v 1.11 2000/10/28 20:41:13 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.3 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#ifdef PC_HEADER 29#include "all.h" 30#else 31#include "glheader.h" 32#include "clip.h" 33#include "colormac.h" 34#include "context.h" 35#include "macros.h" 36#include "matrix.h" 37#include "mmath.h" 38#include "types.h" 39#include "vb.h" 40#include "xform.h" 41#endif 42 43 44 45 46#define CLIP_RGBA0 0x1 47#define CLIP_RGBA1 0x2 48#define CLIP_TEX0 0x4 49#define CLIP_TEX1 0x8 50#define CLIP_INDEX0 0x10 51#define CLIP_INDEX1 0x20 52#define CLIP_FOG_COORD 0x40 53 54 55/* Linear interpolation between A and B: */ 56#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) 57 58 59 60#define INTERP_SZ( t, vec, to, a, b, sz ) \ 61do { \ 62 switch (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] ); \ 67 } \ 68} while(0) 69 70 71static clip_interp_func clip_interp_tab[0x80]; 72 73#define IND 0 74#define NAME clip_nil 75#include "interp_tmp.h" 76 77#define IND (CLIP_RGBA0) 78#define NAME clipRGBA0 79#include "interp_tmp.h" 80 81#define IND (CLIP_RGBA0|CLIP_RGBA1) 82#define NAME clipRGBA0_RGBA1 83#include "interp_tmp.h" 84 85#define IND (CLIP_TEX0|CLIP_RGBA0) 86#define NAME clipTEX0_RGBA0 87#include "interp_tmp.h" 88 89#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) 90#define NAME clipTEX0_RGBA0_RGBA1 91#include "interp_tmp.h" 92 93#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0) 94#define NAME clipTEX1_TEX0_RGBA0 95#include "interp_tmp.h" 96 97#define IND (CLIP_TEX0) 98#define NAME clipTEX0 99#include "interp_tmp.h" 100 101#define IND (CLIP_TEX1|CLIP_TEX0) 102#define NAME clipTEX1_TEX0 103#include "interp_tmp.h" 104 105#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) 106#define NAME clipTEX1_TEX0_RGBA0_RGBA1 107#include "interp_tmp.h" 108 109#define IND (CLIP_INDEX0) 110#define NAME clipINDEX0 111#include "interp_tmp.h" 112 113#define IND (CLIP_INDEX0|CLIP_INDEX1) 114#define NAME clipINDEX0_INDEX1 115#include "interp_tmp.h" 116 117#define IND (CLIP_FOG_COORD) 118#define NAME clip_FOG 119#include "interp_tmp.h" 120 121#define IND (CLIP_RGBA0|CLIP_FOG_COORD) 122#define NAME clipRGBA0_FOG 123#include "interp_tmp.h" 124 125#define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD) 126#define NAME clipRGBA0_RGBA1_FOG 127#include "interp_tmp.h" 128 129#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD) 130#define NAME clipTEX0_RGBA0_FOG 131#include "interp_tmp.h" 132 133#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD) 134#define NAME clipTEX0_RGBA0_RGBA1_FOG 135#include "interp_tmp.h" 136 137#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD) 138#define NAME clipTEX1_TEX0_RGBA0_FOG 139#include "interp_tmp.h" 140 141#define IND (CLIP_TEX0|CLIP_FOG_COORD) 142#define NAME clipTEX0_FOG 143#include "interp_tmp.h" 144 145#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD) 146#define NAME clipTEX1_TEX0_FOG 147#include "interp_tmp.h" 148 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" 152 153#define IND (CLIP_INDEX0|CLIP_FOG_COORD) 154#define NAME clipINDEX0_FOG 155#include "interp_tmp.h" 156 157#define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD) 158#define NAME clipINDEX0_INDEX1_FOG 159#include "interp_tmp.h" 160 161 162 163 164/**********************************************************************/ 165/* Get/Set User clip-planes. */ 166/**********************************************************************/ 167 168 169 170void 171_mesa_ClipPlane( GLenum plane, const GLdouble *eq ) 172{ 173 GET_CURRENT_CONTEXT(ctx); 174 GLint p; 175 GLfloat equation[4]; 176 177 equation[0] = eq[0]; 178 equation[1] = eq[1]; 179 equation[2] = eq[2]; 180 equation[3] = eq[3]; 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 232_mesa_GetClipPlane( GLenum plane, GLdouble *equation ) 233{ 234 GET_CURRENT_CONTEXT(ctx); 235 GLint p; 236 237 ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane"); 238 239 240 p = (GLint) (plane - GL_CLIP_PLANE0); 241 if (p<0 || p>=MAX_CLIP_PLANES) { 242 gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" ); 243 return; 244 } 245 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]; 250} 251 252 253 254 255/**********************************************************************/ 256/* View volume clipping. */ 257/**********************************************************************/ 258 259 260/* 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 265 */ 266GLuint gl_viewclip_point( const GLfloat v[] ) 267{ 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] ) { 271 return 0; 272 } 273 else { 274 return 1; 275 } 276} 277 278/* 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 283 */ 284GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] ) 285{ 286 GLuint p; 287 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]; 294 if (dot < 0.0F) { 295 return 0; 296 } 297 } 298 } 299 300 return 1; 301} 302 303 304 305 306#if 0 307#define NEGATIVE(x) ((*(int *)&x)<0) 308#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) 309#else 310#define NEGATIVE(x) (x < 0) 311#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) 312#endif 313 314 315static clip_poly_func gl_poly_clip_tab[2][5]; 316static clip_line_func gl_line_clip_tab[2][5]; 317 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] 322#define SIZE 4 323#define IND 0 324#define TAG(x) x##_4 325#include "clip_funcs.h" 326 327#define W(i) 1.0 328#define Z(i) coord[i][2] 329#define Y(i) coord[i][1] 330#define X(i) coord[i][0] 331#define SIZE 3 332#define IND 0 333#define TAG(x) x##_3 334#include "clip_funcs.h" 335 336#define W(i) 1.0 337#define Z(i) 0.0 338#define Y(i) coord[i][1] 339#define X(i) coord[i][0] 340#define SIZE 2 341#define IND 0 342#define TAG(x) x##_2 343#include "clip_funcs.h" 344 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] 349#define SIZE 4 350#define IND CLIP_TAB_EDGEFLAG 351#define TAG(x) x##_4_edgeflag 352#include "clip_funcs.h" 353 354#define W(i) 1.0 355#define Z(i) coord[i][2] 356#define Y(i) coord[i][1] 357#define X(i) coord[i][0] 358#define SIZE 3 359#define IND CLIP_TAB_EDGEFLAG 360#define TAG(x) x##_3_edgeflag 361#include "clip_funcs.h" 362 363#define W(i) 1.0 364#define Z(i) 0.0 365#define Y(i) coord[i][1] 366#define X(i) coord[i][0] 367#define SIZE 2 368#define IND CLIP_TAB_EDGEFLAG 369#define TAG(x) x##_2_edgeflag 370#include "clip_funcs.h" 371 372 373 374 375void gl_update_clipmask( GLcontext *ctx ) 376{ 377 GLuint mask = 0; 378 379 if (ctx->Visual.RGBAflag) 380 { 381 mask |= CLIP_RGBA0; 382 383 if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR)) 384 mask |= CLIP_RGBA1; 385 386 if (ctx->Texture.ReallyEnabled & 0xf0) 387 mask |= CLIP_TEX1|CLIP_TEX0; 388 389 if (ctx->Texture.ReallyEnabled & 0xf) 390 mask |= CLIP_TEX0; 391 } 392 else if (ctx->Light.ShadeModel==GL_SMOOTH) 393 { 394 mask |= CLIP_INDEX0; 395 396 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) 397 mask |= CLIP_INDEX1; 398 } 399 400 if (ctx->Fog.Enabled) 401 mask |= CLIP_FOG_COORD; 402 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]; 406 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]; 410 } 411} 412 413 414#define USER_CLIPTEST(NAME, SZ) \ 415static void NAME( struct vertex_buffer *VB ) \ 416{ \ 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; \ 422 GLuint p, i; \ 423 GLubyte bit; \ 424 \ 425 \ 426 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \ 427 if (ctx->Transform.ClipEnabled[p]) { \ 428 GLuint nr = 0; \ 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; \ 435 \ 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; \ 440 \ 441 if (dp < 0) { \ 442 clipMask[i] |= CLIP_USER_BIT; \ 443 userClipMask[i] |= bit; \ 444 nr++; \ 445 } \ 446 } \ 447 \ 448 if (nr > 0) { \ 449 VB->ClipOrMask |= CLIP_USER_BIT; \ 450 VB->CullMode |= CLIP_MASK_ACTIVE; \ 451 if (nr == count - start) { \ 452 VB->ClipAndMask |= CLIP_USER_BIT; \ 453 VB->Culled = 1; \ 454 return; \ 455 } \ 456 } \ 457 } \ 458} 459 460 461USER_CLIPTEST(userclip2, 2) 462USER_CLIPTEST(userclip3, 3) 463USER_CLIPTEST(userclip4, 4) 464 465static void (*(usercliptab[5]))( struct vertex_buffer * ) = { 466 0, 467 0, 468 userclip2, 469 userclip3, 470 userclip4 471}; 472 473void gl_user_cliptest( struct vertex_buffer *VB ) 474{ 475 usercliptab[VB->ClipPtr->size]( VB ); 476} 477 478 479void gl_init_clip(void) 480{ 481 init_clip_funcs_4(); 482 init_clip_funcs_3(); 483 init_clip_funcs_2(); 484 485 init_clip_funcs_4_edgeflag(); 486 init_clip_funcs_3_edgeflag(); 487 init_clip_funcs_2_edgeflag(); 488 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; 501 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; 514} 515 516