コード例 #1
0
ファイル: ODdc.cpp プロジェクト: Hakansv/ocpn_draw_pi
void ODDC::DrawPolygonsTessellated( int n, int npoints[], wxPoint points[], wxCoord xoffset, wxCoord yoffset )
{
    if( dc ) {
        int prev = 0;
        for( int i = 0; i < n; i++ ) {
            dc->DrawPolygon( npoints[i], &points[i + prev], xoffset, yoffset );
            prev += npoints[i];
        }
    }
    #ifdef ocpnUSE_GL
    else {
        
        GLUtesselator *tobj = gluNewTess();
        
        gluTessCallback( tobj, GLU_TESS_VERTEX, (_GLUfuncptr) &ODDCvertexCallback );
        gluTessCallback( tobj, GLU_TESS_BEGIN, (_GLUfuncptr) &ODDCbeginCallback );
        gluTessCallback( tobj, GLU_TESS_END, (_GLUfuncptr) &ODDCendCallback );
        gluTessCallback( tobj, GLU_TESS_COMBINE, (_GLUfuncptr) &ODDCcombineCallback );
        gluTessCallback( tobj, GLU_TESS_ERROR, (_GLUfuncptr) &ODDCerrorCallback );
        
        gluTessNormal( tobj, 0, 0, 1);
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
        
        if(glIsEnabled(GL_TEXTURE_2D)) g_bTexture2D = true;
        else g_bTexture2D = false;
        
        ConfigurePen();
        if( ConfigureBrush() ) {
            gluTessBeginPolygon(tobj, NULL);
            int prev = 0;
            for( int j = 0; j < n; j++ ) {
                gluTessBeginContour(tobj);
                for( int i = 0; i < npoints[j]; i++ ) {
                    GLvertex* vertex = new GLvertex();
                    gTesselatorVertices.Add( vertex );
                    vertex->info.x = (GLdouble) points[i + prev].x;
                    vertex->info.y = (GLdouble) points[i + prev].y;
                    vertex->info.z = (GLdouble) 0.0;
                    vertex->info.r = (GLdouble) 0.0;
                    vertex->info.g = (GLdouble) 0.0;
                    vertex->info.b = (GLdouble) 0.0;
                    vertex->info.a = (GLdouble) 0.0;
                    gluTessVertex( tobj, (GLdouble*)vertex, (GLdouble*)vertex );
                }
                gluTessEndContour( tobj );
                prev += npoints[j];
            }
            gluTessEndPolygon(tobj);
        }
        
        gluDeleteTess(tobj);
        for (unsigned int i = 0; i<gTesselatorVertices.Count(); i++)
            delete (GLvertex*)gTesselatorVertices.Item(i);
        gTesselatorVertices.Clear();
        
    }
    #endif    
}
コード例 #2
0
ファイル: LLRegion.cpp プロジェクト: chucksk/OpenCPN
void LLRegion::Put( const LLRegion& region, int winding_rule, bool reverse)
{
    work w(*this);
   
    gluTessCallback( w.tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr) &LLvertexCallback );
    gluTessCallback( w.tobj, GLU_TESS_BEGIN, (_GLUfuncptr) &LLbeginCallback );
    gluTessCallback( w.tobj, GLU_TESS_COMBINE_DATA, (_GLUfuncptr) &LLcombineCallback );
    gluTessCallback( w.tobj, GLU_TESS_END_DATA, (_GLUfuncptr) &LLendCallback );
    gluTessCallback( w.tobj, GLU_TESS_ERROR, (_GLUfuncptr) &LLerrorCallback );
    gluTessProperty(w.tobj, GLU_TESS_WINDING_RULE, winding_rule);
    gluTessProperty(w.tobj, GLU_TESS_BOUNDARY_ONLY, GL_TRUE);
//    gluTessProperty(w.tobj, GLU_TESS_TOLERANCE, 1e-5);

    gluTessNormal( w.tobj, 0, 0, 1);

    gluTessBeginPolygon(w.tobj, &w);

    PutContours(w, *this);
    PutContours(w, region, reverse);
    contours.clear();
    gluTessEndPolygon( w.tobj ); 

    Optimize();
    m_box.Invalidate();
}
コード例 #3
0
ファイル: vrml_board.cpp プロジェクト: jerkey/kicad
VRML_LAYER::VRML_LAYER()
{
    fix = false;
    Fault = false;
    idx = 0;
    ord = 0;
    glcmd   = 0;
    pholes  = NULL;
    maxdev  = 0.02;

    tess = gluNewTess();

    if( !tess )
        return;

    // set up the tesselator callbacks
    gluTessCallback( tess, GLU_TESS_BEGIN_DATA, GLCALLBACK( vrml_tess_begin ) );

    gluTessCallback( tess, GLU_TESS_VERTEX_DATA, GLCALLBACK( vrml_tess_vertex ) );

    gluTessCallback( tess, GLU_TESS_END_DATA, GLCALLBACK( vrml_tess_end ) );

    gluTessCallback( tess, GLU_TESS_ERROR_DATA, GLCALLBACK( vrml_tess_err ) );

    gluTessCallback( tess, GLU_TESS_COMBINE_DATA, GLCALLBACK( vrml_tess_combine ) );

    gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );

    gluTessNormal( tess, 0, 0, 1 );
}
コード例 #4
0
  MapPainterOpenGL::MapPainterOpenGL(const StyleConfigRef& styleConfig)
  : MapPainter(styleConfig,
               new CoordBufferImpl<Vertex3D>()),
    coordBuffer((CoordBufferImpl<Vertex3D>*)transBuffer.buffer),
    tesselator(gluNewTess())
  {
    gluTessNormal(tesselator,
                  0,0,1);

    gluTessCallback(tesselator,
                    GLU_TESS_BEGIN,
                    (GLvoid(CALLBACK *)()) &tessalatorBeginCallback);

    gluTessCallback(tesselator,
                    GLU_TESS_VERTEX,
                    (GLvoid(CALLBACK *)()) &glVertex3dv);

    gluTessCallback(tesselator,
                    GLU_TESS_END,
                    (GLvoid(CALLBACK *)()) &tessalatorEndCallback);

    gluTessCallback(tesselator,
                    GLU_TESS_ERROR,
                    (GLvoid(CALLBACK *)()) &tesselatorErrorCallback);

  }
コード例 #5
0
ファイル: egl_impl.cpp プロジェクト: Dasudian/otp
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
{
  ErlDrvBinary* bin;
  int i;
  int num_vertices;
  GLdouble *n;
  int AP;
  int a_max = 2;
  int i_max = 6;
  num_vertices = * (int *) buff; buff += 8; /* Align */
  n = (double *) buff; buff += 8*3;

  egl_tess.alloc_max = a_max*num_vertices*3;
  bin = driver_alloc_binary(egl_tess.alloc_max*sizeof(GLdouble));
  egl_tess.error = 0;
  egl_tess.tess_coords = (double *) bin->orig_bytes;
  memcpy(egl_tess.tess_coords,buff,num_vertices*3*sizeof(GLdouble));
  egl_tess.index_max = i_max*3*num_vertices;
  egl_tess.tess_index_list = (int *) driver_alloc(sizeof(int) * egl_tess.index_max);

  egl_tess.tess_coords = (double *) bin->orig_bytes;
  egl_tess.index_n = 0;
  egl_tess.alloc_n = num_vertices*3;

  gluTessNormal(tess, n[0], n[1], n[2]);
  gluTessBeginPolygon(tess, 0);
  gluTessBeginContour(tess);
  for (i = 0; i < num_vertices; i++) {
    gluTessVertex(tess, egl_tess.tess_coords+3*i, egl_tess.tess_coords+3*i);
  }
  gluTessEndContour(tess);
  gluTessEndPolygon(tess);

  AP = 0; ErlDrvTermData *rt;
  rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+egl_tess.index_n*2));
  rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");

  for(i=0; i < egl_tess.index_n; i++) {
    rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) egl_tess.tess_index_list[i];
  };
  rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = egl_tess.index_n+1;

  rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
  rt[AP++] = egl_tess.alloc_n*sizeof(GLdouble); rt[AP++] = 0;

  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple

  driver_send_term(port,caller,rt,AP);
  /* fprintf(stderr, "List %d: %d %d %d \r\n",  */
  /* 	  res, */
  /* 	  n_pos,  */
  /* 	  (tess_alloc_vertex-new_vertices)*sizeof(GLdouble),  */
  /* 	  num_vertices*6*sizeof(GLdouble)); */
  driver_free_binary(bin);
  driver_free(egl_tess.tess_index_list);
  driver_free(rt);
  return 0;
}
コード例 #6
0
ファイル: slice.cpp プロジェクト: esoren/YARRH
void Slice::drawPolygon(Polygons &pgs, int layer){

    glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
    GLUtesselator* tess = gluNewTess();
    gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (__stdcall *) ())&BeginCallback);
    gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (__stdcall *) ())&VertexCallback);
    gluTessCallback(tess, GLU_TESS_END, (GLvoid (__stdcall *) ())&EndCallback);
    gluTessCallback(tess, GLU_TESS_COMBINE, (GLvoid (__stdcall *) ())&CombineCallback);
    gluTessCallback(tess, GLU_TESS_ERROR, (GLvoid (__stdcall *) ())&ErrorCallback);
    gluTessNormal(tess, 0.0, 0.0, 1.0);
    gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
    gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); //GL_FALSE
    gluTessBeginPolygon(tess, NULL);
    glPushMatrix();
    glTranslated(0.0,0.0,this->layerHeight*layer);
    for (Polygons::size_type i = 0; i < pgs.size(); ++i)
    {
        gluTessBeginContour(tess);
        for (ClipperLib::Polygon::size_type j = 0; j < pgs[i].size(); ++j)
        {
            GLdouble *vert =
                    NewVector((GLdouble)pgs[i][j].X/1000, (GLdouble)pgs[i][j].Y/1000);
            gluTessVertex(tess, vert, vert);
        }
        gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);
    ClearVectors();

    glColor4f(0.0f, 0.6f, 1.0f, 0.5f);
    glLineWidth(1.8f);

    gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
    gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE);
    for (Polygons::size_type i = 0; i < pgs.size(); ++i)
    {
        gluTessBeginPolygon(tess, NULL);
        gluTessBeginContour(tess);
        for (ClipperLib::Polygon::size_type j = 0; j < pgs[i].size(); ++j)
        {
            GLdouble *vert =
                    NewVector((GLdouble)pgs[i][j].X/1000, (GLdouble)pgs[i][j].Y/1000);
            gluTessVertex(tess, vert, vert);
        }

        glColor4f(0.0f, 0.0f, 0.8f, 0.5f);

        gluTessEndContour(tess);
        gluTessEndPolygon(tess);
    }

    //final cleanup ...
    gluDeleteTess(tess);
    ClearVectors();
    glPopMatrix();
}
コード例 #7
0
ファイル: ocpndc.cpp プロジェクト: libai245/wht1
void ocpnDC::DrawPolygonTessellated( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
{
    if( dc )
        dc->DrawPolygon( n, points, xoffset, yoffset );
#ifdef ocpnUSE_GL
    else {
# ifndef ocpnUSE_GLES  // tessalator in glues is broken
        if( n < 5 )
# endif
        {
            DrawPolygon( n, points, xoffset, yoffset );
            return;
        }

        glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT | GL_POLYGON_BIT ); //Save state
        SetGLAttrs( false );

        static GLUtesselator *tobj = NULL;
        if( ! tobj ) tobj = gluNewTess();

        gluTessCallback( tobj, GLU_TESS_VERTEX, (_GLUfuncptr) &ocpnDCvertexCallback );
        gluTessCallback( tobj, GLU_TESS_BEGIN, (_GLUfuncptr) &ocpnDCbeginCallback );
        gluTessCallback( tobj, GLU_TESS_END, (_GLUfuncptr) &ocpnDCendCallback );
        gluTessCallback( tobj, GLU_TESS_COMBINE, (_GLUfuncptr) &ocpnDCcombineCallback );
        gluTessCallback( tobj, GLU_TESS_ERROR, (_GLUfuncptr) &ocpnDCerrorCallback );

        gluTessNormal( tobj, 0, 0, 1);
        gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );

        if( ConfigureBrush() ) {
            gluTessBeginPolygon( tobj, NULL );
            gluTessBeginContour( tobj );

            for( int i = 0; i < n; i++ ) {
                GLvertex* vertex = new GLvertex();
                gTesselatorVertices.Add( vertex );
                vertex->info.x = (GLdouble) points[i].x;
                vertex->info.y = (GLdouble) points[i].y;
                vertex->info.z = (GLdouble) 0.0;
                vertex->info.r = (GLdouble) 0.0;
                vertex->info.g = (GLdouble) 0.0;
                vertex->info.b = (GLdouble) 0.0;
                gluTessVertex( tobj, (GLdouble*)vertex, (GLdouble*)vertex );
            }
            gluTessEndContour( tobj );
            gluTessEndPolygon( tobj );
        }

        glPopAttrib();

        for( unsigned int i=0; i<gTesselatorVertices.Count(); i++ )
            delete (GLvertex*)gTesselatorVertices.Item(i);
        gTesselatorVertices.Clear();
    }
#endif    
}
コード例 #8
0
void glu_tessnormal( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {

    MOGLDEFMYTESS;
	if (NULL == gluTessNormal) mogl_glunsupported("gluTessNormal");

    gluTessNormal((GLUtesselator*) mytess->glutesselator,
		(GLdouble)mxGetScalar(prhs[1]),
		(GLdouble)mxGetScalar(prhs[2]),
		(GLdouble)mxGetScalar(prhs[3]));

}
コード例 #9
0
ファイル: tesselator.cpp プロジェクト: MEPP-team/libcitygml
void Tesselator::init( const TVec3d& normal, GLenum winding_rule )
{
    gluTessBeginPolygon( _tobj, this );

    gluTessProperty( _tobj, GLU_TESS_WINDING_RULE, winding_rule );
    gluTessNormal( _tobj, normal.x, normal.y, normal.z );

    _vertices.clear();
    _indices.clear();
    _curIndices.clear();
    _texCoordsLists.clear();
    _outIndices.clear();
}
コード例 #10
0
ファイル: triangulate.cpp プロジェクト: dakodun/uair
Triangulate::Triangulate() {
	mTesselator = gluNewTess();
	
	if (mTesselator) {
		gluTessNormal(mTesselator, 0.0d, 0.0d, 1.0d);
		
		gluTessCallback(mTesselator, GLU_TESS_BEGIN,        (void (CALLBACK *)())HandleBegin);
		gluTessCallback(mTesselator, GLU_TESS_END,          (void (CALLBACK *)())HandleEnd);
		gluTessCallback(mTesselator, GLU_TESS_VERTEX_DATA,  (void (CALLBACK *)())HandleVertexData);
		gluTessCallback(mTesselator, GLU_TESS_COMBINE_DATA, (void (CALLBACK *)())HandleCombineData);
		gluTessCallback(mTesselator, GLU_TESS_ERROR_DATA,   (void (CALLBACK *)())HandleErrorData);
		gluTessCallback(mTesselator, GLU_TESS_EDGE_FLAG,    (void (CALLBACK *)())HandleEdgeFlag);
	}
}
コード例 #11
0
ファイル: Tessellation.c プロジェクト: OS2World/DEV-UTIL-HUGS
static void hugsprim_gluTessNormal_20(HugsStackPtr hugs_root)
{
    HsPtr arg1;
    HsDouble arg2;
    HsDouble arg3;
    HsDouble arg4;
    arg1 = hugs->getPtr();
    arg2 = hugs->getDouble();
    arg3 = hugs->getDouble();
    arg4 = hugs->getDouble();
    gluTessNormal(arg1, arg2, arg3, arg4);
    
    hugs->returnIO(hugs_root,0);
}
コード例 #12
0
void FTVectoriser::MakeMesh( FTGL_DOUBLE zNormal)
{
  if( mesh)
  {
    delete mesh;
  }
    
  mesh = new FTMesh;
  
  GLUtesselator* tobj = gluNewTess();
  
  gluTessCallback( tobj, GLU_TESS_BEGIN_DATA,    (ftglCallback)ftglBegin);
  gluTessCallback( tobj, GLU_TESS_VERTEX_DATA,  (ftglCallback)ftglVertex);
  gluTessCallback( tobj, GLU_TESS_COMBINE_DATA,  (ftglCallback)ftglCombine);
  gluTessCallback( tobj, GLU_TESS_END_DATA,    (ftglCallback)ftglEnd);
  gluTessCallback( tobj, GLU_TESS_ERROR_DATA,    (ftglCallback)ftglError);
  
  
  if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
  {
    gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
  }
  else
  {
    gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
  }
  
  
  gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);
  gluTessNormal( tobj, 0.0, 0.0, zNormal);
  gluTessBeginPolygon( tobj, mesh);
  
    for( size_t c = 0; c < contours(); ++c)
    {
      const FTContour* acontour = contourList[c];
      gluTessBeginContour( tobj);
      
        for( size_t p = 0; p < acontour->size(); ++p)
        {
          FTGL_DOUBLE* d = const_cast<FTGL_DOUBLE*>(&acontour->pointList[p].x);
          gluTessVertex( tobj, d, d);
        }
      gluTessEndContour( tobj);
    }
    
  gluTessEndPolygon( tobj);

  gluDeleteTess( tobj);
  
}
コード例 #13
0
ファイル: ml_glutess.c プロジェクト: youjinbou/lablgl
static void iniTesselator(value winding, value by_only, value tolerance)
{
  if (!tobj) {
    tobj=gluNewTess();
    if (!tobj) ml_raise_gl("Failed to initialise the GLU tesselator.");
  }
  gluTessNormal(tobj, 0.0, 0.0, 1.0);
  gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
                  (winding != Val_unit ? GLUenum_val(Field(winding,0))
                   : GLU_TESS_WINDING_ODD));
  gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY,
                  (by_only != Val_unit && Field(by_only,0) != Val_unit));
  gluTessProperty(tobj, GLU_TESS_TOLERANCE,
                  (tolerance != Val_unit ? Float_val(Field(by_only,0)) : 0));
}
コード例 #14
0
ファイル: Tesselator.cpp プロジェクト: trackpack/Software
//input plygonList must be in order - depicting a fill or void
int B9Tesselator::Triangulate( const std::vector<QVector2D>* polygonList, std::vector<QVector2D> *triangleStrip)
{

        unsigned long int i;
        GLUtesselator *tess = gluNewTess(); // create a tessellator
        if(!tess) return 0;  // failed to create tessellation object, return 0


        this->triStrip = triangleStrip;
        this->CombineVertexIndex = 0;

        numPolyVerts = polygonList->size();
        polyverts = new GLdouble*[polygonList->size()];

        for(i = 0; i < polygonList->size(); i++)
        {
            polyverts[i] = new GLdouble[3];
            polyverts[i][0] = GLdouble(polygonList->at(i).x());
            polyverts[i][1] = GLdouble(polygonList->at(i).y());
            polyverts[i][2] = GLdouble(0.0);//zero in the z
        }

        gluTessProperty(tess, GLU_TESS_WINDING_RULE,
                           GLU_TESS_WINDING_NONZERO);
        gluTessNormal(tess, 0, 0, 1);

        // register callback functions
        gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (void (CALLBACK *)())tessBeginCB);
        gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK *)())tessEndCB);
        gluTessCallback(tess, GLU_TESS_ERROR_DATA, (void (CALLBACK *)())tessErrorCB);
        gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (void (CALLBACK *)())tessVertexCB);
        gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (void (CALLBACK *)())tessCombineCB);


        gluTessBeginPolygon(tess, (void*) this);
            gluTessBeginContour(tess);
            for(i = 0; i < numPolyVerts; i++)
            {
                gluTessVertex(tess, polyverts[i], polyverts[i]);
            }
            gluTessEndContour(tess);
        gluTessEndPolygon(tess);


        gluDeleteTess(tess);        // delete after tessellation

        return !(int)memoryFull;
}
コード例 #15
0
VRML_LAYER::VRML_LAYER()
{
    // arc parameters suitable to mm measurements
    maxArcSeg = 48;
    minSegLength = 0.1;
    maxSegLength = 0.5;
    offsetX = 0.0;
    offsetY = 0.0;

    fix = false;
    Fault = false;
    idx = 0;
    hidx = 0;
    eidx = 0;
    ord = 0;
    glcmd   = 0;
    pholes  = NULL;

    tess = gluNewTess();

    if( !tess )
        return;

    // set up the tesselator callbacks
    gluTessCallback( tess, GLU_TESS_BEGIN_DATA, GLCALLBACK( vrml_tess_begin ) );

    gluTessCallback( tess, GLU_TESS_VERTEX_DATA, GLCALLBACK( vrml_tess_vertex ) );

    gluTessCallback( tess, GLU_TESS_END_DATA, GLCALLBACK( vrml_tess_end ) );

    gluTessCallback( tess, GLU_TESS_ERROR_DATA, GLCALLBACK( vrml_tess_err ) );

    gluTessCallback( tess, GLU_TESS_COMBINE_DATA, GLCALLBACK( vrml_tess_combine ) );

    gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );

    gluTessNormal( tess, 0, 0, 1 );
}
コード例 #16
0
ファイル: mygeom.cpp プロジェクト: Ptizef/OpenCPN
//      Build PolyTessGeo Object from OGR Polygon
//      Using OpenGL/GLU tesselator
int PolyTessGeo::BuildTessGLU()
{
    
    unsigned int iir, ip;
    GLdouble *geoPt;


#if 0    
    //  Make a quick sanity check of the polygon coherence
    bool b_ok = true;
    OGRLineString *tls = poly->getExteriorRing();
    if(!tls) {
        b_ok = false;
    }
    else {
        int tnpta  = poly->getExteriorRing()->getNumPoints();
        if(tnpta < 3 )
            b_ok = false;
    }

    
    for( iir=0 ; iir < poly->getNumInteriorRings() ; iir++)
    {
        int tnptr = poly->getInteriorRing(iir)->getNumPoints();
        if( tnptr < 3 )
            b_ok = false;
    }
    
    if( !b_ok )
        return ERROR_BAD_OGRPOLY;
    
#endif
    


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
    m_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
    m_buf_len = NINIT_BUFFER_LEN * 2;
    m_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
    m_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
    GLUtessobj = gluNewTess();

    //  Register the callbacks
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_VERTEX_DATA,  (GLvoid (*) ())&vertexCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_END_DATA,     (GLvoid (*) ())&endCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_COMBINE_DATA, (GLvoid (*) ())&combineCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_ERROR_DATA,   (GLvoid (*) ())&errorCallback);

    gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
    gluTessNormal(GLUtessobj, 0, 0, 1);

//      Get total number of points(vertices)  to build a buffer
    int npta  = 0;

    for( int i=0 ; i < m_ncnt ; i++)
        npta += m_cntr[i];


    geoPt = (GLdouble *)malloc((npta + 6) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

    if((npta * 4) > m_buf_len)
    {
        m_pwork_buf = (GLdouble *)realloc(m_pwork_buf, npta * 4 * sizeof(GLdouble));
        m_buf_len = npta * 4;
    }


//  Define the polygon
    gluTessBeginPolygon(GLUtessobj, this);


    
    //  Check and account for winding direction of ring


      double x0, y0, x, y;
//      OGRPoint p;

      wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[0];
      bool cw = !isRingClockwise(pp, m_cntr[0]);
      
      //pp++;       // skip 0?

      if(cw)
      {
            x0 = pp->m_x;
            y0 = pp->m_y;
      }
      else
      {
            x0 = pp[m_cntr[0]-1].m_x;
            y0 = pp[m_cntr[0]-1].m_y;
      }



      unsigned int ptValid = m_cntr[0];
      
//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
      GLdouble *ppt = geoPt;
      
      for(ip = 0 ; ip < (unsigned int)m_cntr[0] ; ip++)
      {
            int pidx;
            if(cw)
                  pidx = m_cntr[0] - ip - 1;

            else
                  pidx = ip;

            x = pp[pidx].m_x;
            y = pp[pidx].m_y;

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                  if(m_tess_orient == TESS_VERT)
                  {
                        *ppt++ = x;
                        *ppt++ = y;
                        *ppt++ = 0;
                  }
                  else
                  {
                        *ppt++ = y;
                        *ppt++ = x;
                        *ppt++ = 0;
                  }
            }
            else
                  ptValid--;

            x0 = x;
            y0 = y;
      }

      //  Apply LOD reduction
    int beforeLOD = ptValid;
    int afterLOD = beforeLOD;
   
 
    if(ptValid > 20 && (m_LOD_meters > .01)) {
        std::vector<bool> bool_keep(ptValid, false);

        // Keep a few key points
        bool_keep[0] = true;
        bool_keep[1] = true;
        bool_keep[ptValid-1] = true;
        bool_keep[ptValid-2] = true;
        
        DouglasPeuckerDI(geoPt, 1, ptValid-2, m_LOD_meters, bool_keep);
            
        // Create a new buffer
        double *LOD_result = (double *)malloc((m_cntr[0]) * 3 * sizeof(double));     
        double *plod = LOD_result;
        int kept_LOD =0;
        
        for(unsigned int i=0 ; i < ptValid ; i++){
            if(bool_keep[i]){
                double x = geoPt[i*3];
                double y = geoPt[(i*3) + 1];
                *plod++ = x;
                *plod++ = y;
                *plod++ = 0;
                kept_LOD++;
            }
        }

        beforeLOD = ptValid;
        afterLOD = kept_LOD;

        // Copy the lod points back into the vertex buffer
        memcpy(geoPt, LOD_result, kept_LOD * 3 * sizeof(double));
        
        free(LOD_result);
        ptValid = kept_LOD;
    }

    //  Declare the gluContour and copy the points
    gluTessBeginContour(GLUtessobj);
    
    double *DPrun = geoPt;
    for(ip = 0 ; ip < ptValid ; ip++) {
        gluTessVertex( GLUtessobj, DPrun, DPrun ) ;
        DPrun += 3;
    }
  
    gluTessEndContour(GLUtessobj);

    //  Now the interior contours
#if 1    
    int gpIndex = m_cntr[0];
    
    for(iir=0; iir < (unsigned int)m_ncnt-1; iir++){
        
            wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[iir + 1];

            int npti  = m_cntr[iir+1];
            ptValid = npti;
            
            double *ppt = &geoPt[gpIndex * 3]; // next available location in geoPT
            double *DPStart = ppt;
            
      //  Check and account for winding direction of ring
            bool cw = isRingClockwise(pp, m_cntr[iir+1]);

            if(cw)
            {
                  x0 = pp[0].m_x;
                  y0 = pp[0].m_y;
            }
            else
            {
                  x0 = pp[npti-1].m_x;
                  y0 = pp[npti-1].m_y;
            }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
            for(int ip = 0 ; ip < npti ; ip++)
            {
                  int pidx;
                  if(cw)                               // interior contours must be cw
                        pidx = npti - ip - 1;
                  else
                        pidx = ip;


                  x = pp[pidx].m_x;
                  y = pp[pidx].m_y;

                  if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
                  {
                        if(m_tess_orient == TESS_VERT)
                        {
                              *ppt++ = x;
                              *ppt++ = y;
                              *ppt++ = 0;
                        }
                        else
                        {
                              *ppt++ = y;
                              *ppt++ = x;
                              *ppt++ = 0;
                        }
                  }
                  else
                        ptValid--;

                  x0 = x;
                  y0 = y;

            }
            
                       //  Declare the gluContour and reference the points
            gluTessBeginContour(GLUtessobj);
    
            double *DPruni = DPStart;
            for(ip = 0 ; ip < ptValid ; ip++)
            {
                gluTessVertex( GLUtessobj, DPruni, DPruni ) ;
                DPruni += 3;
            }
        
            gluTessEndContour(GLUtessobj);

            gpIndex +=  m_cntr[iir+1];
      }
#endif
        
        
        
        

    m_pTPG_Last = NULL;
    m_pTPG_Head = NULL;
    m_nvmax = 0;

    //      Ready to kick off the tesselator
    gluTessEndPolygon(GLUtessobj);          // here it goes

    m_nvertex_max = m_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

    m_ppg_head = new PolyTriGroup;
    m_ppg_head->m_bSMSENC = m_b_senc_sm;

    m_ppg_head->nContours = m_ncnt;

    m_ppg_head->pn_vertex = m_cntr;             // pointer to array of poly vertex counts
    m_ppg_head->data_type = DATA_TYPE_DOUBLE;
    

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

// Recalculate the size of the geometry buffer
    unsigned int nptfinal = m_cntr[0] + 2;
//     for(int i=0 ; i < nint ; i++)
//         nptfinal += cntr[i+1] + 2;
    
    //  No longer need the full geometry in the SENC,
    nptfinal = 1;
    
    m_nwkb = (nptfinal + 1) * 2 * sizeof(float);
    m_ppg_head->pgroup_geom = (float *)calloc(sizeof(float), (nptfinal + 1) * 2);
    float *vro = m_ppg_head->pgroup_geom;
    ppt = geoPt;
    float tx,ty;

    for(ip = 0 ; ip < nptfinal ; ip++)
    {
        if(TESS_HORZ == m_tess_orient)
        {
            ty = *ppt++;
            tx = *ppt++;
        }
        else
        {
            tx = *ppt++;
            ty = *ppt++;
        }

        if(m_b_senc_sm)
        {
            //  Calculate SM from chart common reference point
            double easting, northing;
            toSM(ty, tx, m_ref_lat, m_ref_lon, &easting, &northing);
            *vro++ = easting;              // x
            *vro++ = northing;             // y
        }
        else
        {
            *vro++ = tx;                  // lon
            *vro++ = ty;                  // lat
        }

        ppt++;                      // skip z
    }

    m_ppg_head->tri_prim_head = m_pTPG_Head;         // head of linked list of TriPrims


    //  Convert the Triangle vertex arrays into a single memory allocation of floats
    //  to reduce SENC size and enable efficient access later
    
    //  First calculate the total byte size
    int total_byte_size = 2 * sizeof(float);
    TriPrim *p_tp = m_ppg_head->tri_prim_head;
    while( p_tp ) {
        total_byte_size += p_tp->nVert * 2 * sizeof(float);
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    
    float *vbuf = (float *)malloc(total_byte_size);
    p_tp = m_ppg_head->tri_prim_head;
    float *p_run = vbuf;
    while( p_tp ) {
        float *pfbuf = p_run;
        GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
        
        for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
            float x = (float)( *((GLdouble *)pdouble_buf) );
            pdouble_buf++;
            *p_run++ = x;
        }
        
        free(p_tp->p_vertex);
        p_tp->p_vertex = (double *)pfbuf;
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    m_ppg_head->bsingle_alloc = true;
    m_ppg_head->single_buffer = (unsigned char *)vbuf;
    m_ppg_head->single_buffer_size = total_byte_size;
    m_ppg_head->data_type = DATA_TYPE_FLOAT;
    
    
    
    
    
    
    gluDeleteTess(GLUtessobj);

    free( m_pwork_buf );
    m_pwork_buf = NULL;

    free (geoPt);

    //      Free up any "Combine" vertices created
    for(unsigned int i = 0; i < m_pCombineVertexArray->GetCount() ; i++)
          free (m_pCombineVertexArray->Item(i));
    delete m_pCombineVertexArray;

    m_bOK = true;

    
    return 0;
}
コード例 #17
0
PsychError SCREENFillPoly(void)  
{	
	PsychColorType				color;
	PsychWindowRecordType		*windowRecord;
	double						whiteValue;
	int							i, mSize, nSize, pSize;
	psych_bool					isArgThere;
	double						*pointList;
	double						isConvex;
	int							j,k;
	int							flag;
	double						z;
	
	combinerCacheSlot = 0;
	combinerCacheSize = 0;
	combinerCache = NULL;
	
	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString,seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous arguments
	PsychErrorExit(PsychCapNumInputArgs(4));   //The maximum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(0));  //The maximum number of outputs
	
	//get the window record from the window record argument and get info from the window record
	PsychAllocInWindowRecordArg(1, kPsychArgRequired, &windowRecord);
	
	//Get the color argument or use the default, then coerce to the form determened by the window depth.  
	isArgThere=PsychCopyInColorArg(2, FALSE, &color);
	if(!isArgThere){
		whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
		PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
	}
 	PsychCoerceColorMode( &color);
	
	//get the list of pairs and validate.  
	PsychAllocInDoubleMatArg(3, kPsychArgRequired, &mSize, &nSize, &pSize, &pointList);
	if(nSize!=2) PsychErrorExitMsg(PsychError_user, "Width of pointList must be 2");
	if(mSize<3)  PsychErrorExitMsg(PsychError_user, "Polygons must consist of at least 3 points; M dimension of pointList was < 3!");
	if(pSize>1)  PsychErrorExitMsg(PsychError_user, "pointList must be a 2D matrix, not a 3D matrix!");
	
	isConvex = -1;
	PsychCopyInDoubleArg(4, kPsychArgOptional, &isConvex);
	
    // On non-OpenGL1/2 we always force isConvex to zero, so the GLU tesselator is
    // always used. This because the tesselator only emits GL_TRIANGLES and GL_TRIANGLE_STRIP
    // and GL_TRIANGLE_FANS primitives which are supported on all current OpenGL API's, whereas
    // or "classic" fast-path needs GL_POLYGONS, which are only supported on classic OpenGL1/2:
    if (!PsychIsGLClassic(windowRecord)) isConvex = 0;

	// Enable this windowRecords framebuffer as current drawingtarget:
	PsychSetDrawingTarget(windowRecord);
	
	// Set default drawshader:
	PsychSetShader(windowRecord, -1);
	
	PsychUpdateAlphaBlendingFactorLazily(windowRecord);		 
	PsychSetGLColor(&color, windowRecord);
	
	///////// Test for convexity ////////
	// This algorithm checks, if the polygon is definitely convex, or not.
	// We take the slow-path, if polygon is non-convex or if we can't prove
	// that it is convex.
	//
	// Algorithm adapted from: http://astronomy.swin.edu.au/~pbourke/geometry/clockwise/
	// Which was written by Paul Bourke, 1998.
	//
	// -> This webpage explains the mathematical principle behind the test and provides
	// a C-Source file which has been adapted for use here.
	//	
	if (isConvex == -1) {
		flag = 0;
		for (i=0; i < mSize; i++) {
			j = (i + 1) % mSize;
			k = (i + 2) % mSize;
			z  = (pointList[j] - pointList[i]) * (pointList[k+mSize] - pointList[j+mSize]);
			z -= (pointList[j+mSize] - pointList[i+mSize]) * (pointList[k] - pointList[j]);
			
			if (z < 0) {
				flag |= 1;
			}
			else if (z > 0) {
				flag |= 2;
			}
			
			if (flag == 3) {
				// This is definitely a CONCAVE polygon --> not Convex --> Take slow but safe path.
				break;
			}
		}
		
		if (flag!=0 && flag!=3) {
			// This is a convex polygon --> Take fast path.
			isConvex = 1;
		}
		else {
			// This is a complex polygon --> can't determine if it is convex or not --> Take slow but safe path.
			isConvex = 0;
		}
	}
			
	////// Switch between fast path and slow path, depending on convexity of polygon:
	if (isConvex > 0) {
		// Convex, non-self-intersecting polygon - Take the fast-path:
		glBegin(GL_POLYGON);
		for(i=0;i<mSize;i++) glVertex2d((GLdouble)pointList[i], (GLdouble)pointList[i+mSize]);
		glEnd();
	}
	else {
		// Possibly concave and/or self-intersecting polygon - At least we couldn't prove it is convex.
		// Take the slow, but safe, path using GLU-Tesselators to break it up into a couple of convex, simple
		// polygons:
		
		// Create and initialize a new GLU-Tesselator object, if needed:
		if (NULL == tess) {
			// Create tesselator:
			tess = gluNewTess();
			if (NULL == tess) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");

			// Assign our callback-functions:
			gluTessCallback(tess, GLU_TESS_BEGIN, GLUTESSCBCASTER PsychtcbBegin);
			gluTessCallback(tess, GLU_TESS_VERTEX, GLUTESSCBCASTER PsychtcbVertex);
			gluTessCallback(tess, GLU_TESS_END, GLUTESSCBCASTER PsychtcbEnd);
			gluTessCallback(tess, GLU_TESS_COMBINE, GLUTESSCBCASTER PsychtcbCombine);

			// Define all tesselated polygons to lie in the x-y plane:
			gluTessNormal(tess, 0, 0, 1);
		}

		// We need to hold the values in a temporary array:
		if (tempvsize < mSize) {
			tempvsize = ((mSize / 1000) + 1) * 1000;
			tempv = (double*) realloc((void*) tempv, sizeof(double) * 3 * tempvsize);
			if (NULL == tempv) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");
		}

		// Now submit our Polygon for tesselation:
		gluTessBeginPolygon(tess, NULL);
		gluTessBeginContour(tess);

		for(i=0; i < mSize; i++) {
			tempv[i*3]=(GLdouble) pointList[i];
			tempv[i*3+1]=(GLdouble) pointList[i+mSize];
			tempv[i*3+2]=0;
			gluTessVertex(tess, (GLdouble*) &(tempv[i*3]), (void*) &(tempv[i*3]));
		}
		
		// Process, finalize and render it by calling our callback-functions:
		gluTessEndContour(tess);
		gluTessEndPolygon (tess);
		
		// Done with drawing the filled polygon. (Slow-Path)
	}
	
	// Mark end of drawing op. This is needed for single buffered drawing:
	PsychFlushGL(windowRecord);
	
	// printf("CombinerCalls %i out of %i allocated.\n", combinerCacheSlot, combinerCacheSize);

	return(PsychError_none);
}
コード例 #18
0
//----------------------------------------------------------
ofVboMesh ofTessellator::tessellate( const ofPolyline& polyline, bool bIs2D ){

	mutex.lock();
	
	clear();
	resultMesh = ofVboMesh();
//	resultMesh.clear();
	
	// now get the tesselator object up and ready:
	GLUtesselator * ofShapeTobj = gluNewTess();
	
#if defined( TARGET_OSX)
#ifndef MAC_OS_X_VERSION_10_5
#define OF_NEED_GLU_FIX
#endif
#endif
	
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// MAC - XCODE USERS PLEASE NOTE - some machines will not be able to compile the code below
	// if this happens uncomment the "OF_NEED_GLU_FIX" line below and it
	// should compile also please post to the forums with the error message, you OS X version,
	// Xcode verison and the CPU type - PPC or Intel. Thanks!
	// (note: this is known problem based on different version of glu.h, we are working on a fix)
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	
	//#define OF_NEED_GLU_FIX
	
#ifdef OF_NEED_GLU_FIX
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)(...))
#else
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)())
#endif
	gluTessCallback( ofShapeTobj, GLU_TESS_BEGIN, OF_GLU_CALLBACK_HACK &ofTessellator::begin);
	gluTessCallback( ofShapeTobj, GLU_TESS_VERTEX, OF_GLU_CALLBACK_HACK &ofTessellator::vertex);
	gluTessCallback( ofShapeTobj, GLU_TESS_COMBINE, OF_GLU_CALLBACK_HACK &ofTessellator::combine);
	gluTessCallback( ofShapeTobj, GLU_TESS_END, OF_GLU_CALLBACK_HACK &ofTessellator::end);
	gluTessCallback( ofShapeTobj, GLU_TESS_ERROR, OF_GLU_CALLBACK_HACK &ofTessellator::error);
	
	gluTessProperty( ofShapeTobj, GLU_TESS_WINDING_RULE, ofGetStyle().polyMode);
	if (!ofGetStyle().bFill){
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, true);
	} else {
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, false);
	}
	gluTessProperty( ofShapeTobj, GLU_TESS_TOLERANCE, 0);
	
	/* ------------------------------------------
	 for 2d, this next call (normal) likely helps speed up ....
	 quote : The computation of the normal represents about 10% of
	 the computation time. For example, if all polygons lie in
	 the x-y plane, you can provide the normal by using the
	 -------------------------------------------  */
	if( bIs2D) 
		gluTessNormal(ofShapeTobj, 0.0, 0.0, 1.0);

	gluTessBeginPolygon( ofShapeTobj, NULL);
	
	for ( int i=0; i<polyline.size(); i++ ) {
		double* point = new double[3];
		point[0] = polyline[i].x;
		point[1] = polyline[i].y;
		point[2] = polyline[i].z;
		ofShapePolyVertexs.push_back(point);
	}

	gluTessBeginContour( ofShapeTobj );
	
	for (int i=0; i<(int)ofShapePolyVertexs.size(); i++) {
		gluTessVertex( ofShapeTobj, ofShapePolyVertexs[i], ofShapePolyVertexs[i]);
	}
	
	gluTessEndContour( ofShapeTobj );

	
	
	// no matter what we did / do, we need to delete the tesselator object
	gluTessEndPolygon( ofShapeTobj);
	gluDeleteTess( ofShapeTobj);
	ofShapeTobj = NULL;
	
   	// now clear the vertices on the dynamically allocated data
   	clear();

	mutex.unlock();
	
	return resultMesh;
	
}
コード例 #19
0
nuiRenderObject* nuiTessellator::GenerateFromShape(float Quality)
{
  gluTessNormal(mpTess, 0,0,1);
  gluTessProperty(mpTess,GLU_TESS_TOLERANCE, 0);
  gluTessCallback(mpTess, GLU_TESS_BEGIN_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessBegin);
  gluTessCallback(mpTess, GLU_TESS_EDGE_FLAG_DATA,NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEdgeFlag);
  gluTessCallback(mpTess, GLU_TESS_VERTEX_DATA,   NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessVertex);
  gluTessCallback(mpTess, GLU_TESS_END_DATA,      NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEnd);
  gluTessCallback(mpTess, GLU_TESS_COMBINE_DATA,  NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessCombine);
  gluTessCallback(mpTess, GLU_TESS_ERROR_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessError);

  gluTessProperty(mpTess,GLU_TESS_BOUNDARY_ONLY, mOutline?GL_TRUE:GL_FALSE);
  nuiShape::Winding Winding = mpShape->GetWinding();
  if (Winding == nuiShape::eNone)
    Winding = nuiShape::eNonZero;
  gluTessProperty(mpTess,GLU_TESS_WINDING_RULE, Winding);

  mpObject = new nuiRenderObject();
  mEdgeFlag = true;

  uint32 countours = mpShape->GetContourCount();

  gluTessBeginPolygon(mpTess, this);
  
  for (uint32 contour = 0; contour < countours; contour++)
  {
    nuiPath Points;
    nuiContour* pContour = mpShape->GetContour(contour);
    NGL_ASSERT(pContour != NULL);

    pContour->Tessellate(Points, Quality);

    uint count = Points.GetCount();
    bool beginNext = true;
    if (count)
    {
      for (uint i = 0; i < count; i++)
      {
        nuiPoint& rPoint = Points[i];
        if (!beginNext && rPoint.GetType() == nuiPointTypeStop)
        {
          gluTessEndContour(mpTess);
          beginNext = true;
        }
        else
        {
          if (beginNext)
          {
            gluTessBeginContour(mpTess);
            beginNext = false;
          }

          GLdouble vec[3] = { rPoint[0], rPoint[1], rPoint[2] };
          gluTessVertex(mpTess, vec, (void*)mTempPoints.AddVertex(rPoint));
        }
      }
      gluTessEndContour(mpTess);
      beginNext = true;
    }
  }

  gluTessEndPolygon(mpTess); 

  nuiRenderObject* pObject = mpObject;
  mpObject = NULL;
  mTempPoints.Clear();
  return pObject;
}
コード例 #20
0
ファイル: FTVectoriser.cpp プロジェクト: AbdelghaniDr/mirror
void FTVectoriser::MakeMesh(FTGL_DOUBLE zNormal, int outsetType, float outsetSize)
{
    if(mesh)
    {
        delete mesh;
    }

    mesh = new FTMesh;

    GLUtesselator* tobj = gluNewTess();

    gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,     (GLUTesselatorFunction)ftglBegin);
    gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,    (GLUTesselatorFunction)ftglVertex);
    gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,   (GLUTesselatorFunction)ftglCombine);
    gluTessCallback(tobj, GLU_TESS_END_DATA,       (GLUTesselatorFunction)ftglEnd);
    gluTessCallback(tobj, GLU_TESS_ERROR_DATA,     (GLUTesselatorFunction)ftglError);

    if(contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
    }
    else
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
    }


    gluTessProperty(tobj, GLU_TESS_TOLERANCE, 0);
    gluTessNormal(tobj, 0.0f, 0.0f, zNormal);
    gluTessBeginPolygon(tobj, mesh);

        for(size_t c = 0; c < ContourCount(); ++c)
        {
            /* Build the */
            switch(outsetType)
            {
                case 1 : contourList[c]->buildFrontOutset(outsetSize); break;
                case 2 : contourList[c]->buildBackOutset(outsetSize); break;
            }
            const FTContour* contour = contourList[c];


            gluTessBeginContour(tobj);
                for(size_t p = 0; p < contour->PointCount(); ++p)
                {
                    const FTGL_DOUBLE* d;
                    switch(outsetType)
                    {
                        case 1: d = contour->FrontPoint(p); break;
                        case 2: d = contour->BackPoint(p); break;
                        case 0: default: d = contour->Point(p); break;
                    }
                    // XXX: gluTessVertex doesn't modify the data but does not
                    // specify "const" in its prototype, so we cannot cast to
                    // a const type.
                    gluTessVertex(tobj, (GLdouble *)d, (GLvoid *)d);
                }

            gluTessEndContour(tobj);
        }
    gluTessEndPolygon(tobj);

    gluDeleteTess(tobj);
}
コード例 #21
0
ファイル: Boundary.cpp プロジェクト: rika/TCC11
void Boundary::render(bool invert) {
  // Calculate the geometry of the border
  calculate();

  //glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);

  // Render the border
  glBegin(GL_QUADS);
  for (int i = 0; i < outerEdges.size(); i++) {
    Edge out = outerEdges[i];
    Edge in = innerEdges[i];

    if (!invert) {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    } else {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    }
    glVertex3f(out.a.x, out.a.y, 0.0);
    glVertex3f(out.b.x, out.b.y, 0.0);
    
    if (!invert) {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    } else {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    }
    glVertex3f(in.b.x, in.b.y, 0.0);
    glVertex3f(in.a.x, in.a.y, 0.0);
  }
  glEnd();
  
  // Fill the border
  if (!invert) {
    glColor3f(1.0, 1.0, 1.0);
  } else {
    glColor3f(0.0, 0.0, 0.0);
  }

  GLUtesselator *tess = gluNewTess();

  gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (*) ()) &glBegin);
  gluTessCallback(tess, GLU_TESS_END, (GLvoid (*) ()) &glEnd);
  gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (*) ()) &glVertex3dv); 
  
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);   
  gluTessNormal(tess, 0, 0, 1);

  gluTessBeginPolygon(tess, NULL);
  gluTessBeginContour(tess);

  GLdouble *vertices = new GLdouble[innerEdges.size() * 3];
  for (int i = 0; i < innerEdges.size(); i++) {
    vertices[(i * 3) + 0] = innerEdges[i].a.x;
    vertices[(i * 3) + 1] = innerEdges[i].a.y;
    vertices[(i * 3) + 2] = 0.0;

    gluTessVertex(tess, vertices + (i * 3), vertices + (i * 3));
  }

  gluTessEndContour(tess);
  gluTessEndPolygon(tess);

  delete [] vertices;
  gluDeleteTess(tess);
}
コード例 #22
0
nuiRenderObject* nuiTessellator::GenerateFromPath(float Quality)
{
  nuiPath Points;

  mpPath->Tessellate(Points, Quality);
  uint count = Points.GetCount();
  if (!count)
    return nullptr;
  
  gluTessNormal(mpTess, 0,0,1);
  gluTessProperty(mpTess,GLU_TESS_TOLERANCE, 0);
  gluTessCallback(mpTess, GLU_TESS_BEGIN_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessBegin);
  gluTessCallback(mpTess, GLU_TESS_EDGE_FLAG_DATA,NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEdgeFlag);
  gluTessCallback(mpTess, GLU_TESS_VERTEX_DATA,   NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessVertex);
  gluTessCallback(mpTess, GLU_TESS_END_DATA,      NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEnd);
  gluTessCallback(mpTess, GLU_TESS_COMBINE_DATA,  NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessCombine);
  gluTessCallback(mpTess, GLU_TESS_ERROR_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessError);

  gluTessProperty(mpTess,GLU_TESS_BOUNDARY_ONLY, mOutline?GL_TRUE:GL_FALSE);
  gluTessProperty(mpTess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);

  mpObject = new nuiRenderObject();
  mEdgeFlag = true;

  gluTessBeginPolygon(mpTess, this);

  bool beginNext = true;

  //printf("Start tesselation\n");
  for (uint i = 0; i < count; i++)
  {
    nuiPoint& rPoint = Points[i];
    if (rPoint.GetType() != nuiPointTypeStop)
    {
      if (beginNext)
      {
        gluTessBeginContour(mpTess);
        beginNext = false;
      }

      double vec[4] = { rPoint[0], rPoint[1], rPoint[2], 0 };
      //printf("%d input %f %f\n", i, vec[0], vec[1]);
      gluTessVertex(mpTess, vec, (void*)mTempPoints.AddVertex(rPoint));
    }
    else
    {
      //printf("End Contour\n");
      gluTessEndContour(mpTess);
      beginNext = true;
    }
  }
  if (Points.Back().GetType() != nuiPointTypeStop)
    gluTessEndContour(mpTess);

  gluTessEndPolygon(mpTess); 

  nuiRenderObject* pObject = mpObject;
  mpObject = NULL;
  mTempPoints.Clear();
  return pObject;
}
コード例 #23
0
ファイル: egl_impl.cpp プロジェクト: Bwooce/otp
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
{
  ErlDrvBinary* bin;
  int i;
  GLdouble* new_vertices;
  int *vertices;
  int num_vertices;
  GLdouble *n;
  int n_pos, AP, res;
  
  num_vertices = * (int *) buff; buff += 8; /* Align */
  n = (double *) buff; buff += 8*3;

  bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));  
  new_vertices = tess_coords = (double *) bin->orig_bytes;
  memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble));
  tess_alloc_vertex = tess_coords + num_vertices*3;

#if 0
  fprintf(stderr, "n=%d\r\n", num_vertices);
#endif 
  vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices);
  
  tess_vertices = vertices;
  
  gluTessNormal(tess, n[0], n[1], n[2]);
  gluTessBeginPolygon(tess, 0);
  gluTessBeginContour(tess);
  for (i = 0; i < num_vertices; i++) {
    gluTessVertex(tess, tess_coords+3*i, tess_coords+3*i);
  }
  gluTessEndContour(tess);
  gluTessEndPolygon(tess);
    
  n_pos = (tess_vertices - vertices); 
  
  AP = 0; ErlDrvTermData *rt;
  rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2));
  rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");

  for(i=0; i < n_pos; i++) {
    rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) vertices[i];
  };
  rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1;

  rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin; 
  rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0;
  
  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple
  
  res = driver_send_term(port,caller,rt,AP);
  /* fprintf(stderr, "List %d: %d %d %d \r\n",  */
  /* 	  res, */
  /* 	  n_pos,  */
  /* 	  (tess_alloc_vertex-new_vertices)*sizeof(GLdouble),  */
  /* 	  num_vertices*6*sizeof(GLdouble)); */
  driver_free_binary(bin);
  driver_free(vertices);
  driver_free(rt);
  return 0;
}
コード例 #24
0
void DVRClipper::clipSlice(      DVRVolume      *volume,
                                 DVRSlice       &unclippedSlice, 
                           const Vec3f          &slicingNormal, 
                                 Real32          dist2RefPlane,
                                 DVRRenderSlice &clippedSlice)
{
    const Vec3f &texScale     = unclippedSlice.getTextureScale    ();
    const Vec3f &texTranslate = unclippedSlice.getTextureTranslate();

    // get clip objects
    DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume, 
                                                        DVRClipObjects);

    // nothing to clip with?
    if(clipObjects == NullFC)
    {
        DVRRenderSlicePrimitive *newPrimitive =  new DVRRenderSlicePrimitive();

        newPrimitive->type = GL_TRIANGLE_FAN;

        for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
        {
            UInt32 idx = (6+numAddPerVertexAttr)*i;
            sliceVertexData[idx    ] = 
                unclippedSlice.getVertex(i).getValues()[0];

            sliceVertexData[idx + 1] = 
                unclippedSlice.getVertex(i).getValues()[1];

            sliceVertexData[idx + 2] =
                unclippedSlice.getVertex(i).getValues()[2];


            // set (standard) texture coordinates
            sliceVertexData[idx + 3] = 
                texScale[0] * 
                unclippedSlice.getVertex(i).getValues()[0] + 
                texTranslate[0];

            sliceVertexData[idx + 4] = 
                texScale[1] * 
                unclippedSlice.getVertex(i).getValues()[1] + 
                texTranslate[1];

            sliceVertexData[idx + 5] = 
                texScale[2] * 
                unclippedSlice.getVertex(i).getValues()[2] + 
                texTranslate[2];      

            newPrimitive->vertices.push_back(&sliceVertexData[idx]);
        }

        clippedSlice.push_back(newPrimitive);
        
        return;
    }

    if(!hasTesselatorSupport)
        return;

    // render colored contours only (usefull for debugging)
    if(clipObjects->getDoContours())
    {
        glDisable(GL_TEXTURE   );
        glDisable(GL_LIGHTING  );

        glBegin  (GL_LINE_STRIP);  
        {
            int col = 0;
            
            for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
            {      
                glColor3f(col % 3 == 0 ? 1.0f : 0.0f, 
                          col % 3 == 1 ? 1.0f : 0.0f, 
                          col % 3 == 2 ? 1.0f : 0.0f);
                
                col++;
                
                glVertex3fv(unclippedSlice.getVertex(i).getValues());
            }
        }
        glEnd();
   
        bool clipAwayOutside = 
            clipObjects->getClipMode() == DVRClipObjects::Difference;
    
        for(UInt32 i = 0; i < clipObjects->count(); i++)
        {
            // get i-th clip object
            DVRClipGeometryPtr clipObject = clipObjects->get(i);
      
            // compute the contours of the triangles intersecting the 
            // current slice

            const DVRTriangleList &contours = 
                clipObject->getContours(dist2RefPlane,
                                        !clipAwayOutside,
                                        slicingNormal);     
      
            if(!contours.empty())
            {
                DVRTriangle *current;
                DVRTriangle *contourStart;
	
                // iterate over all contours
                DVRTriangleList::const_iterator contoursIt;

                for(contoursIt  = contours.begin(); 
                    contoursIt != contours.end  (); 
                    contoursIt++)
                { 
                    contourStart = current = *contoursIt;	 
	  
                    glBegin(GL_LINE_STRIP);	  
                    {
                        int col = 0;
                        
                        // iterate over all triangles in the current contour
                        do
                        {	    	   
                            glColor3f(col % 3 == 0 ? 1.0f : 0.0f, 
                                      col % 3 == 1 ? 1.0f : 0.0f, 
                                      col % 3 == 2 ? 1.0f : 0.0f);

                            col++;

                            glVertex3dv(current->cutPoint);

                            current = current->contourNeighbour;

                        } while(current!= contourStart);
                    }
                    glEnd();
                }
            }
        }
        
        glEnable(GL_TEXTURE );
        glEnable(GL_LIGHTING);
        
    }
    else
    {
        // tesselate and render the clipped slices

        // set the slice normal for tesselation
        gluTessNormal(myTess, 
                      slicingNormal[0], 
                      slicingNormal[1], 
                      slicingNormal[2]);    
        
        clippedSlice.clear();
        
        gluTessBeginPolygon(myTess, &clippedSlice);
    
        // set the slice's base contour
        gluTessBeginContour(myTess);
        
        for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
        {       
            UInt32 idx = (6 + numAddPerVertexAttr) * i;

            sliceVertexData[idx    ] = 
                unclippedSlice.getVertex(i).getValues()[0];

            sliceVertexData[idx + 1] = 
                unclippedSlice.getVertex(i).getValues()[1];

            sliceVertexData[idx + 2] = 
                unclippedSlice.getVertex(i).getValues()[2];

            // set (standard) texture coordinates
            sliceVertexData[idx + 3] = 
                texScale[0] *
                unclippedSlice.getVertex(i).getValues()[0] + 
                texTranslate[0];

            sliceVertexData[idx + 4] = 
                texScale[1] * 
                unclippedSlice.getVertex(i).getValues()[1] + 
                texTranslate[1];

            sliceVertexData[idx + 5] = 
                texScale[2] * 
                unclippedSlice.getVertex(i).getValues()[2] +
                texTranslate[2];

            gluTessVertex(myTess, 
                          &sliceVertexData[idx], 
                          &sliceVertexData[idx]);
        }
        
        gluTessEndContour(myTess);
        
        // set contours of clip objects
        if(clipObjects->getClipMode() != DVRClipObjects::Off)
        {
            // get clip mode
            bool clipAwayOutside = 
                clipObjects->getClipMode() == DVRClipObjects::Difference;
      
            // add the contours of the intersections of the clip geometries 
            // with the slice
            for(UInt32 i = 0; i < clipObjects->count(); i++)
            {
                // get i-th clip object
                DVRClipGeometryPtr clipObject = clipObjects->get(i);
	
                // compute the contours of the triangles intersecting 
                // the current slice

                const DVRTriangleList &contours = 
                    clipObject->getContours( dist2RefPlane,
                                            !clipAwayOutside,
                                             slicingNormal);       
	
                if(!contours.empty())
                {
                    DVRTriangle *current;
                    DVRTriangle *contourStart;
	  
                    // iterate over all contours
                    DVRTriangleList::const_iterator contoursIt;

                    for(contoursIt  = contours.begin(); 
                        contoursIt != contours.end  (); 
                        contoursIt++)
                    { 
                        contourStart = current = *contoursIt;
	    	    
                        // start new contour
                        gluTessBeginContour(myTess);
	    
                        // iterate over all triangles in the current contour
                        do
                        {	    
                            // set (standard) texture coordinates
                            current->cutPoint[3] = 
                                texScale[0] * 
                                current->cutPoint[0] + 
                                texTranslate[0];

                            current->cutPoint[4] = 
                                texScale[1] * 
                                current->cutPoint[1] + 
                                texTranslate[1];

                            current->cutPoint[5] = 
                                texScale[2] * 
                                current->cutPoint[2] + 
                                texTranslate[2];

                            if(!current->cutPoint)
                                std::cerr << "WTF: cutPoint is NULL"
                                          << std::endl;

                            gluTessVertex(myTess, 
                                          current->cutPoint, 
                                          current->cutPoint);

                            current = current->contourNeighbour;

                        } while(current != contourStart);
	    
                        gluTessEndContour(myTess);
                    }
                }
            }
        }
        
        gluTessEndPolygon(myTess);
    }
}
コード例 #25
0
/* draw all solid polygons found in aPolysList
 * aZpos = z position in board internal units
 * aThickness = thickness in board internal units
 * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
 * If aThickness > 0, a solid object is drawn.
 *  The top side is located at aZpos + aThickness / 2
 *  The bottom side is located at aZpos - aThickness / 2
 */
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
        int aZpos, int aThickness, double aBiuTo3DUnits,
        bool aUseTextures )
{
    // for Tess callback functions:
    s_biuTo3Dunits = aBiuTo3DUnits;
    s_useTextures = aUseTextures;

    GLUtesselator* tess = gluNewTess();

    gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB );
    gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB );
    gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
    gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex );

    GLdouble    v_data[3];
    double      zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
    s_currentZpos = zpos;     // for Tess callback functions
    v_data[2] = aZpos + (aThickness / 2.0);

    // Set normal toward positive Z axis, for a solid object on the top side
    if( aThickness )
        SetNormalZpos();

    // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

    // Draw solid areas contained in this list
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex

    int startContour;

    for( int side = 0; side < 2; side++ )
    {
        startContour = 1;

        for( unsigned ii = 0; ii < polylist.GetCornersCount(); ii++ )
        {
            if( startContour == 1 )
            {
                gluTessBeginPolygon( tess, NULL );
                gluTessBeginContour( tess );
                startContour = 0;
            }

            // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
            gluTessNormal( tess, 0.0, 0.0, 0.0 );


            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * aBiuTo3DUnits;
            // gluTessVertex store pointers on data, not data, so do not store
            // different corners values in a temporary variable
            // but send pointer on each CPolyPt value in polylist
            // before calling gluDeleteTess
            gluTessVertex( tess, v_data, &polylist[ii] );


            if( polylist.IsEndContour( ii ) )
            {
                gluTessEndContour( tess );
                gluTessEndPolygon( tess );
                startContour = 1;
            }
        }

        if( aThickness == 0 )
            break;

        // Prepare the bottom side of solid areas
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        s_currentZpos = zpos;     // for Tess callback functions
        v_data[2] = zpos;
        // Set normal toward negative Z axis, for a solid object on bottom side
        SetNormalZneg();
    }

    if( startContour == 0 )
    {
        gluTessEndContour( tess );
        gluTessEndPolygon( tess );
    }

    gluDeleteTess( tess );

    if( aThickness == 0 )
    {
        return;
    }

    // Build the 3D data : vertical side
    Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), false, aBiuTo3DUnits );
}
コード例 #26
0
ファイル: cogl-path.c プロジェクト: 3v1n0/cogl
static void
_cogl_path_build_fill_attribute_buffer (CoglPath *path)
{
  CoglPathTesselator tess;
  unsigned int path_start = 0;
  CoglPathData *data = path->data;
  int i;

  /* If we've already got a vbo then we don't need to do anything */
  if (data->fill_attribute_buffer)
    return;

  tess.primitive_type = FALSE;

  /* Generate a vertex for each point on the path */
  tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
  g_array_set_size (tess.vertices, data->path_nodes->len);
  for (i = 0; i < data->path_nodes->len; i++)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, i);
      CoglPathTesselatorVertex *vertex =
        &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);

      vertex->x = node->x;
      vertex->y = node->y;

      /* Add texture coordinates so that a texture would be drawn to
         fit the bounding box of the path and then cropped by the
         path */
      if (data->path_nodes_min.x == data->path_nodes_max.x)
        vertex->s = 0.0f;
      else
        vertex->s = ((node->x - data->path_nodes_min.x)
                     / (data->path_nodes_max.x - data->path_nodes_min.x));
      if (data->path_nodes_min.y == data->path_nodes_max.y)
        vertex->t = 0.0f;
      else
        vertex->t = ((node->y - data->path_nodes_min.y)
                     / (data->path_nodes_max.y - data->path_nodes_min.y));
    }

  tess.indices_type =
    _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
  _cogl_path_tesselator_allocate_indices_array (&tess);

  tess.glu_tess = gluNewTess ();

  if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD)
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_ODD);
  else
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_NONZERO);

  /* All vertices are on the xy-plane */
  gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0);

  gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
                   _cogl_path_tesselator_begin);
  gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
                   _cogl_path_tesselator_vertex);
  gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
                   _cogl_path_tesselator_end);
  gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
                   _cogl_path_tesselator_combine);

  gluTessBeginPolygon (tess.glu_tess, &tess);

  while (path_start < data->path_nodes->len)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, path_start);

      gluTessBeginContour (tess.glu_tess);

      for (i = 0; i < node->path_size; i++)
        {
          double vertex[3] = { node[i].x, node[i].y, 0.0 };
          gluTessVertex (tess.glu_tess, vertex,
                         GINT_TO_POINTER (i + path_start));
        }

      gluTessEndContour (tess.glu_tess);

      path_start += node->path_size;
    }

  gluTessEndPolygon (tess.glu_tess);

  gluDeleteTess (tess.glu_tess);

  data->fill_attribute_buffer =
    cogl_attribute_buffer_new (data->context,
                               sizeof (CoglPathTesselatorVertex) *
                               tess.vertices->len,
                               tess.vertices->data);
  g_array_free (tess.vertices, TRUE);

  data->fill_attributes[0] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_position_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);
  data->fill_attributes[1] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_tex_coord0_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);

  data->fill_vbo_indices = cogl_indices_new (data->context,
                                             tess.indices_type,
                                             tess.indices->data,
                                             tess.indices->len);
  data->fill_vbo_n_indices = tess.indices->len;
  g_array_free (tess.indices, TRUE);
}
コード例 #27
0
ファイル: bsptree.c プロジェクト: NautiluX/geomview
/* convert a PolyList into a linked list of PolyListNodes, subdivide
 * non-flat or concave polgons
 */
static PolyListNode *
PolyListToLinkedPoyList(Transform T, Transform Tdual, Transform TxT,
			const void **tagged_app,
			PolyListNode **plistp,
			PolyList *pl, struct obstack *scratch)
{
  PolyListNode *plist = NULL;
  int pnr;
  
  if (!plistp) {
    plistp = &plist;
  }

  PolyListComputeNormals(pl, PL_HASVN|PL_HASPN|PL_HASPFL);
  for (pnr = 0; pnr < pl->n_polys; pnr++) {
    PolyListNode *new_pn;
    Poly *poly;

    if (pl->p[pnr].flags & POLY_NOPOLY) {
      /* degenerated, just skip it */
      continue;
    }

    poly = &pl->p[pnr];
    poly->flags |= pl->geomflags;

    if (T && T != TM_IDENTITY) {
      poly = transform_poly(T, Tdual, TxT, poly, scratch);
    }

    switch (pl->p[pnr].n_vertices) {
    case 3: /* ok */
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#if !HAVE_LIBGLU
    case 4: /* supported */
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	/* split this polygon along a diagonal, if the polygon is
	 * concave: split across the unique concave vertex.
	 */
	int concave;

	if (pl->p[pnr].flags & POLY_CONCAVE) {
	  Point3 nu;

	  /* We need to determine the concave vertex */
	  PolyNormal(poly, &nu, pl->geomflags & VERT_4D, false, NULL,
		     &concave);
	} else {
	  concave= 0;
	}
	split_quad_poly(concave, poly, plistp, tagged_app, scratch);
      } else {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
    default:
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	static int was_here;
	
	if (!was_here ) {
	  GeomError(1, "Non-flat or concave polygons not supported yet.\n");
	  was_here = 1;
	}
      }
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#else
    case 4:
      /* if we want to be able to render polygons with
       * self-intersections "correctly", then we always have to use
       * the GLU tesselater for polygons with more than 4 vertices and
       * for non-convex quadrilaterals. We can handle non-flat
       * quadrilaterals ourselves.
       */
      if ((pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) == POLY_NONFLAT) {
	/* Split this polygon along a diagonal. Leave concave
	 * quadrilaterals to the GLU tesselator; they could have
	 * self-intersections.
	 */
	split_quad_poly(0, poly, plistp, tagged_app, scratch);
      } else if ((pl->p[pnr].flags & POLY_CONCAVE) == 0) {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
      /* otherwise fall into the > 4 vertices case and leave
       * everything to the GLU tesselator.
       */
    default: {
      /* We use the GLU tesselator here, if available. It is not
       * necessary to reinvent the wheel; also, the OpenGL MG backend
       * also uses the tesselator (so we will get comparable shapes
       * w/o translucency).
       */
      static GLUtesselator *glutess;
      struct tess_data tessdata[1];
      VARARRAY2(dv, GLdouble, poly->n_vertices, 3);
      Vertex **vp;
      int i;
      
      if (glutess == NULL) {
	glutess = gluNewTess();
	gluTessProperty(glutess,
			GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
	gluTessCallback(glutess, GLU_TESS_BEGIN_DATA,
			(GLvoid (*)())tess_begin_data);
	gluTessCallback(glutess, GLU_TESS_VERTEX_DATA,
			(GLvoid (*)())tess_vertex_data);
	gluTessCallback(glutess, GLU_TESS_COMBINE_DATA,
			(GLvoid (*)())tess_combine_data);
      }

      tessdata->trickyp    = poly;
      tessdata->polyflags  = poly->flags;
      tessdata->pn         = &poly->pn;
      tessdata->scratch    = scratch;
      tessdata->plistp     = plistp;
      tessdata->tagged_app = tagged_app;

      /* tell GLU what we think is a good approximation for the normal */
      gluTessNormal(glutess, poly->pn.x, poly->pn.y, poly->pn.z);

      /* rest is done in the callback functions */
      gluTessBeginPolygon(glutess, tessdata);
      gluTessBeginContour(glutess);
      for (i = 0, vp = poly->v; i < poly->n_vertices; i++, vp++) {
	HPt3Coord w = (*vp)->pt.w ? (*vp)->pt.w : 1e20;

	if (w == 1.0) {
	  dv[i][0] = (*vp)->pt.x;
	  dv[i][1] = (*vp)->pt.y;
	  dv[i][2] = (*vp)->pt.z;
	} else {
	  dv[i][0] = (*vp)->pt.x / w;
	  dv[i][1] = (*vp)->pt.y / w;
	  dv[i][2] = (*vp)->pt.z / w;
	}
	gluTessVertex(glutess, dv[i], *vp);
      }
      gluTessEndContour(glutess);
      gluTessEndPolygon(glutess);
      break; /* out of switch */
    } /* default */
#endif
    } /* switch */
  } /* for */
  return *plistp;
}
コード例 #28
0
ファイル: GeneralPolygon.cpp プロジェクト: 675492062/NavMesh
void GeneralPolygon::render()
{
	//http://www.flipcode.com/archives/Polygon_Tessellation_In_OpenGL.shtml

	glPushMatrix();
	
	glTranslatef(_position.x, _position.y, 0.0f);
	glRotatef(_rotation,0.0f, 0.0f, 1.0f);
	glScalef(_size.x, _size.y, 1.0f);

	glColor4f( _r, _g, _b, _a);

	switch( _renderMode )
	{
		case RenderMethod::GLU_Tessalation:
		{

			// first time rendering? then create the GLUTesselate object
			if( _gluTesselator == NULL )
			{
				// helper lambda function that creates a vertex for OpenGL
				auto combineTesselate = [&](GLdouble coords[3], GLdouble *data[4], GLfloat weight[4], GLdouble **dataOut ) {GLdouble *vert = _newCombineVertexData(coords[0], coords[1]); *dataOut = vert;};
				auto errorTesselate = [] (GLenum errorCode) { std::cerr<< (char *)gluErrorString(errorCode); };

				_gluTesselator = gluNewTess();

				// defines all the callback to render the polygons
				gluTessCallback(_gluTesselator, GLU_TESS_BEGIN, (void (CALLBACK*)()) glBegin );
				gluTessCallback(_gluTesselator, GLU_TESS_VERTEX, (void (CALLBACK*)()) glVertex3dv );
				gluTessCallback(_gluTesselator, GLU_TESS_END, (void (CALLBACK*)()) glEnd );
				gluTessCallback(_gluTesselator, GLU_TESS_COMBINE, (void (CALLBACK*)()) &combineTesselate );
				gluTessCallback(_gluTesselator, GLU_TESS_ERROR, (void (CALLBACK*)()) &errorTesselate );

				// tells to all polygons that the normal is in +z direction
				gluTessNormal(_gluTesselator, 0.0, 0.0, 1.0);
				gluTessProperty(_gluTesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
				gluTessProperty(_gluTesselator, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
			}	
			
			gluTessBeginPolygon(_gluTesselator, NULL); 
			for(unsigned int i = 0; i < _contours.size(); ++i)
			{
				const Contour& contour = _contours[i];
				gluTessBeginContour(_gluTesselator);

				for(unsigned int j = 0; j < contour.size(); ++j)
				{
					GLdouble *vert = _newCombineVertexData((GLdouble)contour[j].x, (GLdouble)contour[j].y);
					gluTessVertex(_gluTesselator, vert, vert); 
				}
				gluTessEndContour(_gluTesselator); 
			}

			// here at the TessEnd is where GLU makes its magic and tesselate our stuff
			gluTessEndPolygon(_gluTesselator);

			_clearCombineVertexData();
		}
		break;
		
		case RenderMethod::ConvexTessalation:
		{
			list<TPPLPoly>::iterator it = _optimalConvexTesselation.begin();

			while( it != _optimalConvexTesselation.end() )
			{
				glBegin(GL_POLYGON);// render convex polygon only

				TPPLPoly &poly = *it;

				for(unsigned int p=0; p < poly.GetNumPoints() ; ++p)
					glVertex3f(poly[p].x, poly[p].y, 0);

				if( poly.GetNumPoints() > 0 )
					glVertex3f(poly[0].x, poly[0].y, 0);
		
				glEnd();

				++it;
			}
		}
		break;

		default:
			std::cerr<<"GeneralPolygon::render -> Render Method set not valid"<<std::endl;
		break;
	}

	glPopMatrix();
}
コード例 #29
0
ファイル: ofGraphics.cpp プロジェクト: LuaAV/LuaAV
//----------------------------------------------------------
void ofBeginShape(){

	if (bSmoothHinted && drawMode == OF_OUTLINE) startSmoothing();

	// just clear the vertices, just to make sure that
	// someone didn't do something improper, like :
	// a) ofBeginShape()
	// b) ofVertex(), ofVertex(), ofVertex() ....
	// c) ofBeginShape()
	// etc...

	clearTessVertices();
	
	
	// now get the tesselator object up and ready: 
	
	tobj = gluNewTess();


	// --------------------------------------------------------
	// note: 	you could write your own begin and end callbacks
	// 			if you wanted to...
	// 			for example, to count triangles or know which
	// 			type of object tess is giving back, etc...
	// --------------------------------------------------------

//	#if defined( TARGET_WIN32) || defined( TARGET_LINUX ) || defined( MAC_OS_X_VERSION_10_5 )
//		gluTessCallback( tobj, GLU_TESS_BEGIN, (void(CALLBACK*)())&glBegin);
//		gluTessCallback( tobj, GLU_TESS_VERTEX, (void(CALLBACK*)())&tessVertex);
//		gluTessCallback( tobj, GLU_TESS_COMBINE, (void(CALLBACK*)())&tessCombine);
//		gluTessCallback( tobj, GLU_TESS_END, (void(CALLBACK*)())&glEnd);
//		gluTessCallback( tobj, GLU_TESS_ERROR, (void(CALLBACK*)())&tessError);
//	#else
//		// xcode / osx complained, so we write it the way that makes it happy:
//		gluTessCallback( tobj, GLU_TESS_BEGIN, (void(CALLBACK*)(...))&glBegin);
//		gluTessCallback( tobj, GLU_TESS_VERTEX, (void(CALLBACK*)(...))&tessVertex);
//		gluTessCallback( tobj, GLU_TESS_COMBINE, (void(CALLBACK*)(...))&tessCombine);
//		gluTessCallback( tobj, GLU_TESS_END, (void(CALLBACK*)(...))&glEnd);
//		gluTessCallback( tobj, GLU_TESS_ERROR, (void(CALLBACK*)(...))&tessError);
//	#endif


	gluTessProperty( tobj, GLU_TESS_WINDING_RULE, polyMode);

	if (drawMode == OF_OUTLINE){
		gluTessProperty( tobj, GLU_TESS_BOUNDARY_ONLY, true);
	} else {
		gluTessProperty( tobj, GLU_TESS_BOUNDARY_ONLY, false);
	}

	gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);

	/* ------------------------------------------
	for 2d, this next call (normal) likely helps speed up ....
	quote : The computation of the normal represents about 10% of
	the computation time. For example, if all polygons lie in
	the x-y plane, you can provide the normal by using the
	-------------------------------------------  */

	gluTessNormal(tobj, 0.0, 0.0, 1.0);
	gluTessBeginPolygon( tobj, NULL);
	
}