进行裁剪步骤有4个
1, 创建ddraw裁减器对象
CreateClipper( 0, LPDIRECTDRAWCLIPPER * , NULL );
2, 创建裁剪队列(即RECT结构的矩形列表,blitter硬件只绘制裁剪区内的内容,其余的都剪掉)
裁剪队列需要填充RGBDATA()的数据结构
Typedef struct _RGNDATA
{
RGNDATAHEADER rdh; //头信息
Char Buffer[1]; //分配大小
}
RGNDATAHEADER结构
Typedef struct _RGNDATAHEADER
{
DWORD dwSize; //sizeof( RGNDATAHEADER)
DWORD iType; //RDH_RECTANGLES
DWORD nCount;//裁剪序列中的RECTS数目
DWORD nRGNSize; //sizeof(RECT ) * nCount,以字节为大小的存储大小
RECT rcBound; //包围所有RECTS的边界
}RGNDATAHEADER
3, 将裁剪队列发送给裁剪器
SetClipList( LPRGNDATA lpClipList, 0 );
4, 将裁剪器同窗口/表面相关联
Surface->SetClipper( & clipper );
原理就是这样,先看看例子。
OK,看看怎么封装,其实这个也简单,T3DLIB已经封装好了。
加上个裁剪器 LPDIRECTDRAWCLIPPER m_lpddclipper;
m_lpddclipper = NULL;
DDraw_Attach_Clipper()函数,把整个步骤都封装好了。
LPDIRECTDRAWCLIPPER DDRAW_Interface::DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
int num_rects,
LPRECT clip_list)
{
// this function creates a clipper from the sent clip list and attaches
// it to the sent surface
int index; // looping var
LPDIRECTDRAWCLIPPER lpddclipper; // pointer to the newly created dd clipper
LPRGNDATA region_data; // pointer to the region data that contains
// the header and clip list
// first create the direct draw clipper
if (FAILED(m_lpdd->CreateClipper(0,&lpddclipper,NULL)))
return(NULL);
// now create the clip list from the sent data
// first allocate memory for region data
region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
// now copy the rects into region data
memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);
// set up fields of header
region_data->rdh.dwSize = sizeof(RGNDATAHEADER);
region_data->rdh.iType = RDH_RECTANGLES;
region_data->rdh.nCount = num_rects;
region_data->rdh.nRgnSize = num_rects*sizeof(RECT);
region_data->rdh.rcBound.left = 64000;
region_data->rdh.rcBound.top = 64000;
region_data->rdh.rcBound.right = -64000;
region_data->rdh.rcBound.bottom = -64000;
// find bounds of all clipping regions
for (index=0; index<num_rects; index++)
{
// test if the next rectangle unioned with the current bound is larger
if (clip_list[index].left < region_data->rdh.rcBound.left)
region_data->rdh.rcBound.left = clip_list[index].left;
if (clip_list[index].right > region_data->rdh.rcBound.right)
region_data->rdh.rcBound.right = clip_list[index].right;
if (clip_list[index].top < region_data->rdh.rcBound.top)
region_data->rdh.rcBound.top = clip_list[index].top;
if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
region_data->rdh.rcBound.bottom = clip_list[index].bottom;
} // end for index
// now we have computed the bounding rectangle region and set up the data
// now let's set the clipping list
if (FAILED(lpddclipper->SetClipList(region_data, 0)))
{
// release memory and return error
free(region_data);
return(NULL);
} // end if
// now attach the clipper to the surface
if (FAILED(lpdds->SetClipper(lpddclipper)))
{
// release memory and return error
free(region_data);
return(NULL);
} // end if
// all is well, so release memory and send back the pointer to the new clipper
free(region_data);
return(lpddclipper);
} // end DDraw_Attach_Cl
OK
下一步,看下根据T3DLIB,如何改进。关于clipper的,进行了下剪切后备缓冲。OK,由于还没有考虑窗口那边的,先只裁剪窗口的 。
//一直裁剪后备缓冲
RECT screen_rect = { 0, 0, SCREEN_WIDTH,SCREEN_HEIGHT };
m_lpddclipper = DDraw_Attach_Clipper( m_lpddsback, 1, & screen_rect );