Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用OpenGL渲染具有大量顶点的填充复杂多边形_C++_Opengl_2d_Triangulation_Concave - Fatal编程技术网

C++ 使用OpenGL渲染具有大量顶点的填充复杂多边形

C++ 使用OpenGL渲染具有大量顶点的填充复杂多边形,c++,opengl,2d,triangulation,concave,C++,Opengl,2d,Triangulation,Concave,我使用OpenGL渲染2D地图,在此过程中,我需要渲染具有大量顶点的填充多边形(100000+)。为此,我使用glu tessellator将多边形细分为三角形,并使用VBO渲染三角形 多边形已成功渲染问题在于细分过程非常缓慢。对于一些顶点数500000的图表,在我的笔记本电脑(i5-3230M 2.6GHz,8G RAM)上需要将近2分钟。这对我的申请来说是不可接受的 有没有比glu细分器更快的其他细分算法 还是我做错了 以下两幅图像是使用的渲染结果 glPolygonMode(GL_FRON

我使用OpenGL渲染2D地图,在此过程中,我需要渲染具有大量顶点的填充多边形(
100000+
)。为此,我使用glu tessellator将多边形细分为三角形,并使用VBO渲染三角形

多边形已成功渲染问题在于细分过程非常缓慢。对于一些顶点数
500000
的图表,在我的笔记本电脑(i5-3230M 2.6GHz,8G RAM)上需要将近2分钟。这对我的申请来说是不可接受的

有没有比glu细分器更快的其他细分算法

还是我做错了

以下两幅图像是使用的渲染结果

glPolygonMode(GL_FRONT, GL_LINE)

编辑:地图数据为静态数据,原始多边形数据为经纬度格式。我已经将镶嵌多边形数据(那些三角形)保存在单独的文件中

为了更清楚(与问题没有直接关系),对于在屏幕上渲染,需要使用投影将LL格式转换为屏幕坐标


问题是,用户可能要安装数千个图表(其中将进行细分)。虽然细分只运行一次,但仍然需要很长时间。

我有一些想法。。。你能把这些关系分成有组织的部分吗。。。有点像网格?然后,如果事情发生了变化,你只能明智地重新组合那些发生变化的部分

地图是静态的还是动态的

用于静态贴图

为什么不将细分多边形存储在某个文件中,而不再次细分它

用于动态贴图

使用不同的渲染方法(不需要对凸多边形进行细分)可能会更快,如下所示:

  • 带有岛状颜色的清晰屏幕
  • 渲染孤岛轮廓

    GL\u LINE\u LOOP
    这样的未填充原语根本不需要进行细分

  • 填写瓦特表

    只需从任何多边形外的点开始,用watter填充地图即可。如果整体填充编码正确(无递归,填充线而非像素),则只需几毫秒。这种方法的问题是,您需要访问渲染的内容,因此至少需要两次渲染。在GPU上实现泛洪填充也不容易

    还有一些替代方案,如在CPU侧存储边缘点,以及在CPU侧预计算瓦特填充。在这种情况下,您需要为图像的每个
    y
    扫描行提供
    x
    坐标列表,该列表将保存每个焊盘的起点和终点。然后只需在单个渲染过程中填充间隙

    这应该在RT中轻松呈现

  • [编辑]增长填充测试演示

    对您的数据进行了迭代增长填充测试。数据集存在一些问题,例如多边形重叠,可能只是孔洞,但我没有填充颜色信息,而是对象ID,因此很难说。反正也可以修。这里是使用我上面提到的方法(动态地图)的small win 32VCL/OpenGL/SW演示:

    • 使用慢速下载,这是免费的,不需要任何注册,只需输入代码
    它是Win32单机版,无需使用OpenGL+VCL进行安装

    • 鼠标滚轮缩放
    • Shift+鼠标滚轮选择不同的多边形
    • 鼠标+左键平移
    可以修复的问题很少,但作为概念证明,它运行良好。我将ASCII映射编译成二进制形式(因此加载速度更快,但形式相同,只是多边形数相同,然后每个多边形的点数和点x、y的点数是64位的两倍。计数是32位整数)

    我正在使用我自己的OpenGL引擎(我无法共享),因此您需要对这些内容进行编码(比如OpenGL和Texture init/set/usage)。无论如何,这里是这个VCL应用程序的C++代码:

    //$$---- Form CPP ----
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <math.h>
    #pragma hdrstop
    #include "win_main.h"
    #include "gl/OpenGL3D_double.cpp"
    #include "performance.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    // VCL
    TMain *Main;
    // OpenGL
    OpenGLtime tim;
    OpenGLscreen scr;
    OpenGL_FBO fbo;
    GLuint txr_map=-1;
    // miscel
    int pn=0;                       // vertex count
    double px0,px1,py0,py1;         // bbox
    double mx,my;                   // mouse
    double view[16],iview[16];      // direct and inverse Modelview matrix
    double zoom=1.0,dzoom=1.1,viewx=0.0,viewy=0.0;  // view
    int index=0;                    // selected polygon
    bool _redraw=true;
    DWORD cl_water=0xFFEE9040;
    DWORD cl_land =0xFF70A0B0;
    DWORD cl_edge =0xFF000000;
    DWORD cl_sel  =0xFF00FFFF;
    AnsiString tcpu,tgpu;
    // map
    List< List<double> > polygon;   // loaded polygons
          List<double>   water;     // points with water from last frame
    //---------------------------------------------------------------------------
    void view_compute()
        {
        double x,y;
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        x=divide(1.0,px1-px0)*scr.aspect;
        y=divide(1.0,py1-py0)*scr._aspect;
        if (x>y) x=y;
        x*=zoom;
        glTranslated(viewx,viewy,0.0);
        glScaled(x,x,1.0);
        glTranslated(-0.5*(px0+px1),-0.5*(py0+py1),0.0);
        glGetDoublev(GL_MODELVIEW_MATRIX,view);
        glPopMatrix();
        matrix_inv(iview,view);
        }
    //---------------------------------------------------------------------------
    void map_load_csv(AnsiString filename)
        {
        BYTE *dat;
        AnsiString lin,s,s0;
        int ix,i,l,hnd,siz,adr;
        double x,y;
        List< AnsiString > id;
    
             id.allocate(128);      id.num=0;
        polygon.allocate(128); polygon.num=0;
    
        hnd=FileOpen(filename,fmOpenRead); if (hnd<0) return;
        siz=FileSeek(hnd,0,2);
            FileSeek(hnd,0,0);
        dat=new BYTE[siz]; if (dat==NULL) { FileClose(hnd); return; }
        siz=FileRead(hnd,dat,siz);
        FileClose(hnd);
    
        adr=0; txt_load_lin(dat,siz,adr,true);
        for (ix=-1,s0="";adr<siz;)
            {
            lin=txt_load_lin(dat,siz,adr,true);
            if (lin=="") continue;
            i=1; l=lin.Length();
            s=str_load_str(lin,i,true); s=s.SubString(2,s.Length()-2);
            if (s0!=s)
                {
                for (ix=0;ix<id.num;ix++) if (id[ix]==s) break;
                if (ix>=id.num)
                    {
                    ix=id.num;
                    id.add(s);
                    polygon.add();
                    polygon[ix].allocate(256);
                    polygon[ix].num=0;
                    }
                s0=s;
                }
            s=str_load_str(lin,i,true); s=s.SubString(2,s.Length()-2); x=str2flt(s);
            s=str_load_str(lin,i,true); s=s.SubString(2,s.Length()-2); y=str2flt(s);
            polygon[ix].add(x);
            polygon[ix].add(y);
            }
        }
    //---------------------------------------------------------------------------
    void map_save_bin(AnsiString filename)
        {
        int hnd,i;
        hnd=FileCreate(filename); if (hnd<0) return;
        FileWrite(hnd,&polygon.num,4);
        for (i=0;i<polygon.num;i++)
            {
            FileWrite(hnd,&polygon[i].num,4);
            FileWrite(hnd,polygon[i].dat,polygon[i].num*8);
            }
        FileClose(hnd);
        }
    //---------------------------------------------------------------------------
    void map_load_bin(AnsiString filename)
        {
        int hnd,i,n,m;
        hnd=FileOpen(filename,fmOpenRead); if (hnd<0) return;
        FileRead(hnd,&n,4);
        polygon.allocate(n); polygon.num=n;
        for (i=0;i<n;i++)
            {
            FileRead(hnd,&m,4);
            polygon[i].allocate(m); polygon[i].num=m;
            FileRead(hnd,polygon[i].dat,m*8);
            }
        FileClose(hnd);
        }
    //---------------------------------------------------------------------------
    void map_bbox()
        {
        int ix,i,n;
        double *p,a;
        pn=0;
        px0=px1=polygon[0][0];
        py0=py1=polygon[0][1];
        for (ix=0;ix<polygon.num;ix++)
            {
            p=polygon[ix].dat;
            n=polygon[ix].num; pn+=n>>1;
            for (i=0;i<n;i+=2)
                {
                a=*p; p++; if (px0>a) px0=a; if (px1<a) px1=a;
                a=*p; p++; if (py0>a) py0=a; if (py1<a) py1=a;
                }
            }
        }
    //---------------------------------------------------------------------------
    void map_draw()
        {
        int ix,i,n;
        double *p,a;
    //  glLineWidth(2.0);
        for (ix=0;ix<polygon.num;ix++)
            {
            p=polygon[ix].dat;
            n=polygon[ix].num;
            if (ix==index) glColor4ubv((BYTE*)&cl_sel);
             else          glColor4ubv((BYTE*)&cl_edge);
            glBegin(GL_LINE_LOOP);
            for (i=0;i<n;i+=2,p+=2) glVertex2dv(p);
            glEnd();
            }
    //  glLineWidth(1.0);
        }
    //---------------------------------------------------------------------------
    void TMain::draw()
        {
        tbeg();
        tim.tbeg();
    
        // [ render outline to texture ]
        fbo.bind(scr);
        glClearColor(divide((cl_land)&255,255),divide((cl_land>>8)&255,255),divide((cl_land>>16)&255,255),1.0);
        scr.cls();
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixd(view);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        if (water.num)  // water start points for grow fill
            {
            // add water around txr border
            glBegin(GL_POINTS);
            glColor4ubv((BYTE*)&cl_water);
            for (int i=0;i<water.num;i+=2)
             glVertex2dv(water.dat+i);
            glEnd();
            }
    
        map_draw();
        scr.exe();
    
        fbo.unbind(scr);
    
        // [ copy GL texture to CPU image ]
        scr.txrs.txr_ld(txr_map);
        // [ create ScanLines for direct pixel access pyx[y][x] ]
        int e,x,y,xs,ys; DWORD **pyx,*p,c0,c1; double a[3];
        xs=scr.txrs.txr.xs;                     // texture resolution (rounded up to power of 2)
        ys=scr.txrs.txr.ys;
        pyx=new DWORD*[ys];
        p=(DWORD*)scr.txrs.txr.txr;             // CPU image pixel data
        for (y=0;y<ys;y++,p+=xs) pyx[y]=p;      // scan line pointers
    
        // [ Grow Fill water ]
        c0=rgb2bgr(cl_land);
        c1=rgb2bgr(cl_water);
        if (water.num==0)   // first frame view must be set so water is on all borders
            {
            // add water around txr border
            for (x=   1,y=0;y<ys;y++) pyx[y][x]=c1;
            for (x=xs-2,y=0;y<ys;y++) pyx[y][x]=c1;
            for (y=   1,x=0;x<xs;x++) pyx[y][x]=c1;
            for (y=ys-2,x=0;x<xs;x++) pyx[y][x]=c1;
            }
    
        for (e=1;e;)                            // grow it
        for (e=0,y=1;y<ys-1;y++)
         for (   x=1;x<xs-1;x++)
          if (pyx[y][x]==c0)
           if ((pyx[y-1][x]==c1)
             ||(pyx[y+1][x]==c1)
             ||(pyx[y][x-1]==c1)
             ||(pyx[y][x+1]==c1)) { e=1; pyx[y][x]=c1; }
    
        // create water start points for next frame
        water.num=0;
        e=4;    // step
        for (y=1;y<ys-2;y+=e)
         for (x=1;x<xs-2;x+=e)
           if ((pyx[y-1][x-1]==c1) // enough water around (x,y)?
             &&(pyx[y-1][x  ]==c1)
             &&(pyx[y-1][x+1]==c1)
             &&(pyx[y  ][x-1]==c1)
             &&(pyx[y  ][x  ]==c1)
             &&(pyx[y  ][x+1]==c1)
             &&(pyx[y+1][x-1]==c1)
             &&(pyx[y+1][x  ]==c1)
             &&(pyx[y+1][x+1]==c1))
                {
                // convert pixel(x,y) -> World(x,y)
                a[0]=divide(2.0*x,xs)-1.0;
                a[1]=divide(2.0*y,ys)-1.0;
                a[2]=0.0;
                matrix_mul_vector(a,iview,a);
                water.add(a[0]);
                water.add(a[1]);
                }
    
        // [ copy CPU image back to GL texture ]
        delete[] pyx;                           // release ScanLines no need for them anymore
        scr.txrs.txr.rgb2bgr();                 // I got RGB/BGR mismatch somewhere
        scr.txrs.txr_st(txr_map);               // scr.txrs.txr.txr holds pointer to 32bit pixel data
        scr.exe();
    
        // [ render texture to screen ]
        scr.cls();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        scr.txrs.bind(txr_map);
        glColor3f(1.0,1.0,1.0);
        glBegin(GL_QUADS);
        glTexCoord2f(0.0,0.0); glVertex2f(-1.0,-1.0);
        glTexCoord2f(1.0,0.0); glVertex2f(+1.0,-1.0);
        glTexCoord2f(1.0,1.0); glVertex2f(+1.0,+1.0);
        glTexCoord2f(0.0,1.0); glVertex2f(-1.0,+1.0);
        glEnd();
        scr.txrs.unbind();
        // [info]
        glColor3f(1.0,1.0,1.0);
        scr.text_init_pix(1.0);
        scr.text(tcpu);
        scr.text(tgpu);
        scr.text_exit();
    
        scr.exe();
        scr.rfs();
    
        tend(); tcpu=" CPU time: "+tstr(1);
        tim.tend();
        }
    //---------------------------------------------------------------------------
    void TMain::mouse(double x,double y,TShiftState sh)
        {
        x=divide(2.0*x,scr.xs)-1.0;
        y=1.0-divide(2.0*y,scr.ys);
        if (sh.Contains(ssLeft))
            {
            viewx+=x-mx;
            viewy+=y-my;
            view_compute();
            _redraw=true;
            }
        mx=x;
        my=y;
        }
    //---------------------------------------------------------------------------
    __fastcall TMain::TMain(TComponent* Owner) : TForm(Owner)
        {
        scr.init(this);
        txr_map=fbo.add(scr);
    //  map_load_csv("map.csv");
    //  map_save_bin("map.bin");
        map_load_bin("map.bin");
        map_bbox();
        view_compute();
        draw();
        _redraw=true;
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormDestroy(TObject *Sender)
        {
        scr.exit();
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormPaint(TObject *Sender)
        {
        _redraw=true;
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormResize(TObject *Sender)
        {
        scr.resize();
        fbo.resize(scr);
        _redraw=true;
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
        {
        if (Shift.Contains(ssShift))
            {
            if (WheelDelta>0) index++; else index--;
            if (index>=polygon.num) index=polygon.num-1;
            if (index<0) index=0;
            _redraw=true;
            }
        else{
            double p[3]={ mx,my,0.0 };
            view_compute();
            matrix_mul_vector(p,iview,p);
            if (WheelDelta>0) zoom*=dzoom; else zoom/=dzoom;
            view_compute();
            matrix_mul_vector(p,view,p);
            viewx-=p[0]-mx;
            viewy-=p[1]-my;
            view_compute();
            _redraw=true;
            }
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormMouseMove(TObject *Sender, TShiftState Shift, int X,int Y) { mouse(X,Y,Shift); }
    void __fastcall TMain::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { mouse(X,Y,Shift); }
    void __fastcall TMain::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { mouse(X,Y,Shift); }
    //---------------------------------------------------------------------------
    void __fastcall TMain::Timer1Timer(TObject *Sender)
        {
        tgpu=AnsiString().sprintf(" GPU time: [%8.3lf ms]",tim.time());
        if (_redraw) { draw(); _redraw=false; }
        }
    //---------------------------------------------------------------------------
    void __fastcall TMain::FormDblClick(TObject *Sender)
        {
        Width+=10; // ignore this had some bug in resize FBO texture and this was for debugging it
        }
    //---------------------------------------------------------------------------
    
    /$$----表格CPP----
    //---------------------------------------------------------------------------
    #包括
    #包括
    #布拉格语hdrstop
    #包括“win_main.h”
    #包括“gl/OpenGL3D\u double.cpp”
    #包括“performance.h”
    //---------------------------------------------------------------------------
    #pragma包(智能初始化)
    #pragma资源“*.dfm”
    //VCL
    TMain*Main;
    //OpenGL
    开放时间;
    OpenGLscreen;
    OpenGL_FBO FBO;
    GLuint-txr_-map=-1;
    //杂烩
    int pn=0;//顶点计数
    双px0,px1,py0,py1;//口技
    双mx,我的;//老鼠
    双视图[16],iview[16];//正逆模型视图矩阵
    双缩放=1.0,dzoom=1.1,viewx=0.0,viewy=0.0;//看法
    int index=0;//选定多边形
    bool_redraw=true;
    DWORD cl_water=0xFFEE9040;
    DWORD CLU land=0xFF70A0B0;
    DWORD cl_边=0xFF000000;
    DWORD cl_sel=0xFF00FFFF;
    发送tcpu、tgpu;
    //地图
    列表<列表>多边形;//加载多边形
    列出水;//最后一帧中的水点
    //---------------------------------------------------------------------------
    void view_compute()
    {
    双x,y;
    glMatrixMode(GLU模型视图);
    glPushMatrix();
    glLoadIdentity();
    x=除以(1.0,px1-px0)*scr.aspect;
    y=除法(1.0,py1-py0)*scr.\u纵横比;
    如果(x>y)x=y;
    x*=缩放;
    GLX(viewx,viewy,0.0);
    glScaled(x,x,1.0);
    glTranslated(-0.5*(px0+px1),-0.5*(py0+py1),0.0);
    glGetDoublev(GL_模型视图_矩阵,视图);
    glPopMatrix();
    矩阵_inv(iview,view);
    }
    //---------------------------------------------------------------------------
    无效映射\u加载\u csv(解析文件名)
    {
    字节*dat;
    林安生,s,s0;
    int