home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / clip.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  14KB  |  515 lines

  1. /* $Id: clip.c,v 1.4.2.1 1999/11/25 16:51:24 keithw Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  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.  
  29.  
  30.  
  31. #ifdef PC_HEADER
  32. #include "all.h"
  33. #else
  34. #ifndef XFree86Server
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #else
  39. #include "GL/xf86glx.h"
  40. #endif
  41. #include "clip.h"
  42. #include "context.h"
  43. #include "macros.h"
  44. #include "matrix.h"
  45. #include "mmath.h"
  46. #include "types.h"
  47. #include "vb.h"
  48. #include "xform.h"
  49. #endif
  50.  
  51.  
  52.  
  53.  
  54. #define CLIP_RGBA0    0x1
  55. #define CLIP_RGBA1    0x2
  56. #define CLIP_TEX0     0x4
  57. #define CLIP_TEX1     0x8
  58. #define CLIP_INDEX0   0x10
  59. #define CLIP_INDEX1   0x20
  60. #define CLIP_FOG_COORD 0x40
  61.  
  62.  
  63. /* Linear interpolation between A and B: */
  64. #define LINTERP( T, A, B )   ( (A) + (T) * ( (B) - (A) ) )
  65.  
  66.  
  67.  
  68. #define INTERP_SZ( t, vec, to, a, b, sz )            \
  69. do {                                \
  70.    switch (sz) {                        \
  71.    case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] );    \
  72.    case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] );    \
  73.    case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] );    \
  74.    case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] );    \
  75.    }                                \
  76. } while(0)
  77.    
  78. static clip_interp_func clip_interp_tab[0x80]; 
  79.  
  80. #define IND 0
  81. #define NAME clip_nil
  82. #include "interp_tmp.h"
  83.  
  84. #define IND (CLIP_RGBA0)
  85. #define NAME clipRGBA0
  86. #include "interp_tmp.h"
  87.  
  88. #define IND (CLIP_RGBA0|CLIP_RGBA1)
  89. #define NAME clipRGBA0_RGBA1
  90. #include "interp_tmp.h"
  91.  
  92. #define IND (CLIP_TEX0|CLIP_RGBA0)
  93. #define NAME clipTEX0_RGBA0
  94. #include "interp_tmp.h"
  95.  
  96. #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
  97. #define NAME clipTEX0_RGBA0_RGBA1
  98. #include "interp_tmp.h"
  99.  
  100. #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
  101. #define NAME clipTEX1_TEX0_RGBA0
  102. #include "interp_tmp.h"
  103.  
  104. #define IND (CLIP_TEX0)
  105. #define NAME clipTEX0
  106. #include "interp_tmp.h"
  107.  
  108. #define IND (CLIP_TEX1|CLIP_TEX0)
  109. #define NAME clipTEX1_TEX0
  110. #include "interp_tmp.h"
  111.  
  112. #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
  113. #define NAME clipTEX1_TEX0_RGBA0_RGBA1
  114. #include "interp_tmp.h"
  115.  
  116. #define IND (CLIP_INDEX0)
  117. #define NAME clipINDEX0
  118. #include "interp_tmp.h"
  119.  
  120. #define IND (CLIP_INDEX0|CLIP_INDEX1)
  121. #define NAME clipINDEX0_INDEX1
  122. #include "interp_tmp.h"
  123.  
  124. #define IND (CLIP_FOG_COORD)
  125. #define NAME clip_FOG
  126. #include "interp_tmp.h"
  127.  
  128. #define IND (CLIP_RGBA0|CLIP_FOG_COORD)
  129. #define NAME clipRGBA0_FOG
  130. #include "interp_tmp.h"
  131.  
  132. #define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
  133. #define NAME clipRGBA0_RGBA1_FOG
  134. #include "interp_tmp.h"
  135.  
  136. #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
  137. #define NAME clipTEX0_RGBA0_FOG
  138. #include "interp_tmp.h"
  139.  
  140. #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
  141. #define NAME clipTEX0_RGBA0_RGBA1_FOG
  142. #include "interp_tmp.h"
  143.  
  144. #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_FOG_COORD)
  145. #define NAME clipTEX1_TEX0_RGBA0_FOG
  146. #include "interp_tmp.h"
  147.  
  148. #define IND (CLIP_TEX0|CLIP_FOG_COORD)
  149. #define NAME clipTEX0_FOG
  150. #include "interp_tmp.h"
  151.  
  152. #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_FOG_COORD)
  153. #define NAME clipTEX1_TEX0_FOG
  154. #include "interp_tmp.h"
  155.  
  156. #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_FOG_COORD)
  157. #define NAME clipTEX1_TEX0_RGBA0_RGBA1_FOG
  158. #include "interp_tmp.h"
  159.  
  160. #define IND (CLIP_INDEX0|CLIP_FOG_COORD)
  161. #define NAME clipINDEX0_FOG
  162. #include "interp_tmp.h"
  163.  
  164. #define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_FOG_COORD)
  165. #define NAME clipINDEX0_INDEX1_FOG
  166. #include "interp_tmp.h"
  167.  
  168.  
  169.  
  170.  
  171. /**********************************************************************/
  172. /*                     Get/Set User clip-planes.                      */
  173. /**********************************************************************/
  174.  
  175.  
  176.  
  177. void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation )
  178. {
  179.    GLint p;
  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.  
  217. void 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.  
  230. void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation )
  231. {
  232.    GLint p;
  233.  
  234.    ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane");
  235.  
  236.  
  237.    p = (GLint) (plane - GL_CLIP_PLANE0);
  238.    if (p<0 || p>=MAX_CLIP_PLANES) {
  239.       gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" );
  240.       return;
  241.    }
  242.  
  243.    equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0];
  244.    equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1];
  245.    equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2];
  246.    equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3];
  247. }
  248.  
  249.  
  250.  
  251.  
  252. /**********************************************************************/
  253. /*                         View volume clipping.                      */
  254. /**********************************************************************/
  255.  
  256.  
  257. /*
  258.  * Clip a point against the view volume.
  259.  * Input:  v - vertex-vector describing the point to clip
  260.  * Return:  0 = outside view volume
  261.  *          1 = inside view volume
  262.  */
  263. GLuint gl_viewclip_point( const GLfloat v[] )
  264. {
  265.    if (   v[0] > v[3] || v[0] < -v[3]
  266.        || v[1] > v[3] || v[1] < -v[3]
  267.        || v[2] > v[3] || v[2] < -v[3] ) {
  268.       return 0;
  269.    }
  270.    else {
  271.       return 1;
  272.    }
  273. }
  274.  
  275. /*
  276.  * Clip a point against the user clipping planes.
  277.  * Input:  v - vertex-vector describing the point to clip.
  278.  * Return:  0 = point was clipped
  279.  *          1 = point not clipped
  280.  */
  281. GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] )
  282. {
  283.    GLuint p;
  284.  
  285.    for (p=0;p<MAX_CLIP_PLANES;p++) {
  286.       if (ctx->Transform.ClipEnabled[p]) {
  287.      GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0]
  288.              + v[1] * ctx->Transform.ClipUserPlane[p][1]
  289.              + v[2] * ctx->Transform.ClipUserPlane[p][2]
  290.              + v[3] * ctx->Transform.ClipUserPlane[p][3];
  291.          if (dot < 0.0F) {
  292.             return 0;
  293.          }
  294.       }
  295.    }
  296.  
  297.    return 1;
  298. }
  299.  
  300.  
  301.  
  302.  
  303. #if defined(__i386__)
  304. #define NEGATIVE(x) ((*(int *)&x)<0)
  305. #else
  306. #define NEGATIVE(x) (x < 0)
  307. #endif
  308.  
  309.  
  310. static clip_poly_func gl_poly_clip_tab[2][5];
  311. static clip_line_func gl_line_clip_tab[2][5];
  312.  
  313. #define W(i) coord[i][3]
  314. #define Z(i) coord[i][2]
  315. #define Y(i) coord[i][1]
  316. #define X(i) coord[i][0]
  317. #define SIZE 4
  318. #define IND 0
  319. #define TAG(x) x##_4
  320. #include "clip_funcs.h"
  321.  
  322.  
  323. #define W(i) 1.0
  324. #define Z(i) coord[i][2]
  325. #define Y(i) coord[i][1]
  326. #define X(i) coord[i][0]
  327. #define SIZE 3
  328. #define IND 0
  329. #define TAG(x) x##_3
  330. #include "clip_funcs.h"
  331.  
  332. #define W(i) 1.0
  333. #define Z(i) 0.0
  334. #define Y(i) coord[i][1]
  335. #define X(i) coord[i][0]
  336. #define SIZE 2
  337. #define IND 0
  338. #define TAG(x) x##_2
  339. #include "clip_funcs.h"
  340.  
  341. #define W(i) coord[i][3]
  342. #define Z(i) coord[i][2]
  343. #define Y(i) coord[i][1]
  344. #define X(i) coord[i][0]
  345. #define SIZE 4
  346. #define IND CLIP_TAB_EDGEFLAG
  347. #define TAG(x) x##_4_edgeflag
  348. #include "clip_funcs.h"
  349.  
  350. #define W(i) 1.0
  351. #define Z(i) coord[i][2]
  352. #define Y(i) coord[i][1]
  353. #define X(i) coord[i][0]
  354. #define SIZE 3
  355. #define IND CLIP_TAB_EDGEFLAG
  356. #define TAG(x) x##_3_edgeflag
  357. #include "clip_funcs.h"
  358.  
  359. #define W(i) 1.0
  360. #define Z(i) 0.0
  361. #define Y(i) coord[i][1]
  362. #define X(i) coord[i][0]
  363. #define SIZE 2
  364. #define IND CLIP_TAB_EDGEFLAG
  365. #define TAG(x) x##_2_edgeflag
  366. #include "clip_funcs.h"
  367.  
  368.  
  369.  
  370.  
  371. void gl_update_clipmask( GLcontext *ctx )
  372. {
  373.    GLuint mask = 0;
  374.  
  375.    if (ctx->Visual->RGBAflag) 
  376.    {
  377.       if (ctx->Light.ShadeModel==GL_SMOOTH) 
  378.       {
  379.      mask |= CLIP_RGBA0;
  380.       
  381.      if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR))
  382.         mask |= CLIP_RGBA1;
  383.       }
  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->FogMode == FOG_FRAGMENT && (ctx->TriangleCaps & DD_CLIP_FOG_COORD))
  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)                        \
  414. static 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.  
  460. USER_CLIPTEST(userclip2, 2)               
  461. USER_CLIPTEST(userclip3, 3)               
  462. USER_CLIPTEST(userclip4, 4)               
  463.  
  464. static void (*(usercliptab[5]))( struct vertex_buffer * ) = {
  465.    0,
  466.    0,
  467.    userclip2,
  468.    userclip3,
  469.    userclip4
  470. };
  471.  
  472. void gl_user_cliptest( struct vertex_buffer *VB )
  473. {
  474.    usercliptab[VB->ClipPtr->size]( VB );
  475. }
  476.  
  477.  
  478. void 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.