多边形可以分解为多个三角形,所以只用实现三角形的填充即可实现多边形的填充,三角形主要分为3类:A左边长B右边长C平底或平顶。
平底或平顶三角形比较简单,填充他们只要分别根据两边的斜率求出Y坐标每增加一个单位相应的X坐标,这样就能求出相应的一对一对左右坐标,然后连接这连个坐标,最后就能实现三角形的填充。
具体的分析过程请查阅:Windows游戏编程大师技巧 第八章
效果图:
代码并未经过优化,可能存在很多BUG,只用于演示用
代码:
//画平底或平顶填充三角形 bool CEnginApp::DrawSolidPloygon(ScPoint spoint[],int lenth,UNINT *vb_start, int lpitch) { if (!vb_start||!spoint||lpitch<=0||lenth<3) return false; if(lenth==3) { //将点从小到大排序 for (int i=0;i<lenth;i++) { for (int k=i+1;k<lenth;k++) { if (spoint[i].x>spoint[k].x) { int temp=spoint[k].x; spoint[k].x=spoint[i].x; spoint[i].x=temp; temp=spoint[k].y; spoint[k].y=spoint[i].y; spoint[i].y=temp; } } } if (spoint[0].y!=spoint[2].y) { if (spoint[0].y==spoint[1].y)//顶点在最右边 { int temp=spoint[1].x; spoint[1].x=spoint[2].x; spoint[2].x=temp; temp=spoint[1].y; spoint[1].y=spoint[2].y; spoint[2].y=temp; } else if (spoint[1].y==spoint[2].y)//顶点在最左边 { int temp=spoint[1].x; spoint[1].x=spoint[0].x; spoint[0].x=temp; temp=spoint[1].y; spoint[1].y=spoint[0].y; spoint[0].y=temp; } } //判断是否是平底或者平顶三角形 double x0,y0,x1,y1,x2,y2; x0=spoint[0].x; y0=spoint[0].y; x1=spoint[1].x; y1=spoint[1].y; x2=spoint[2].x; y2=spoint[2].y; double dleft=(x0-x1)/(y0-y1); double dright=(x2-x1)/(y2-y1); if (y0==y2) { if (y1<y0)//平底 { int start_y=y1,nowy=y1; int start_x=x1; int addy=y2-y1; int left_x=0,right_x=0; ScPoint point1,point2; Plot_Pixel_32(x1,y1,0,255,0,0,vb_start,lpitch); for (int i=1;i<=addy;i++) { nowy++; left_x=start_x+dleft*i; right_x=start_x+dright*i; point1.x=left_x; point1.y=point2.y=nowy; point2.x=right_x; Draw_Line2(point1,point2,RGB(0,255,0),vb_start,lpitch); } } else if (y1>y0)//平顶 { int start_y=y1,nowy=y1; int start_x=x1; int addy=y1-y0; int left_x=0,right_x=0; ScPoint point1,point2; Plot_Pixel_32(x1,y1,0,255,0,0,vb_start,lpitch); for (int i=1;i<=addy;i++) { nowy--; left_x=start_x-dleft*i; right_x=start_x-dright*i; point1.x=left_x; point1.y=point2.y=nowy; point2.x=right_x; Draw_Line2(point1,point2,RGB(0,255,0),vb_start,lpitch); } } } } return true; }
////画右边长或左边长三角形填充图形 bool CEnginApp::DrawNotFlatPloygon(ScPoint spoint[],int lenth,UNINT *vb_start, int lpitch) { if (!vb_start||!spoint||lpitch<=0||lenth<3) return false; if(lenth==3) { //将点从小到大排序 for (int i=0;i<lenth;i++) { for (int k=i+1;k<lenth;k++) { if (spoint[i].x>spoint[k].x) { int temp=spoint[k].x; spoint[k].x=spoint[i].x; spoint[i].x=temp; temp=spoint[k].y; spoint[k].y=spoint[i].y; spoint[i].y=temp; } } } //判断是否是平底或者平顶三角形 double x0,y0,x1,y1,x2,y2; x0=spoint[0].x; y0=spoint[0].y; x1=spoint[1].x; y1=spoint[1].y; x2=spoint[2].x; y2=spoint[2].y; if (y0==y2)//是平底或者平顶 { DrawSolidPloygon(spoint,lenth,vb_start,lpitch); }else//左边长或右边长 { float k,b,dx,dy; ScPoint jPoint; if (y2>y0)//右边长 { dy=y2-y1; dx=x2-x1; k=dx/dy; b=(y1+y2-k*(x1+x2))/2; jPoint.y=y0; jPoint.x=(jPoint.y-b)/k; ScPoint dpoint[3]; dpoint[0].x=spoint[0].x; dpoint[0].y=spoint[0].y; dpoint[1].x=spoint[1].x; dpoint[1].y=spoint[1].y; dpoint[2].x=jPoint.x; dpoint[2].y=jPoint.y; DrawSolidPloygon(dpoint,3,vb_start,lpitch); dpoint[0].x=spoint[0].x; dpoint[0].y=spoint[0].y; dpoint[2].x=spoint[2].x; dpoint[2].y=spoint[2].y; dpoint[1].x=jPoint.x; dpoint[1].y=jPoint.y; DrawSolidPloygon(dpoint,3,vb_start,lpitch); }else//左边长 { dy=y1-y0; dx=x1-x0; k=dx/dy; b=(y1+y0-k*(x1+x0))/2; jPoint.y=y2; jPoint.x=(jPoint.y-b)/k; ScPoint dpoint[3]; dpoint[2].x=spoint[2].x; dpoint[2].y=spoint[2].y; dpoint[1].x=spoint[1].x; dpoint[1].y=spoint[1].y; dpoint[0].x=jPoint.x; dpoint[0].y=jPoint.y; DrawSolidPloygon(dpoint,3,vb_start,lpitch); dpoint[0].x=spoint[0].x; dpoint[0].y=spoint[0].y; dpoint[2].x=spoint[2].x; dpoint[2].y=spoint[2].y; dpoint[1].x=jPoint.x; dpoint[1].y=jPoint.y; DrawSolidPloygon(dpoint,3,vb_start,lpitch); } } } return true; }