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

  1. /* $Id: clip_funcs.h,v 1.4 1999/09/30 11:18:21 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.  * New (3.1) transformation code written by Keith Whitwell.
  29.  */
  30.  
  31. static GLuint TAG(userclip_line)( struct vertex_buffer *VB, 
  32.                   GLuint *i, GLuint *j );
  33. static GLuint TAG(userclip_polygon)( struct vertex_buffer *VB, 
  34.                      GLuint n, GLuint vlist[] );
  35.  
  36.  
  37.  
  38. /* This now calls the user clip functions if required.
  39.  */
  40. static GLuint TAG(viewclip_line)( struct vertex_buffer *VB, 
  41.                   GLuint *i, GLuint *j,
  42.                   GLubyte mask )
  43. {
  44.    GLfloat (*coord)[4] = VB->ClipPtr->data;
  45.    GLfloat t, dx, dy, dz, dw, neww;
  46.    GLuint ii = *i, jj = *j;
  47.    GLuint vlist[2];
  48.    GLuint n;
  49.    clip_interp_func interp = VB->ctx->ClipInterpFunc;
  50.    GLuint vb_free = VB->FirstFree;
  51.  
  52. /*
  53.  * We use 6 instances of this code to clip agains the 6 planes.
  54.  * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
  55.  * macros apprpriately.
  56.  */
  57. #define GENERAL_CLIP                    \
  58.    if (mask & PLANE) {                    \
  59.       GLuint flagI = INSIDE( ii );            \
  60.       GLuint flagJ = INSIDE( jj );            \
  61.                             \
  62.       if (!(flagI|flagJ))                \
  63.      return 0;                    \
  64.                             \
  65.       if (flagI ^ flagJ) {                \
  66.      COMPUTE_INTERSECTION( jj, ii, vb_free );    \
  67.      interp( VB, vb_free, t, jj, ii);        \
  68.                             \
  69.      if (flagI) {                    \
  70.             VB->ClipMask[jj] |= PLANE;            \
  71.         jj = vb_free;                \
  72.      } else {                    \
  73.             VB->ClipMask[ii] |= PLANE;            \
  74.         ii = vb_free;                \
  75.      }                        \
  76.                             \
  77.          VB->ClipMask[vb_free++] = 0;            \
  78.       }                            \
  79.    }
  80.  
  81. #include "general_clip.h"
  82.  
  83.    VB->Free = vb_free;
  84.  
  85.    if (mask & CLIP_USER_BIT) {
  86.       if ( TAG(userclip_line)( VB, &ii, &jj ) == 0 )
  87.      return 0;
  88.    }
  89.  
  90.    vlist[0] = ii;
  91.    vlist[1] = jj;
  92.    n = 2;
  93.  
  94.    /* Should always be at least one new vertex.
  95.     */
  96.    {
  97.       const GLfloat *m = VB->ctx->Viewport.WindowMap.m;
  98.       GLfloat sx = m[MAT_SX];
  99.       GLfloat tx = m[MAT_TX];
  100.       GLfloat sy = m[MAT_SY];
  101.       GLfloat ty = m[MAT_TY];
  102.       GLfloat sz = m[MAT_SZ];
  103.       GLfloat tz = m[MAT_TZ];
  104.       GLuint i, j;
  105.       GLfloat (*win)[4] = VB->Win.data;
  106.       GLuint start = VB->FirstFree;
  107.  
  108.       for (i = 0; i < n; i++) {
  109.      j = vlist[i];
  110.      if (j >= start) {
  111.         if (W(j) != 0.0F) {
  112.            GLfloat wInv = 1.0F / W(j);
  113.            win[j][0] = X(j) * wInv * sx + tx;
  114.            win[j][1] = Y(j) * wInv * sy + ty;
  115.            win[j][2] = Z(j) * wInv * sz + tz;
  116.            win[j][3] = wInv;
  117.         } else {
  118.            win[j][0] = win[j][1] = win[j][2] = 0.0F;
  119.            win[j][3] = 1.0F;
  120.         }
  121.      }
  122.       }
  123.    }
  124.  
  125.    if (VB->ctx->Driver.RasterSetup)
  126.       VB->ctx->Driver.RasterSetup(VB, VB->FirstFree, VB->Free);
  127.  
  128.    *i = ii;
  129.    *j = jj;
  130.    return 1;
  131. }
  132.  
  133. /* We now clip polygon triangles individually.  This is necessary to
  134.  * avoid artifacts dependent on where the boundary of the VB falls
  135.  * within the polygon.  As a result, there is an upper bound on the
  136.  * number of vertices which may be created, and the test against VB_SIZE
  137.  * is redundant.  
  138.  */
  139. static GLuint TAG(viewclip_polygon)( struct vertex_buffer *VB, 
  140.                      GLuint n, GLuint vlist[],
  141.                      GLubyte mask )
  142. {
  143.    GLfloat (*coord)[4] = VB->ClipPtr->data;
  144.    GLuint vlist2[VB_SIZE-VB_MAX];
  145.    GLuint *inlist = vlist, *outlist = vlist2;
  146.    GLdouble dx, dy, dz, dw, t = 0, neww;
  147.    GLuint i;
  148.    GLuint vb_free = VB->FirstFree;
  149.    clip_interp_func interp = VB->ctx->ClipInterpFunc;
  150.  
  151.    if (mask & CLIP_ALL_BITS) {
  152.  
  153. #define GENERAL_CLIP                              \
  154.    if (mask & PLANE) {                          \
  155.       GLuint prevj = inlist[n-1];                      \
  156.       GLuint prevflag = INSIDE(prevj);                      \
  157.       GLuint outcount = 0;                          \
  158.       GLuint ef_state = 3;                        \
  159.       GLuint i;                                  \
  160.                                       \
  161.                                     \
  162.       for (i = 0; i < n; i++) {                          \
  163.      GLuint j = inlist[i];                          \
  164.      GLuint flag = INSIDE(j);                      \
  165.                                       \
  166.      if (flag ^ prevflag) {                          \
  167.         if (flag) {                            \
  168.            /* Coming back in                    \
  169.         */                            \
  170.         COMPUTE_INTERSECTION( j, prevj, vb_free );              \
  171.         interp( VB, vb_free, t, j, prevj );                              \
  172.                                     \
  173.            if (IND&CLIP_TAB_EDGEFLAG)                \
  174.           VB->EdgeFlagPtr->data[vb_free] =            \
  175.              VB->EdgeFlagPtr->data[prevj] & ef_state;        \
  176.                                     \
  177.                                     \
  178.         } else {                            \
  179.            /* Going out of bounds                    \
  180.         */                            \
  181.            COMPUTE_INTERSECTION( prevj, j, vb_free );        \
  182.            interp( VB, vb_free, t, prevj, j );            \
  183.                                     \
  184.            if (IND&CLIP_TAB_EDGEFLAG)                \
  185.           VB->EdgeFlagPtr->data[vb_free] = 1;            \
  186.         }                                \
  187.                                     \
  188.         outlist[outcount++] = vb_free;                  \
  189.             VB->ClipMask[vb_free++] = 0;   \
  190.      }                                  \
  191.                                       \
  192.      if (flag) {                              \
  193.         outlist[outcount++] = j;                      \
  194.      } else {                              \
  195.             VB->ClipMask[j] |= (PLANE&CLIP_ALL_BITS); /* don't setup */   \
  196.          }                                  \
  197.      prevj = j;                              \
  198.      prevflag = flag;                          \
  199.      ef_state = 1;                            \
  200.       }                                      \
  201.                                       \
  202.       if (outcount < 3)                              \
  203.      return 0;                              \
  204.       else {                                  \
  205.      GLuint *tmp = inlist;                          \
  206.      inlist = outlist;                          \
  207.      outlist = tmp;                              \
  208.      n = outcount;                              \
  209.       }                                      \
  210.    }
  211.  
  212.  
  213. #include "general_clip.h"
  214.  
  215.       if (inlist != vlist) 
  216.      for (i = 0 ; i < n ; i++)
  217.         vlist[i] = inlist[i];
  218.    }
  219.  
  220.    VB->Free = vb_free;
  221.  
  222.    /* Clip against user clipping planes in clip space. 
  223.     */
  224.    if (mask & CLIP_USER_BIT) {
  225.       n = TAG(userclip_polygon)( VB, n, vlist );
  226.       if (n < 3) return 0;
  227.    }
  228.  
  229.  
  230.    {
  231.       const GLfloat *m = VB->ctx->Viewport.WindowMap.m;
  232.       GLfloat sx = m[MAT_SX];
  233.       GLfloat tx = m[MAT_TX];
  234.       GLfloat sy = m[MAT_SY];
  235.       GLfloat ty = m[MAT_TY];
  236.       GLfloat sz = m[MAT_SZ];
  237.       GLfloat tz = m[MAT_TZ];
  238.       GLuint i;
  239.       GLfloat (*win)[4] = VB->Win.data;
  240.       GLuint first = VB->FirstFree;
  241.  
  242.       for (i = 0; i < n; i++) {
  243.      GLuint j = vlist[i];
  244.      if (j >= first) {
  245.         if (W(j) != 0.0F) {
  246.            GLfloat wInv = 1.0F / W(j);
  247.            win[j][0] = X(j) * wInv * sx + tx;
  248.            win[j][1] = Y(j) * wInv * sy + ty;
  249.            win[j][2] = Z(j) * wInv * sz + tz;
  250.            win[j][3] = wInv;
  251.         } else {
  252.            win[j][0] = win[j][1] = win[j][2] = 0.0;
  253.            win[j][3] = 1.0F;
  254.         }
  255.      }
  256.       }
  257.    }
  258.  
  259.    if (VB->ctx->Driver.RasterSetup)
  260.       VB->ctx->Driver.RasterSetup(VB, VB->FirstFree, VB->Free);
  261.  
  262.    return n;
  263. }
  264.  
  265.  
  266. #define INSIDE( J ) !NEGATIVE(J)
  267. #define OUTSIDE( J ) NEGATIVE(J)
  268.  
  269.  
  270.  
  271.  
  272. static GLuint TAG(userclip_line)( struct vertex_buffer *VB, 
  273.                   GLuint *i, GLuint *j )
  274. {
  275.    GLcontext *ctx = VB->ctx;
  276.    GLfloat (*coord)[4] = VB->ClipPtr->data;
  277.    clip_interp_func interp = ctx->ClipInterpFunc;
  278.    GLuint ii = *i;
  279.    GLuint jj = *j;
  280.    GLuint p;
  281.    GLuint vb_free = VB->Free;
  282.  
  283.    for (p=0;p<MAX_CLIP_PLANES;p++) {
  284.       if (ctx->Transform.ClipEnabled[p]) {
  285.      GLfloat a = ctx->Transform.ClipUserPlane[p][0];
  286.      GLfloat b = ctx->Transform.ClipUserPlane[p][1];
  287.      GLfloat c = ctx->Transform.ClipUserPlane[p][2];
  288.      GLfloat d = ctx->Transform.ClipUserPlane[p][3];
  289.  
  290.      GLfloat dpI = d*W(ii) + c*Z(ii) + b*Y(ii) + a*X(ii);
  291.      GLfloat dpJ = d*W(jj) + c*Z(jj) + b*Y(jj) + a*X(jj);
  292.  
  293.          GLuint flagI = OUTSIDE( dpI );
  294.          GLuint flagJ = OUTSIDE( dpJ );
  295.  
  296.      if (flagI & flagJ) 
  297.         return 0;
  298.  
  299.      if (flagI ^ flagJ) {
  300.         GLfloat t = -dpI/(dpJ-dpI);
  301.  
  302.         INTERP_SZ( t, coord, vb_free, ii, jj, SIZE );
  303.         interp( VB, vb_free, t, ii, jj );
  304.         
  305.         if (flagI) {
  306.            VB->ClipMask[ii] |= CLIP_USER_BIT;
  307.            ii = vb_free;
  308.         } else {
  309.            VB->ClipMask[jj] |= CLIP_USER_BIT;
  310.            jj = vb_free;
  311.         }
  312.         
  313.         VB->ClipMask[vb_free++] = 0;
  314.          }
  315.       }
  316.    }
  317.  
  318.    VB->Free = vb_free;
  319.    *i = ii;
  320.    *j = jj;
  321.    return 1;
  322. }
  323.  
  324.  
  325. static GLuint TAG(userclip_polygon)( struct vertex_buffer *VB, 
  326.                      GLuint n, GLuint vlist[] )
  327. {
  328.    GLcontext *ctx = VB->ctx;
  329.    GLfloat (*coord)[4] = VB->ClipPtr->data;
  330.    clip_interp_func interp = ctx->ClipInterpFunc;
  331.    GLuint vlist2[VB_SIZE];
  332.    GLuint *inlist = vlist, *outlist = vlist2;
  333.    GLuint vb_free = VB->Free;
  334.    GLuint p;
  335.  
  336.    for (p=0;p<MAX_CLIP_PLANES;p++) {
  337.       if (ctx->Transform.ClipEnabled[p]) {
  338.      register float a = ctx->Transform.ClipUserPlane[p][0];
  339.      register float b = ctx->Transform.ClipUserPlane[p][1];
  340.      register float c = ctx->Transform.ClipUserPlane[p][2];
  341.      register float d = ctx->Transform.ClipUserPlane[p][3];
  342.  
  343.      /* initialize prev to be last in the input list */
  344.      GLuint prevj = inlist[n - 1];
  345.      GLfloat dpJ = d*W(prevj) + c*Z(prevj) + b*Y(prevj) + a*X(prevj);
  346.      GLuint flagJ = INSIDE(dpJ);
  347.      GLuint outcount = 0;
  348.      GLuint curri;
  349.  
  350.          for (curri=0;curri<n;curri++) {
  351.         GLuint currj = inlist[curri];
  352.         GLfloat dpI = d*W(currj) + c*Z(currj) + b*Y(currj) + a*X(currj);
  353.             GLuint flagI = INSIDE(dpI);
  354.  
  355.         if (flagI ^ flagJ) {
  356.            GLfloat t;
  357.            GLuint in;
  358.            GLuint out;
  359.  
  360.            if (flagI) {
  361.           out = prevj;
  362.                   in = currj;
  363.                   t = dpI/(dpI-dpJ);
  364.  
  365.           if (IND&CLIP_TAB_EDGEFLAG)
  366.              VB->EdgeFlagPtr->data[vb_free] =
  367.             VB->EdgeFlagPtr->data[prevj];
  368.            } else {
  369.           in = prevj;
  370.                   out = currj;
  371.                   t = dpJ/(dpJ-dpI);
  372.  
  373.           if (IND&CLIP_TAB_EDGEFLAG)
  374.              VB->EdgeFlagPtr->data[vb_free] = 1;
  375.            }
  376.  
  377.            INTERP_SZ( t, coord, vb_free, in, out, SIZE );
  378.            interp( VB, vb_free, t, in, out);
  379.            outlist[outcount++] = vb_free;
  380.            VB->ClipMask[vb_free++] = 0;
  381.             }
  382.  
  383.         if (flagI) {
  384.            outlist[outcount++] = currj;
  385.         } else {
  386.            VB->ClipMask[currj] |= CLIP_USER_BIT;
  387.         }
  388.  
  389.         prevj = currj;
  390.         flagJ = flagI;
  391.         dpJ = dpI;
  392.          } 
  393.  
  394.      if (outcount < 3)
  395.         return 0;
  396.      else {
  397.             GLuint *tmp;
  398.             tmp = inlist;
  399.             inlist = outlist;
  400.             outlist = tmp;
  401.             n = outcount;
  402.          }
  403.  
  404.       } /* if */
  405.    } /* for p */
  406.  
  407.    if (inlist!=vlist) {
  408.       GLuint i;
  409.       for (i = 0 ; i < n ; i++) 
  410.      vlist[i] = inlist[i];
  411.    }
  412.  
  413.    VB->Free = vb_free;
  414.    return n;
  415. }
  416.  
  417.  
  418. static void TAG(init_clip_funcs)(void)
  419. {
  420.    gl_poly_clip_tab[IND][SIZE] = TAG(viewclip_polygon);
  421.    gl_line_clip_tab[IND][SIZE] = TAG(viewclip_line);
  422. }
  423.  
  424. #undef W
  425. #undef Z
  426. #undef Y
  427. #undef X
  428. #undef SIZE
  429. #undef TAG
  430. #undef INSIDE
  431. #undef OUTSIDE
  432. #undef IND
  433.