directdraw的图形填充 冷夜

多边形可以分解为多个三角形,所以只用实现三角形的填充即可实现多边形的填充,三角形主要分为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;
}
原文地址:https://www.cnblogs.com/gamesky/p/2673118.html