2013年8月28日星期三(8-2,裁剪Cohen_sutherland算法)

这节就是只保留裁剪区域内的像素,这个例子用直线表示,分为4种情况

1,   直线完全在裁剪区外,不用处理

2,   直线完全在裁剪区之内,也无需改动,直接光栅化

3,   直线的一个端点在裁剪区之外,必须进行裁剪

4,   直线的两个端点都在裁剪区之外,但部分在裁剪区之内。必须进行裁剪

 

Cohen-Sutherland算法中,把裁剪区分成很多部分,然后给每一段被裁剪的线段的两端分配一位代码,而后,只采用少量的if语句或一个case语句,就能判断具体情况

 

#define  CLIP_CODE_C            0x0000   //裁剪区域

#define  CLIP_CODE_N            0x0008   //裁剪区北(上方)

#define  CLIP_CODE_S            0x0004   //南(下方)

#define  CLIP_CODE_E            0x0002   //东(右)

#define  CLIP_CODE_W            0x0001   //西(左)

 

#define  CLIP_CODE_NE       0x000a        //东北(右上)

#define  CLIP_CODE_SE       0x0006        //东南(右下)

#define  CLIP_CODE_NW       0x0009        //西北(左上)

#define  CLIP_CODE_SW       0x0005        //西南(左下)

 

仔细研读了下代码,就是分区-》裁剪-》定两点

具体如下int   Clip_Line( int & x1, int & y1, int *x2, int & y2 )

{

#define  CLIP_CODE_C            0x0000

#define  CLIP_CODE_N            0x0008

#define  CLIP_CODE_S            0x0004

#define  CLIP_CODE_E            0x0002

#define  CLIP_CODE_W            0x0001

 

#define  CLIP_CODE_NE       0x000a

#define  CLIP_CODE_SE       0x0006

#define  CLIP_CODE_NW       0x0009

#define  CLIP_CODE_SW       0x0005

 

     int xc1                     = x1,

         yc1                    = y1,

         xc2                    = x2,

         yc2                    = y2;

 

     int  p1_code                = 0,

         p2_code                = 0;

 

     if( y1 < min_clip_y )

         p1_code                |= CLIP_CODE_N;

     else

         if( y1 > max_clip_y )

              p1_code                |= CLIP_CODE_S;

 

     if( y2 < min_clip_y )

         p1_code                |= CLIP_CODE_N;

     else

         if( y2 > max_clip_y )

              p1_code                |= CLIP_CODE_S;

 

     if( y1 < min_clip_x )

         p1_code                |= CLIP_CODE_W;

     else

         if( y1 > max_clip_x )

              p1_code                |= CLIP_CODE_E;

 

     if( y1 < min_clip_x )

         p1_code                |= CLIP_CODE_W;

     else

         if( y1 > max_clip_x )

              p1_code                |= CLIP_CODE_E;

 

     if( p1_code == 0 && p2_code ==  0 )

         return ( 1 );

 

     switch( p1_code )

     {

     case CLIP_CODE_C:

         break;

 

     case CLIP_CODE_N:

         {

              yc1                = min_clip_y;

              xc1                = x1 + 0.5 + ( min_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

         }

         break;

 

 

     case CLIP_CODE_S:

         {

              yc1                = max_clip_y;

              xc1                = x1 + 0.5 + ( max_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

         }

         break;

 

     case CLIP_CODE_W:

         {

              xc1                = min_clip_x;

              yc1               = y1 + 0.5 + ( min_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

         }

         break;

 

 

     case CLIP_CODE_E:

         {

              xc1                = max_clip_x;

              yc1                = y1 + 0.5 + ( max_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

         }

         break;

 

     case CLIP_CODE_NE:

         {

              yc1                = min_clip_y;

              xc1                = x1 + 0.5 + ( min_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

              if( xc1 < min_clip_x || xc1 > max_clip_x )

              {

                   xc1                = max_clip_x;

                   yc1                = y1 + 0.5 + ( max_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

              }

         }

         break;

 

 

     case CLIP_CODE_SE:

         {

              yc1                = max_clip_y;

              xc1                = x1 + 0.5 + ( max_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

              if( xc1 < min_clip_x || xc1 > max_clip_x )

              {

                   xc1                = max_clip_x;

                   yc1                = y1 + 0.5 + ( max_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

              }

         }

         break;

 

 

     case CLIP_CODE_NW:

         {

              yc1                = min_clip_y;

              xc1                = x1 + 0.5 + ( min_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

              if( xc1 < min_clip_x || xc1 > max_clip_x )

              {

                   xc1                = min_clip_x;

                   yc1                = y1 + 0.5 + ( min_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

              }

         }

         break;

 

 

     case CLIP_CODE_SW:

         {

              yc1                = max_clip_y;

              xc1                = x1 + 0.5 + ( max_clip_y - y1 ) * ( x2 - x1 ) / ( y2 - y1 );

 

              if( xc1 < min_clip_x || xc1 > max_clip_x )

              {

                   xc1                = min_clip_x;

                   yc1                = y1 + 0.5 + ( min_clip_x - x1 ) * ( y2 - y1 ) / ( x2 - x1 );

              }

         }

         break;

 

     default:

         break;

     }

 

     switch( p2_code )

     {

     case CLIP_CODE_C:

         break;

 

     case CLIP_CODE_N:

         {

              yc2                = min_clip_y;

              xc2                = x2  + ( min_clip_y - y2 ) * ( x1 - x2 ) / ( y1 - y2 );

         }

         break;

 

 

     case CLIP_CODE_S:

         {

              yc2                = max_clip_y;

              xc2                = x2 + ( max_clip_y - y2 ) * ( x1 - x2 ) / ( y1 - y2 );

         }

         break;

 

     case CLIP_CODE_W:

         {

              xc2                = min_clip_x;

              yc2                = y2 + ( min_clip_x - x2 ) * ( y1 - y2 ) / ( x1 - x2 );

         }

         break;

 

 

     case CLIP_CODE_E:

         {

              xc2                = max_clip_x;

              yc2                = y2 + ( max_clip_x - x2 ) * ( y1 - y2 ) / ( x1 - x2 );

         }

         break;

 

     case CLIP_CODE_NE:

         {

              yc2                = min_clip_y;

              xc2                = x2 + 0.5 + ( min_clip_y - y2 ) *  ( x1 - x2 ) / ( y1 - y2 );

              if( xc2 < min_clip_x || xc2 > max_clip_x )

              {

                   xc2                = max_clip_x;

                   yc2                = y2 + 0.5 + ( max_clip_x - x2 ) *( y1 - y2 ) / ( x1 - x2 );

              }

         }

         break;

 

 

     case CLIP_CODE_SE:

         {

              yc2                = max_clip_y;

              xc2                = x2 + 0.5 + ( max_clip_y - y2 ) * ( x1 - x2 ) / ( y1 - y2 );

              if( xc2 < min_clip_x || xc2 > max_clip_x )

              {

                   xc2                = max_clip_x;

                   yc2                = y2 + 0.5 + ( max_clip_x - x2 ) *( y1 - y2 ) / ( x1 - x2 );

              }

         }

         break;

 

 

     case CLIP_CODE_NW:

         {

              yc2                = min_clip_y;

              xc2                = x2 + 0.5 + ( min_clip_y - y2 ) *  ( x1 - x2 ) / ( y1 - y2 );

              if( xc2 < min_clip_x || xc2 > max_clip_x )

              {

                   xc2                = min_clip_x;

                   yc2                = y2 + 0.5 + ( min_clip_x - x2 ) *( y1 - y2 ) / ( x1 - x2 );

              }

         }

         break;

 

 

     case CLIP_CODE_SW:

         {

              yc2                = max_clip_y;

              xc2                = x2 + 0.5 + ( max_clip_y - y2 ) * ( x1 - x2 ) / ( y1 - y2 );

 

              if( xc2 < min_clip_x || xc2 > max_clip_x )

              {

                   xc2                = min_clip_x;

                   yc2                = y2 + 0.5 + ( min_clip_x - x2 ) *( y1 - y2 ) / ( x1 - x2 );

              }

         }

         break;

 

     default:

         break;

     }

 

     if( ( xc1 < min_clip_x ) || ( xc1 > max_clip_x ) ||

         ( yc1 < min_clip_y ) || ( yc1 > max_clip_y ) ||

         ( xc2 < min_clip_x ) || ( xc2 > max_clip_x ) ||

         ( yc2 < min_clip_y ) || ( yc2 > max_clip_y ) )

     {

         return ( 0 );

     }

 

     x1                          = xc1;

     y1                          = yc1;

     x2                          = xc2;

     y2                          = yc2;

 

     return ( 1 );

}

 

下一步,还要绘制

int  Draw_Clip_Line( int x0, int y0, int x1,int y1, UCHAR color, UCHAR * dest_buffer, int lpitch )

{

     int cxs, int cys, cxe, cye;

 

     cxs                    = x0;

     cys                    = y0;

     cxe                    = x1;

     cye                    = y1;

 

     if( Clip_Line( cxs, cys, cxe, cye ) )

         Draw_Line( cxs, cys, cxe, cye, color, dest_buffer, lpitch );

 

     return ( 1 );

 

 

}

如下。

 

 

在成员函数中,先设定矩形裁剪常量

 

#define min_clip_x                             ( SCREEN_WIDTH / 2 ) - 100 

#define  max_clip_x                                ( SCREEN_HEIGHT / 2 ) + 100

#define  min_clip_y                                ( SCREEN_HEIGHT / 2 ) - 100

#define  max_clip_y                                ( SCREEN_HEIGHT / 2 ) + 100

进行成员函数。

int  DDRAW_Interface::Draw_Clip_Line(int x0, int y0, int x1, int y1, UCHAR color, UCHAR * dest_buffer,int lpitch )

{

     int cxs,  cys, cxe, cye;

 

     cxs                    = x0;

     cys                    = y0;

     cxe                    = x1;

     cye                    = y1;

 

     if( Clip_Line( cxs, cys, cxe, cye ) )

         Draw_Line( cxs, cys, cxe, cye, color, dest_buffer, lpitch );

 

     return ( 1 );

 

 

}

 

 

int DDRAW_Interface::Clip_Line(int &x1,int &y1,int &x2,int &y2)

{

// this function clips the sent line using the globally defined clipping

// region

 

// internal clipping codes

#define CLIP_CODE_C  0x0000

#define CLIP_CODE_N  0x0008

#define CLIP_CODE_S  0x0004

#define CLIP_CODE_E  0x0002

#define CLIP_CODE_W  0x0001

 

#define CLIP_CODE_NE 0x000a

#define CLIP_CODE_SE 0x0006

#define CLIP_CODE_NW 0x0009

#define CLIP_CODE_SW 0x0005

 

int xc1=x1,

    yc1=y1,

     xc2=x2,

     yc2=y2;

 

int p1_code=0,

    p2_code=0;

 

// determine codes for p1 and p2

if (y1 < min_clip_y)

     p1_code|=CLIP_CODE_N;

else

if (y1 > max_clip_y)

     p1_code|=CLIP_CODE_S;

 

if (x1 < min_clip_x)

     p1_code|=CLIP_CODE_W;

else

if (x1 > max_clip_x)

     p1_code|=CLIP_CODE_E;

 

if (y2 < min_clip_y)

     p2_code|=CLIP_CODE_N;

else

if (y2 > max_clip_y)

     p2_code|=CLIP_CODE_S;

 

if (x2 < min_clip_x)

     p2_code|=CLIP_CODE_W;

else

if (x2 > max_clip_x)

     p2_code|=CLIP_CODE_E;

 

// try and trivially reject

if ((p1_code & p2_code))

     return(0);

 

// test for totally visible, if so leave points untouched

if (p1_code==0 && p2_code==0)

     return(1);

 

// determine end clip point for p1

switch(p1_code)

       {

       case CLIP_CODE_C: break;

 

       case CLIP_CODE_N:

            {

            yc1 = min_clip_y;

            xc1 = x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1);

            } break;

       case CLIP_CODE_S:

            {

            yc1 = max_clip_y;

            xc1 = x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1);

            } break;

 

       case CLIP_CODE_W:

            {

            xc1 = min_clip_x;

            yc1 = y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1);

            } break;

        

       case CLIP_CODE_E:

            {

            xc1 = max_clip_x;

            yc1 = y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1);

            } break;

 

     // these cases are more complex, must compute 2 intersections

       case CLIP_CODE_NE:

            {

            // north hline intersection

            yc1 = min_clip_y;

            xc1 = x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1);

 

            // test if intersection is valid, of so then done, else compute next

              if (xc1 < min_clip_x || xc1 > max_clip_x)

                   {

                   // east vline intersection

                   xc1 = max_clip_x;

                   yc1 = y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1);

                   } // end if

 

            } break;

      

       case CLIP_CODE_SE:

            {

            // south hline intersection

            yc1 = max_clip_y;

            xc1 = x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1);

 

            // test if intersection is valid, of so then done, else compute next

            if (xc1 < min_clip_x || xc1 > max_clip_x)

               {

                // east vline intersection

                xc1 = max_clip_x;

                yc1 = y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1);

                } // end if

 

            } break;

        

       case CLIP_CODE_NW:

            {

            // north hline intersection

            yc1 = min_clip_y;

            xc1 = x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1);

           

            // test if intersection is valid, of so then done, else compute next

            if (xc1 < min_clip_x || xc1 > max_clip_x)

               {

                xc1 = min_clip_x;

               yc1 = y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1);  

                } // end if

 

            } break;

            

       case CLIP_CODE_SW:

            {

            // south hline intersection

            yc1 = max_clip_y;

            xc1 = x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1);

           

            // test if intersection is valid, of so then done, else compute next

            if (xc1 < min_clip_x || xc1 > max_clip_x)

               {

                xc1 = min_clip_x;

               yc1 = y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1);  

                } // end if

 

            } break;

 

       default:break;

 

       } // end switch

 

// determine clip point for p2

switch(p2_code)

       {

       case CLIP_CODE_C: break;

 

       case CLIP_CODE_N:

            {

            yc2 = min_clip_y;

            xc2 = x2 + (min_clip_y-y2)*(x1-x2)/(y1-y2);

            } break;

 

       case CLIP_CODE_S:

            {

            yc2 = max_clip_y;

            xc2 = x2 + (max_clip_y-y2)*(x1-x2)/(y1-y2);

            } break;

 

       case CLIP_CODE_W:

            {

            xc2 = min_clip_x;

            yc2 = y2 + (min_clip_x-x2)*(y1-y2)/(x1-x2);

            } break;

        

       case CLIP_CODE_E:

            {

            xc2 = max_clip_x;

            yc2 = y2 + (max_clip_x-x2)*(y1-y2)/(x1-x2);

            } break;

 

         // these cases are more complex, must compute 2 intersections

       case CLIP_CODE_NE:

            {

            // north hline intersection

            yc2 = min_clip_y;

            xc2 = x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2);

 

            // test if intersection is valid, of so then done, else compute next

              if (xc2 < min_clip_x || xc2 > max_clip_x)

                   {

                   // east vline intersection

                   xc2 = max_clip_x;

                   yc2 = y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2);

                   } // end if

 

            } break;

      

       case CLIP_CODE_SE:

            {

            // south hline intersection

            yc2 = max_clip_y;

            xc2 = x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2);

 

            // test if intersection is valid, of so then done, else compute next

            if (xc2 < min_clip_x || xc2 > max_clip_x)

               {

                // east vline intersection

                xc2 = max_clip_x;

                yc2 = y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2);

                } // end if

 

            } break;

        

       case CLIP_CODE_NW:

            {

            // north hline intersection

            yc2 = min_clip_y;

            xc2 = x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2);

           

            // test if intersection is valid, of so then done, else compute next

            if (xc2 < min_clip_x || xc2 > max_clip_x)

               {

                xc2 = min_clip_x;

               yc2 = y2 + 0.5+(min_clip_x-x2)*(y1-y2)/(x1-x2);  

                } // end if

 

            } break;

            

       case CLIP_CODE_SW:

            {

            // south hline intersection

            yc2 = max_clip_y;

            xc2 = x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2);

           

            // test if intersection is valid, of so then done, else compute next

            if (xc2 < min_clip_x || xc2 > max_clip_x)

               {

                xc2 = min_clip_x;

               yc2 = y2 + 0.5+(min_clip_x-x2)*(y1-y2)/(x1-x2);  

                } // end if

 

            } break;

    

       default:break;

 

       } // end switch

 

// do bounds check

if ((xc1 < min_clip_x) || (xc1 > max_clip_x) ||

     (yc1 < min_clip_y) || (yc1 > max_clip_y) ||

     (xc2 < min_clip_x) || (xc2 > max_clip_x) ||

     (yc2 < min_clip_y) || (yc2 > max_clip_y) )

     {

     return(0);

     } // end if

 

// store vars back

x1 = xc1;

y1 = yc1;

x2 = xc2;

y2 = yc2;

 

return(1);

}

在game_main()中

for( int index = 0; index < 1000; index ++ )

     {

         ddraw->Draw_Clip_Line( rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT,

              rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT,

               rand() % 256,

              ddraw->getPrimarybuffer(),ddraw->getPrimarylpitch() );

 

     }

 

现在再根据t3dlib进行,发现还有个16位的draw_clip_line16()

 

int  DDRAW_Interface::Draw_Clip_Line16(int x0, int y0, int x1, int y1, int color, UCHAR * dest_buffer,int lpitch )

{

     int cxs,  cys, cxe, cye;

 

     cxs                    = x0;

     cys                    = y0;

     cxe                    = x1;

     cye                    = y1;

 

     if( Clip_Line( cxs, cys, cxe, cye ) )

         Draw_Line16( cxs, cys, cxe, cye, color, dest_buffer, lpitch );

 

     return ( 1 );

 

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值