www.pudn.com > RayTracing Code.rar > Clipp3D.cpp, change:2004-04-15,size:11311b


/** 3DGPL *************************************************\ 
 * ()                                                     * 
 * 3-D volume and Z clipping.                             * 
 *                                                        * 
 * Defines:                                               * 
 *  C_volume_clipping        Out of view-volume elements; * 
 *                                                        * 
 *  C_line_z_clipping        Clipping a line;             * 
 *  C_polygon_z_clipping     View plane cliping;          * 
 *  C_line_xyz_clipping      Arbitrry clipping of a line; * 
 *  C_polygon_xyz_clipping   Arbitrry plane cliping.      * 
 *                                                        * 
 * (c) 1995-98 Sergei Savchenko, (savs@cs.mcgill.ca)      * 
\**********************************************************/ 
 
#include "RayTracing.h"           /* HW_copy_int stuff */ 
#include "Trans.h"                 /* T_plane etc. */ 
#include "Clipper.h"             /* clipping constants */ 
#include <limits.h>                         /* INT_MAX & INT_MIN */ 
 
int C_3D_clipping;                          /* type of performed clipping */ 
 
/**********************************************************\ 
 * Accept/reject volume clipping.                         * 
 *                                                        * 
 * RETURNS:  0 when extend is for sure outside the        * 
 * --------    view volume, just discard it;              * 
 *          -1 when further clipping is required;         * 
 *           1 when element has a fair chance to be       * 
 *             inside the view volume, and should be      * 
 *             clipped by 2-D clipping when rasterizing.  * 
 *                                                        * 
 *               | z                                      * 
 *          \    |    /      Clipping volume is a pyramid * 
 *           \   |   /       with 90 degree angle,        * 
 *            \  |  /        so the real view volume      * 
 *        -x>z \ | /  x>z    better be inside it.         *  
 *              \|/                                       * 
 *       --------+--------- x                             * 
 *       z<C_Z_CLIPPING_MIN                               * 
 *                                                        * 
\**********************************************************/ 
 
int C_volume_clipping(int *min,int *max) 
{ 
 if((max[2]<min[0])||(max[2]<min[1])||(max[2]<-max[0])|| 
   (max[2]<-max[1])||(max[2]=C_Z_CLIPPING_MIN)) 
 { 
  return(0);                                /* outside */ 
 } 
 else 
 { 
  if(min[2]<C_Z_CLIPPING_MIN) return(-1);   /* partly behind clipping plane */ 
  else return(1); 
 } 
} 
 
/**********************************************************\ 
 * Line clipping using binary search technique.           * 
 *                                                        * 
 * RETURNS: 0 element was outside the view volume;        * 
 * -------- 1 element was clipped to the view volume.     * 
 *                                                        * 
 * SETS: C_3D_clipping to 1 if first vertex was clipped;  * 
 * ----- 0 otherwise.                                     * 
\**********************************************************/ 
 
int C_line_z_clipping(int **vertex1,int **vertex2,int dimension) 
{ 
 register int i; 
 register int whereto; 
 register int *l,*r,*m,*t;                  /* left right midle and tmp */ 
 static int c_store0[C_MAX_DIMENSIONS];     /* static stores for clipped vxes */ 
 static int c_store1[C_MAX_DIMENSIONS]; 
 static int c_store2[C_MAX_DIMENSIONS]; 
 int **vmn,**vmx;                           /* so that *vmn[3]  *vmx[3] */ 
 int swap;                                  /* were coordinates swaped? */ 
 
 C_3D_clipping=0;                           /* default no clipping yet */ 
 
 if((*vertex1)[2]<(*vertex2)[2])            /* only Z counts 0=X,1=Y,2=Z,... */ 
 { swap=0; vmn=vertex1; vmx=vertex2; }      /* so that *vmn[2]  *vmx[2] */ 
 else 
 { swap=1; vmn=vertex2; vmx=vertex1; } 
 
 if((*vmx)[2]=C_Z_CLIPPING_MIN) return(0); /* compleately outside */ 
 else 
 { 
  if((*vmn)[2]=C_Z_CLIPPING_MIN)           /* clipping */ 
  { 
   HW_copy_int(*vmn,m=c_store0,dimension);  /* copying old vertices */ 
   HW_copy_int(*vmx,r=c_store1,dimension); 
   l=c_store2; 
 
   whereto=1; 
   while(m[2]!=C_Z_CLIPPING_MIN) 
   { 
    if(whereto==1) { t=l; l=m; m=t; } 
    else           { t=r; r=m; m=t; } 
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1; 
    whereto=m[2]<C_Z_CLIPPING_MIN; 
   } 
   *vmn=m;                                  /* that is why m[] is static */ 
   C_3D_clipping=swap^1; 
  } 
  return(1);                                /* partialy or not clipped */ 
 } 
} 
 
/***********************************************************\ 
 * Creating a z-clipped polygon.                           * 
 *                                                         * 
 * RETURNS: number of elements in the clipped polygon.     * 
 * -------- (0 when compleately behind view plane)         * 
 *                                                         * 
 *         |            1-2-3-4-5-6-1  -> 2-2'-5'-6-1-2    * 
 *         |5'                                             * 
 *      5*-*-----*6     If first vertex in the line is     * 
 *      /  |      \     clipped, both vertices are copyed, * 
 *    4*   |       *1   If no clipping or second one is    * 
 *      \  |      /     clipped then only second one is    * 
 *      3*-*-----*2     copyed. If both vertices are       * 
 *         |2'          clipped, neither one is copyed.    * 
 *                                                         * 
\***********************************************************/ 
 
int C_polygon_z_clipping(int *from,register int *to, 
                         int dimension,int length 
                        ) 
{ 
 register int i; 
 int *v1,*v2,new_lng=0; 
 int *first_vrtx=to;                        /* begining of the source */ 
 
 for(i=0;i<length;i++)                      /* for all edges */ 
 { 
  v1=(int*)from; from+=dimension; v2=(int*)from; 
 
  if(C_line_z_clipping(&v1,&v2,dimension))  /* clipping */ 
  { 
   if(C_3D_clipping)                        /* depends which one was clipped */ 
   { 
    HW_copy_int(v1,to,dimension); to+=dimension; 
    HW_copy_int(v2,to,dimension); to+=dimension; 
    new_lng+=2;                             /* first point clipped */ 
   } 
   else 
   { 
    HW_copy_int(v2,to,dimension); to+=dimension; 
    new_lng++;                              /* second point clipped */ 
   } 
  } 
 } 
 HW_copy_int(first_vrtx,to,dimension);      /* looping the polygon vertices */ 
 
 return(new_lng); 
} 
 
/**********************************************************\ 
 * Line clipping using binary search technique.           * 
 *                                                        * 
 * RETURNS: 0 when line is compleately outside;           * 
 * -------- 1 otherwise.                                  * 
 *                                                        * 
 * SETS:  C_3D_clipping to 1 when first or both points    * 
 * -----  were changed; 0 otherwise.                      * 
\**********************************************************/ 
 
int C_line_xyz_clipping(int **vertex1,int **vertex2, 
                        int *by1,int *by2,int *by3, 
                        int dimension 
                       ) 
{ 
 int v1,v2,plane[4],tmp[3];                 /* plane equation */ 
 register int i; 
 register int whereto; 
 register int *l,*r,*m,*t;                  /* left right midle and tmp */ 
 static int c_store0[C_MAX_DIMENSIONS];     /* static stores for clipped vxes */ 
 static int c_store1[C_MAX_DIMENSIONS]; 
 static int c_store2[C_MAX_DIMENSIONS]; 
 int **vmn,**vmx;                           /* so that *vmn[3]  *vmx[3] */ 
 int swap,itmp;                             /* were coordinates swaped? */ 
 
 C_3D_clipping=0;                           /* default no clipping yet */ 
 
 T_plane(by1,by2,by3,plane); 
 v1=T_vertex_on_plane(*vertex1,plane); 
 v2=T_vertex_on_plane(*vertex2,plane); 
 
 if(v1<v2) 
 { swap=0; vmn=vertex1; vmx=vertex2; } 
 else 
 { swap=1; vmn=vertex2; vmx=vertex1; itmp=v1; v1=v2; v2=itmp; } 
 
 if(v2=0) return(0);                       /* compleately outside */ 
 else 
 { 
  if(v1=0)                                 /* clipping */ 
  { 
   HW_copy_int(*vmn,l=c_store2,dimension);  /* copying old vertices */ 
   HW_copy_int(*vmn,m=c_store0,dimension);   
   HW_copy_int(*vmx,r=c_store1,dimension); 
 
   whereto=1; 
   while((T_vertex_on_plane(m,plane)!=0)&&  /* while not on the plane and */ 
         (T_norm(T_vector(l,r,tmp,3))>C_TOLERANCE) 
        )                                   /* not close enough */ 
   { 
    if(whereto==1) { t=l; l=m; m=t; } 
    else           { t=r; r=m; m=t; } 
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1; 
    whereto=T_vertex_on_plane(m,plane)<0; 
   } 
   *vmn=m;                                  /* that is why m[] is static */ 
   C_3D_clipping=swap^1; 
  } 
  return(1);                                /* partialy or not clipped */ 
 } 
} 
 
/**********************************************************\ 
 * Creating a polygon clipped by any plane.               * 
 *                                                        * 
 * RETURNS: number of vertices in the clipped polygon.    * 
 * -------- (0 when compleately clipped)                  * 
 *                                                        * 
 *                       1-2-3-4-5-6-1  -> 2'-3'-5'-6'    * 
 *        \ 5'                                            * 
 *      5*-*------*6     If first vertex in the line is   * 
 *      /   \       \    being clipped both vertices are  * 
 *    4*     \       *1  copyed If no clipping or second  * 
 *      \     \ 3'  /    one is clipped then only second  * 
 *      3*-----*--*2     one is copyed. If both vertices  * 
 *              \        are clipped, neither is copyed.  * 
 *                                                        * 
\**********************************************************/ 
 
int C_polygon_xyz_clipping(int *from,register int *to, 
                           int *by1,int *by2,int *by3, 
                           int dimension,int length 
                          ) 
{ 
 register int i; 
 int *v1,*v2,new_lng=0; 
 int *first_vrtx=to;                        /* begining of the source */ 
 
 for(i=0;i<length;i++)                      /* for all edges */ 
 { 
  v1=(int*)from; from+=dimension; v2=(int*)from; 
 
  if(C_line_xyz_clipping(&v1,&v2,by1,by2,by3,dimension)) 
  {                                         /* clipping */ 
   if(C_3D_clipping)                        /* depends which one was clipped */ 
   { 
    HW_copy_int(v1,to,dimension); to+=dimension; 
    HW_copy_int(v2,to,dimension); to+=dimension; 
    new_lng+=2;                             /* first point clipped */ 
   } 
   else 
   { 
    HW_copy_int(v2,to,dimension); to+=dimension; 
    new_lng++;                              /* second point clipped */ 
   } 
  } 
 } 
 HW_copy_int(first_vrtx,to,dimension);      /* looping the polygon vertices */ 
 
 return(new_lng); 
} 
 
/**********************************************************/