2013年8月27日星期二(DEMO8_1,画线)

这一节进入了数学阶段,画线,主要介绍了BRESENHAM算法,开始于(x0,y0)点,但是不采用斜率,它先在X轴方向移动1个像素,然后决定如何移动Y方向的像素,以使所描绘的直线尽量接近于实际的线,这是通过使用一个衡量光栅化得出的直线与实际直线之间的接近程度的误差项来实现的,该算法对误差项不断调整,以使得数字化的光栅线能够尽量直接接近直接直线,

 

可以做一些改进,将初始点的位置考虑进去,然后把误差值设置在最小误差和最大误差之间,可以将误差设为0.5,但是由于现在使用的是整数量,所以必须将它乘以2,并将dx和dy的影响考虑进来。误差项调整如下:

X轴方向

Error              = 2 * dy dx

Y轴方向

Error              = 2 * dx dy

 

代码如下所示

int Draw_Line( int x0, int y0, int x1, int y1, UCHAR color, UCHAR * vb_start, int lpitch )

{

     int dx,dy, dx2, dy2, x_inc, y_inc, error,index;

 

     vb_start           = vb_start + x0 + y0 * lpitch;

 

     dx                     = x1- x0;

     dy                     = y1 - y0;

     if( dx >= 0 )

     {

         x_inc              = 1;

     }

     else

     {

         x_inc              = -1;

         dx                 = -dx;

     }

 

     if( dy >= 0 )

     {

         y_inc              = lpitch;

     }

     else

     {

         y_inc              = -lpitch;

         dy                 = -dy;

     }

 

     dx2                    = dx << 1;

     dy2                    = dy << 1;

 

 

     if( dx > dy )

     {

         error              = dy2 - dx;

 

         for( index = 0; index <= dx; index ++ )

         {

              * vb_start    = color;

              if( error >= 0 )

              {

                   error    -= dx2;

                   vb_start+= y_inc;

              }

              error         += dy2;

              vb_start += x_inc;

         }

     }

     else

     {

         error              = dx2 - dy;

         for( index = 0; index <= dy; index++ )

         {

              *vb_start = color;

              if( error >= 0 )

              {

                   error    -= dy2;

                   vb_start+= x_inc;

              }

              error         += dx2;

              vb_start += y_inc;

         }

     }

 

     return ( 1 );

 

 

}

上述函数,可以分为三部分,第一部分是处理正负号和端点交换,并计算X,Y,轴的增量,然后,根据线的主要走向,即根据dx>dy还是dy>dx,两个主循环其中的一个把线绘制出来。

结果如下图所示,

OK,现在看看如何封装起来。

首先加一个成员函数

int DDRAW_Interface::Draw_Line( int x0, int y0, int x1, int y1, UCHAR color, UCHAR * vb_start, int lpitch )

{

     int dx,dy, dx2, dy2, x_inc, y_inc, error,index;

 

     vb_start           = vb_start + x0 + y0 * lpitch;

 

     dx                     = x1- x0;

     dy                     = y1 - y0;

     if( dx >= 0 )

     {

         x_inc              = 1;

     }

     else

     {

         x_inc              = -1;

         dx                 = -dx;

     }

 

     if( dy >= 0 )

     {

         y_inc              = lpitch;

     }

     else

     {

         y_inc              = -lpitch;

         dy                 = -dy;

     }

 

     dx2                    = dx << 1;

     dy2                    = dy << 1;

 

 

     if( dx > dy )

     {

         error              = dy2 - dx;

 

         for( index = 0; index <= dx; index ++ )

         {

              * vb_start    = color;

              if( error >= 0 )

              {

                   error    -= dx2;

                   vb_start+= y_inc;

              }

              error         += dy2;

              vb_start += x_inc;

         }

     }

     else

     {

         error              = dx2 - dy;

         for( index = 0; index <= dy; index++ )

         {

              *vb_start = color;

              if( error >= 0 )

              {

                   error    -= dy2;

                   vb_start+= x_inc;

              }

              error         += dx2;

              vb_start += y_inc;

         }

     }

 

     return ( 1 );

 

 

}

 

在game_main()中

 

int Game_Main(void *parms = NULL, int num_parms = 0)

{

     // this is the main loop of the game, do all your processing

     // here

 

     // make sure this isn't executed again

     if (window_closed)

         return(0);

 

     // for now test if user is hitting ESC and send WM_CLOSE

     if (KEYDOWN(VK_ESCAPE))

     {

         PostMessage(main_window_handle,WM_CLOSE,0,0);

         window_closed = 1;

     } // end if

 

     ddraw->DDraw_Lock_Primary_Surface();

 

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

     {

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

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

              rand() % 256,

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

 

     }

 

     ddraw->DDraw_Unlock_Primary_Surface();

     Sleep( 33 );

 

 

 

 

 

 

     // do nothing -- look at pretty picture

 

     // return success or failure or your own return code here

     return(1);

 

} // end Game_Main

运行OK

 

下一步看看T3DLIB,发现还有个16位的函数

 

int DDRAW_Interface::Draw_Line16( int x0, int y0, int x1, int y1, int color, UCHAR * vb_start, int lpitch )

{

     int dx,dy, dx2, dy2, x_inc, y_inc, error,index;

 

     int lpitch_2       = lpitch >> 1;

 

      USHORT * vb_start2    = ( USHORT * )vb_start + x0 + y0 * lpitch_2;

 

     dx                     = x1- x0;

     dy                     = y1 - y0;

     if( dx >= 0 )

     {

         x_inc              = 1;

     }

     else

     {

         x_inc              = -1;

         dx                 = -dx;

     }

 

     if( dy >= 0 )

     {

         y_inc              = lpitch_2;

     }

     else

     {

         y_inc              = -lpitch_2;

         dy                 = -dy;

     }

 

     dx2                    = dx << 1;

     dy2                    = dy << 1;

 

 

     if( dx > dy )

     {

         error              = dy2 - dx;

 

         for( index = 0; index <= dx; index ++ )

         {

              * vb_start2   = ( USHORT )color;

              if( error >= 0 )

              {

                   error    -= dx2;

                   vb_start2+= y_inc;

              }

              error         += dy2;

              vb_start2 += x_inc;

         }

     }

     else

     {

         error              = dx2 - dy;

         for( index = 0; index <= dy; index++ )

         {

              *vb_start2    =(USHORT) color;

              if( error >= 0 )

              {

                   error    -= dy2;

                   vb_start2+= x_inc;

              }

              error         += dx2;

              vb_start2 += y_inc;

         }

     }

 

     return ( 1 );

 

 

}

 

 

 

在GAME_MAIN()里,是    ddraw->Draw_Line16( rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT,

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

              RGB( rand() % 256, rand() % 256, rand() % 256 ),

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

 

即RGB(r,g,b)代替以前的rand()%256

Ok

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值