clip.c revision fe5d67d95f3a5fc84c5421d409a6464642aaf2cb
1/* $Id: clip.c,v 1.10 2000/10/27 16:44:40 keithw 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 "context.h" 34#include "macros.h" 35#include "matrix.h" 36#include "mmath.h" 37#include "types.h" 38#include "vb.h" 39#include "xform.h" 40#endif 41 42 43 44 45#define CLIP_RGBA0 0x1 46#define CLIP_RGBA1 0x2 47#define CLIP_TEX0 0x4 48#define CLIP_TEX1 0x8 49#define CLIP_INDEX0 0x10 50#define CLIP_INDEX1 0x20 51#define CLIP_FOG_COORD 0x40 52 53 54/* Linear interpolation between A and B: */ 55#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) 56 57 58 59#define INTERP_SZ( t, vec, to, a, b, sz ) \ 60do { \ 61 switch (sz) { \ 62 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \ 63 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \ 64 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \ 65 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \ 66 } \ 67} while(0) 68 69 70static clip_interp_func clip_interp_tab[0x80]; 71 72#define IND 0 73#define NAME clip_nil 74#include "interp_tmp.h" 75 76#define IND (CLIP_RGBA0) 77#define NAME clipRGBA0 78#include "interp_tmp.h" 79 80#define IND (CLIP_RGBA0|CLIP_RGBA1) 81#define NAME clipRGBA0_RGBA1 82#include "interp_tmp.h" 83 84#define IND (CLIP_TEX0|CLIP_RGBA0) 85#define NAME clipTEX0_RGBA0 86#include "interp_tmp.h" 87 88#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) 89#define NAME clipTEX0_RGBA0_RGBA1 90#include "interp_tmp.h" 91 92#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0) 93#define NAME clipTEX1_TEX0_RGBA0 94#include "interp_tmp.h" 95 96#define IND (CLIP_TEX0) 97#define NAME clipTEX0 98#include "interp_tmp.h" 99 100#define IND (CLIP_TEX1|CLIP_TEX0) 101#define NAME clipTEX1_TEX0 102#include "interp_tmp.h" 103 104#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1) 105#define NAME clipTEX1_TEX0_RGBA0_RGBA1 106#include "interp_tmp.h" 107 108#define IND (CLIP_INDEX0) 109#define NAME clipINDEX0 110#include "interp_tmp.h" 111 112#define IND (CLIP_INDEX0|CLIP_INDEX1) 113#define NAME clipINDEX0_INDEX1 114#include "interp_tmp.h" 115 116#define IND (CLIP_FOG_COORD) 117#define NAME clip_FOG 118#include "interp_tmp.h" 119 120#define IND (CLIP_RGBA0|CLIP_FOG_COORD) 121#define NAME clipRGBA0_FOG 122#include "interp_tmp.h" 123 124#define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD) 125#define NAME clipRGBA0_RGBA1_FOG 126#include "interp_tmp.h" 127 128#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD) 129#define NAME clipTEX0_RGBA0_FOG 130#include "interp_tmp.h" 131 132#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD) 133#define NAME clipTEX0_RGBA0_RGBA1_FOG 134#include "interp_tmp.h" 135 136#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD) 137#define NAME clipTEX1_TEX0_RGBA0_FOG 138#include "interp_tmp.h" 139 140#define IND (CLIP_TEX0|CLIP_FOG_COORD) 141#define NAME clipTEX0_FOG 142#include "interp_tmp.h" 143 144#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD) 145#define NAME clipTEX1_TEX0_FOG 146#include "interp_tmp.h" 147 148#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD) 149#define NAME clipTEX1_TEX0_RGBA0_RGBA1_FOG 150#include "interp_tmp.h" 151 152#define IND (CLIP_INDEX0|CLIP_FOG_COORD) 153#define NAME clipINDEX0_FOG 154#include "interp_tmp.h" 155 156#define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD) 157#define NAME clipINDEX0_INDEX1_FOG 158#include "interp_tmp.h" 159 160 161 162 163/**********************************************************************/ 164/* Get/Set User clip-planes. */ 165/**********************************************************************/ 166 167 168 169void 170_mesa_ClipPlane( GLenum plane, const GLdouble *eq ) 171{ 172 GET_CURRENT_CONTEXT(ctx); 173 GLint p; 174 GLfloat equation[4]; 175 176 equation[0] = eq[0]; 177 equation[1] = eq[1]; 178 equation[2] = eq[2]; 179 equation[3] = eq[3]; 180 181 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClipPlane"); 182 183 p = (GLint) plane - (GLint) GL_CLIP_PLANE0; 184 if (p<0 || p>=MAX_CLIP_PLANES) { 185 gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" ); 186 return; 187 } 188 189 /* 190 * The equation is transformed by the transpose of the inverse of the 191 * current modelview matrix and stored in the resulting eye coordinates. 192 * 193 * KW: Eqn is then transformed to the current clip space, where user 194 * clipping now takes place. The clip-space equations are recalculated 195 * whenever the projection matrix changes. 196 */ 197 if (ctx->ModelView.flags & MAT_DIRTY_ALL_OVER) { 198 gl_matrix_analyze( &ctx->ModelView ); 199 } 200 gl_transform_vector( ctx->Transform.EyeUserPlane[p], equation, 201 ctx->ModelView.inv ); 202 203 204 if (ctx->Transform.ClipEnabled[p]) { 205 ctx->NewState |= NEW_USER_CLIP; 206 207 if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) { 208 gl_matrix_analyze( &ctx->ProjectionMatrix ); 209 } 210 gl_transform_vector( ctx->Transform.ClipUserPlane[p], 211 ctx->Transform.EyeUserPlane[p], 212 ctx->ProjectionMatrix.inv ); 213 } 214} 215 216 217void gl_update_userclip( GLcontext *ctx ) 218{ 219 GLuint p; 220 221 for (p = 0 ; p < MAX_CLIP_PLANES ; p++) { 222 if (ctx->Transform.ClipEnabled[p]) { 223 gl_transform_vector( ctx->Transform.ClipUserPlane[p], 224 ctx->Transform.EyeUserPlane[p], 225 ctx->ProjectionMatrix.inv ); 226 } 227 } 228} 229 230void 231_mesa_GetClipPlane( GLenum plane, GLdouble *equation ) 232{ 233 GET_CURRENT_CONTEXT(ctx); 234 GLint p; 235 236 ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane"); 237 238 239 p = (GLint) (plane - GL_CLIP_PLANE0); 240 if (p<0 || p>=MAX_CLIP_PLANES) { 241 gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" ); 242 return; 243 } 244 245 equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0]; 246 equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1]; 247 equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2]; 248 equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3]; 249} 250 251 252 253 254/**********************************************************************/ 255/* View volume clipping. */ 256/**********************************************************************/ 257 258 259/* 260 * Clip a point against the view volume. 261 * Input: v - vertex-vector describing the point to clip 262 * Return: 0 = outside view volume 263 * 1 = inside view volume 264 */ 265GLuint gl_viewclip_point( const GLfloat v[] ) 266{ 267 if ( v[0] > v[3] || v[0] < -v[3] 268 || v[1] > v[3] || v[1] < -v[3] 269 || v[2] > v[3] || v[2] < -v[3] ) { 270 return 0; 271 } 272 else { 273 return 1; 274 } 275} 276 277/* 278 * Clip a point against the user clipping planes. 279 * Input: v - vertex-vector describing the point to clip. 280 * Return: 0 = point was clipped 281 * 1 = point not clipped 282 */ 283GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] ) 284{ 285 GLuint p; 286 287 for (p=0;p<MAX_CLIP_PLANES;p++) { 288 if (ctx->Transform.ClipEnabled[p]) { 289 GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0] 290 + v[1] * ctx->Transform.ClipUserPlane[p][1] 291 + v[2] * ctx->Transform.ClipUserPlane[p][2] 292 + v[3] * ctx->Transform.ClipUserPlane[p][3]; 293 if (dot < 0.0F) { 294 return 0; 295 } 296 } 297 } 298 299 return 1; 300} 301 302 303 304 305#if 0 306#define NEGATIVE(x) ((*(int *)&x)<0) 307#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) 308#else 309#define NEGATIVE(x) (x < 0) 310#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) 311#endif 312 313 314static clip_poly_func gl_poly_clip_tab[2][5]; 315static clip_line_func gl_line_clip_tab[2][5]; 316 317#define W(i) coord[i][3] 318#define Z(i) coord[i][2] 319#define Y(i) coord[i][1] 320#define X(i) coord[i][0] 321#define SIZE 4 322#define IND 0 323#define TAG(x) x##_4 324#include "clip_funcs.h" 325 326#define W(i) 1.0 327#define Z(i) coord[i][2] 328#define Y(i) coord[i][1] 329#define X(i) coord[i][0] 330#define SIZE 3 331#define IND 0 332#define TAG(x) x##_3 333#include "clip_funcs.h" 334 335#define W(i) 1.0 336#define Z(i) 0.0 337#define Y(i) coord[i][1] 338#define X(i) coord[i][0] 339#define SIZE 2 340#define IND 0 341#define TAG(x) x##_2 342#include "clip_funcs.h" 343 344#define W(i) coord[i][3] 345#define Z(i) coord[i][2] 346#define Y(i) coord[i][1] 347#define X(i) coord[i][0] 348#define SIZE 4 349#define IND CLIP_TAB_EDGEFLAG 350#define TAG(x) x##_4_edgeflag 351#include "clip_funcs.h" 352 353#define W(i) 1.0 354#define Z(i) coord[i][2] 355#define Y(i) coord[i][1] 356#define X(i) coord[i][0] 357#define SIZE 3 358#define IND CLIP_TAB_EDGEFLAG 359#define TAG(x) x##_3_edgeflag 360#include "clip_funcs.h" 361 362#define W(i) 1.0 363#define Z(i) 0.0 364#define Y(i) coord[i][1] 365#define X(i) coord[i][0] 366#define SIZE 2 367#define IND CLIP_TAB_EDGEFLAG 368#define TAG(x) x##_2_edgeflag 369#include "clip_funcs.h" 370 371 372 373 374void gl_update_clipmask( GLcontext *ctx ) 375{ 376 GLuint mask = 0; 377 378 if (ctx->Visual.RGBAflag) 379 { 380 mask |= CLIP_RGBA0; 381 382 if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR)) 383 mask |= CLIP_RGBA1; 384 385 if (ctx->Texture.ReallyEnabled & 0xf0) 386 mask |= CLIP_TEX1|CLIP_TEX0; 387 388 if (ctx->Texture.ReallyEnabled & 0xf) 389 mask |= CLIP_TEX0; 390 } 391 else if (ctx->Light.ShadeModel==GL_SMOOTH) 392 { 393 mask |= CLIP_INDEX0; 394 395 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) 396 mask |= CLIP_INDEX1; 397 } 398 399 if (ctx->Fog.Enabled) 400 mask |= CLIP_FOG_COORD; 401 402 ctx->ClipInterpFunc = clip_interp_tab[mask]; 403 ctx->poly_clip_tab = gl_poly_clip_tab[0]; 404 ctx->line_clip_tab = gl_line_clip_tab[0]; 405 406 if (ctx->TriangleCaps & DD_TRI_UNFILLED) { 407 ctx->poly_clip_tab = gl_poly_clip_tab[1]; 408 ctx->line_clip_tab = gl_line_clip_tab[0]; 409 } 410} 411 412 413#define USER_CLIPTEST(NAME, SZ) \ 414static void NAME( struct vertex_buffer *VB ) \ 415{ \ 416 GLcontext *ctx = VB->ctx; \ 417 GLubyte *clipMask = VB->ClipMask; \ 418 GLubyte *userClipMask = VB->UserClipMask; \ 419 GLuint start = VB->Start; \ 420 GLuint count = VB->Count; \ 421 GLuint p, i; \ 422 GLubyte bit; \ 423 \ 424 \ 425 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \ 426 if (ctx->Transform.ClipEnabled[p]) { \ 427 GLuint nr = 0; \ 428 const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \ 429 const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \ 430 const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \ 431 const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \ 432 GLfloat *coord = VB->ClipPtr->start; \ 433 GLuint stride = VB->ClipPtr->stride; \ 434 \ 435 for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \ 436 GLfloat dp = coord[0] * a + coord[1] * b; \ 437 if (SZ > 2) dp += coord[2] * c; \ 438 if (SZ > 3) dp += coord[3] * d; else dp += d; \ 439 \ 440 if (dp < 0) { \ 441 clipMask[i] |= CLIP_USER_BIT; \ 442 userClipMask[i] |= bit; \ 443 nr++; \ 444 } \ 445 } \ 446 \ 447 if (nr > 0) { \ 448 VB->ClipOrMask |= CLIP_USER_BIT; \ 449 VB->CullMode |= CLIP_MASK_ACTIVE; \ 450 if (nr == count - start) { \ 451 VB->ClipAndMask |= CLIP_USER_BIT; \ 452 VB->Culled = 1; \ 453 return; \ 454 } \ 455 } \ 456 } \ 457} 458 459 460USER_CLIPTEST(userclip2, 2) 461USER_CLIPTEST(userclip3, 3) 462USER_CLIPTEST(userclip4, 4) 463 464static void (*(usercliptab[5]))( struct vertex_buffer * ) = { 465 0, 466 0, 467 userclip2, 468 userclip3, 469 userclip4 470}; 471 472void gl_user_cliptest( struct vertex_buffer *VB ) 473{ 474 usercliptab[VB->ClipPtr->size]( VB ); 475} 476 477 478void gl_init_clip(void) 479{ 480 init_clip_funcs_4(); 481 init_clip_funcs_3(); 482 init_clip_funcs_2(); 483 484 init_clip_funcs_4_edgeflag(); 485 init_clip_funcs_3_edgeflag(); 486 init_clip_funcs_2_edgeflag(); 487 488 clip_interp_tab[0] = clip_nil; 489 clip_interp_tab[CLIP_RGBA0] = clipRGBA0; 490 clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1] = clipRGBA0_RGBA1; 491 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0] = clipTEX0_RGBA0; 492 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX0_RGBA0_RGBA1; 493 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0] = clipTEX1_TEX0_RGBA0; 494 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = 495 clipTEX1_TEX0_RGBA0_RGBA1; 496 clip_interp_tab[CLIP_TEX0] = clipTEX0; 497 clip_interp_tab[CLIP_TEX1|CLIP_TEX0] = clipTEX1_TEX0; 498 clip_interp_tab[CLIP_INDEX0] = clipINDEX0; 499 clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1] = clipINDEX0_INDEX1; 500 501 clip_interp_tab[CLIP_FOG_COORD] = clip_FOG; 502 clip_interp_tab[CLIP_RGBA0|CLIP_FOG_COORD] = clipRGBA0_FOG; 503 clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] = clipRGBA0_RGBA1_FOG; 504 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD] = clipTEX0_RGBA0_FOG; 505 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] = clipTEX0_RGBA0_RGBA1_FOG; 506 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD] = clipTEX1_TEX0_RGBA0_FOG; 507 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD] = 508 clipTEX1_TEX0_RGBA0_RGBA1_FOG; 509 clip_interp_tab[CLIP_TEX0|CLIP_FOG_COORD] = clipTEX0_FOG; 510 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD] = clipTEX1_TEX0_FOG; 511 clip_interp_tab[CLIP_INDEX0|CLIP_FOG_COORD] = clipINDEX0_FOG; 512 clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD] = clipINDEX0_INDEX1_FOG; 513} 514 515