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 }
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(); }
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 ); }
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); }
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; }
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(); }
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 }
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])); }
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(); }
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); } }
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); }
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); }
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)); }
//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; }
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 ); }
// 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; }
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); }
//---------------------------------------------------------- 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; }
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; }
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); }
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); }
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; }
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; }
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); } }
/* 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 ); }
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); }
/* 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; }
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(); }
//---------------------------------------------------------- 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); }