void drawColourPoly(const carve::geom3d::Vector &normal, std::vector<std::pair<carve::geom3d::Vector, cRGBA> > &v) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); GLUtesselator *tess = gluNewTess(); gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLUTessCallback)_normalBegin); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLUTessCallback)_colourVertex); gluTessCallback(tess, GLU_TESS_END_DATA, (GLUTessCallback)_normalEnd); gluTessBeginPolygon(tess, (void *)(GLdouble *)normal.v); gluTessBeginContour(tess); for (size_t i = 0, l = v.size(); i != l; ++i) { gluTessVertex(tess, (GLdouble *)v[i].first.v, (GLvoid *)&v[i]); } gluTessEndContour(tess); gluTessEndPolygon(tess); gluDeleteTess(tess); }
void glu_tessbeginpolygon( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { MOGLDEFMYTESS; if (NULL == gluTessBeginPolygon) mogl_glunsupported("gluTessBeginPolygon"); // Setup all tesselator callbacks for this polygon: MOGLSETTESSCALLBACK(GLU_TESS_BEGIN); MOGLSETTESSCALLBACK(GLU_TESS_EDGE_FLAG); MOGLSETTESSCALLBACK(GLU_TESS_VERTEX); MOGLSETTESSCALLBACK(GLU_TESS_END); MOGLSETTESSCALLBACK(GLU_TESS_COMBINE); MOGLSETTESSCALLBACK(GLU_TESS_ERROR); // Store user-provided polygon data pointer internally: mytess->polygondata = mxGetScalar(prhs[1]); // Pass pointer to our own struct as polygondata to the real tesselator: gluTessBeginPolygon((GLUtesselator*) mytess->glutesselator, (GLvoid*) mytess); }
void GLShapeRenderer::renderPolygon(LKSurface& Surface, const XShape& shape, Brush& brush, const ScreenProjection& _Proj) { /* OpenGL cannot draw complex polygons so we need to use a Tessallator to draw the polygon using a GL_TRIANGLE_FAN */ #ifdef USE_GLSL OpenGL::solid_shader->Use(); #endif brush.Bind(); std::unique_ptr<const GLBlend> blend; if(!brush.IsOpaque()) { blend = std::make_unique<const GLBlend>(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } curr_LabelPos = clipRect.GetBottomRight(); const shapeObj& shp = shape.shape; gluTessBeginPolygon(tess, this ); for (int j = 0; j < shp.numlines; j++) { gluTessBeginContour(tess); for (int i = 0; i < shp.line[j].numpoints; i++) { const RasterPoint pt = _Proj.LonLat2Screen(shp.line[j].point[i]); if (!noLabel && (pt.x<=curr_LabelPos.x)) { curr_LabelPos = pt; } vertex_t& vertex = *(pointers.insert(pointers.end(), vertex_t({{(GLdouble)pt.x, (GLdouble)pt.y, 0.}}))); gluTessVertex(tess, vertex.data(), vertex.data()); } gluTessEndContour(tess); } gluTessEndPolygon(tess); if(shape.HasLabel() && clipRect.IsInside(curr_LabelPos)) { shape.renderSpecial(Surface, curr_LabelPos.x, curr_LabelPos.y, clipRect); } pointers.clear(); }
void Opengl2dPainter::drawPolygon(const POINT2F* pPoints, INT count, bool bFill) { /// opengl tesselation if (bFill) gluTessProperty(_pPimpl->pTesslation, GLU_TESS_BOUNDARY_ONLY, false); else gluTessProperty(_pPimpl->pTesslation, GLU_TESS_BOUNDARY_ONLY, true); VERTEX_EDGE v; std::vector<VERTEX_EDGE> vertices; vertices.reserve(count+1); gluTessBeginPolygon(_pPimpl->pTesslation, NULL); gluTessBeginContour(_pPimpl->pTesslation); gluNextContour(_pPimpl->pTesslation, GLU_EXTERIOR); for (int i=0; i< count; ++i) { v.x = pPoints[i].x; v.y = pPoints[i].y; v.z = 0; vertices.push_back(v); gluTessVertex(_pPimpl->pTesslation, (double*)&vertices[i], (void*) &vertices[i]); } v.x = pPoints[0].x; v.y = pPoints[0].y; v.z = 0; vertices.push_back(v); gluTessVertex(_pPimpl->pTesslation, (double*)&vertices[count],(void*) &vertices[count]); gluTessEndContour(_pPimpl->pTesslation); gluTessEndPolygon(_pPimpl->pTesslation); }
static void GotoState( GLUtesselator *tess, enum TessState newState ) { while( tess->state != newState ) { /* We change the current state one level at a time, to get to * the desired state. */ if( tess->state < newState ) { switch( tess->state ) { case T_DORMANT: CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON ); gluTessBeginPolygon( tess, NULL ); break; case T_IN_POLYGON: CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR ); gluTessBeginContour( tess ); break; default: assert(0); break; } } else { switch( tess->state ) { case T_IN_CONTOUR: CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR ); gluTessEndContour( tess ); break; case T_IN_POLYGON: CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON ); /* gluTessEndPolygon( tess ) is too much work! */ MakeDormant( tess ); break; default: assert(0); break; } } } }
void tessellate (double **verts, int *nverts, int **tris, int *ntris, const double **contoursbegin, const double **contoursend) { const double *contourbegin, *contourend; struct Vertex_s *current_vertex; GLUtesselator *tess; struct TessContext_s *ctx; tess = gluNewTess(); ctx = new_tess_context(); gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (*) ()) &vertex); gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (*) ()) &begin); gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid (*) ()) &combine); gluTessBeginPolygon(tess, ctx); do { contourbegin = *contoursbegin++; contourend = *contoursbegin; gluTessBeginContour(tess); while (contourbegin != contourend) { current_vertex = new_vertex(ctx, contourbegin[0], contourbegin[1]); contourbegin += 2; gluTessVertex(tess, current_vertex->pt, current_vertex); } gluTessEndContour(tess); } while (contoursbegin != (contoursend - 1)); gluTessEndPolygon(tess); write_output(ctx, verts, tris, nverts, ntris); destroy_tess_context(ctx); gluDeleteTess(tess); }
//only draws the GL polygon face without normals and colors //dir implyes if it is in inverse or direct order (false==inverse) void Face::drawPrimitive(bool dir) { int num=(int)(vertex.size()); int i; if(convex){ glBegin(GL_POLYGON); if(clockwise==dir){ for(i=0;i<num;i++) glVertex3dv(vertex[i].values); } else{ for(i=num-1;i>=0;i--) glVertex3dv(vertex[i].values); } glEnd(); } else{ GLUtesselator *TESS=gluNewTess(); gluTessCallback(TESS,GLU_BEGIN,MR_TESS glBegin); gluTessCallback(TESS,GLU_VERTEX,MR_TESS glVertex3dv); gluTessCallback(TESS,GLU_END, glEnd); gluTessBeginPolygon(TESS, NULL); gluTessBeginContour(TESS); if(clockwise==dir){ for(i=0;i<num;i++)gluTessVertex(TESS,vertex[i].values,vertex[i].values); } else{ for(i=num-1;i>=0;i--)gluTessVertex(TESS,vertex[i].values,vertex[i].values); } gluTessEndContour(TESS); gluTessEndPolygon(TESS); gluDeleteTess(TESS); } }
// Build PolyTessGeo Object from OGR Polygon // Using OpenGL/GLU tesselator int PolyTessGeo::PolyTessGeoGL(OGRPolygon *poly, bool bSENC_SM, double ref_lat, double ref_lon) { #ifdef ocpnUSE_GL int iir, ip; int *cntr; GLdouble *geoPt; wxString sout; wxString sout1; wxString stemp; // 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; #ifdef __WXMSW__ // If using the OpenGL dlls provided with Windows, // load the dll and establish addresses of the entry points needed #ifdef USE_GLU_DLL if(!s_glu_dll_ready) { s_hGLU_DLL = LoadLibrary("glu32.dll"); if (s_hGLU_DLL != NULL) { s_lpfnTessProperty = (LPFNDLLTESSPROPERTY)GetProcAddress(s_hGLU_DLL,"gluTessProperty"); s_lpfnNewTess = (LPFNDLLNEWTESS)GetProcAddress(s_hGLU_DLL, "gluNewTess"); s_lpfnTessBeginContour = (LPFNDLLTESSBEGINCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessBeginContour"); s_lpfnTessEndContour = (LPFNDLLTESSENDCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessEndContour"); s_lpfnTessBeginPolygon = (LPFNDLLTESSBEGINPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessBeginPolygon"); s_lpfnTessEndPolygon = (LPFNDLLTESSENDPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessEndPolygon"); s_lpfnDeleteTess = (LPFNDLLDELETETESS)GetProcAddress(s_hGLU_DLL, "gluDeleteTess"); s_lpfnTessVertex = (LPFNDLLTESSVERTEX)GetProcAddress(s_hGLU_DLL, "gluTessVertex"); s_lpfnTessCallback = (LPFNDLLTESSCALLBACK)GetProcAddress(s_hGLU_DLL, "gluTessCallback"); s_glu_dll_ready = true; } else { return ERROR_NO_DLL; } } #endif #endif // Allocate a work buffer, which will be grown as needed #define NINIT_BUFFER_LEN 10000 s_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble)); s_buf_len = NINIT_BUFFER_LEN * 2; s_buf_idx = 0; // Create an array to hold pointers to allocated vertices created by "combine" callback, // so that they may be deleted after tesselation. s_pCombineVertexArray = new wxArrayPtrVoid; // Create tesselator GLUtessobj = gluNewTess(); // Register the callbacks gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (GLvoid (__CALL_CONVENTION *) ())&beginCallback); gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (GLvoid (__CALL_CONVENTION *) ())&beginCallback); gluTessCallback(GLUtessobj, GLU_TESS_VERTEX, (GLvoid (__CALL_CONVENTION *) ())&vertexCallback); gluTessCallback(GLUtessobj, GLU_TESS_END, (GLvoid (__CALL_CONVENTION *) ())&endCallback); gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (GLvoid (__CALL_CONVENTION *) ())&combineCallback); // gluTessCallback(GLUtessobj, GLU_TESS_ERROR, (GLvoid (__CALL_CONVENTION *) ())&errorCallback); // glShadeModel(GL_SMOOTH); gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); // gluTess algorithm internally selects vertically oriented triangle strips and fans. // This orientation is not optimal for conventional memory-mapped raster display shape filling. // We can "fool" the algorithm by interchanging the x and y vertex values passed to gluTessVertex // and then reverting x and y on the resulting vertexCallbacks. // In this implementation, we will explicitely set the preferred orientation. //Set the preferred orientation tess_orient = TESS_HORZ; // prefer horizontal tristrips // PolyGeo BBox as lat/lon OGREnvelope Envelope; poly->getEnvelope(&Envelope); xmin = Envelope.MinX; ymin = Envelope.MinY; xmax = Envelope.MaxX; ymax = Envelope.MaxY; // Get total number of contours m_ncnt = 1; // always exterior ring int nint = poly->getNumInteriorRings(); // interior rings m_ncnt += nint; // Allocate cntr array cntr = (int *)malloc(m_ncnt * sizeof(int)); // Get total number of points(vertices) int npta = poly->getExteriorRing()->getNumPoints(); cntr[0] = npta; npta += 2; // fluff for( iir=0 ; iir < nint ; iir++) { int nptr = poly->getInteriorRing(iir)->getNumPoints(); cntr[iir+1] = nptr; npta += nptr + 2; } // printf("pPoly npta: %d\n", npta); geoPt = (GLdouble *)malloc((npta) * 3 * sizeof(GLdouble)); // vertex array // Grow the work buffer if necessary if((npta * 4) > s_buf_len) { s_pwork_buf = (GLdouble *)realloc(s_pwork_buf, npta * 4 * sizeof(GLdouble)); s_buf_len = npta * 4; } // Define the polygon gluTessBeginPolygon(GLUtessobj, NULL); // Create input structures // Exterior Ring int npte = poly->getExteriorRing()->getNumPoints(); cntr[0] = npte; GLdouble *ppt = geoPt; // Check and account for winding direction of ring bool cw = !(poly->getExteriorRing()->isClockwise() == 0); double x0, y0, x, y; OGRPoint p; if(cw) { poly->getExteriorRing()->getPoint(0, &p); x0 = p.getX(); y0 = p.getY(); } else { poly->getExteriorRing()->getPoint(npte-1, &p); x0 = p.getX(); y0 = p.getY(); } // Transcribe contour to an array of doubles, with duplicates eliminated double *DPbuffer = (double *)malloc(npte * 2 * sizeof(double)); double *DPrun = DPbuffer; int nPoints = npte; for(ip = 0 ; ip < npte ; ip++) { int pidx; if(cw) pidx = npte - ip - 1; else pidx = ip; poly->getExteriorRing()->getPoint(pidx, &p); x = p.getX(); y = p.getY(); if( ((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))) { GLdouble *ppt_temp = ppt; if(tess_orient == TESS_VERT) { *DPrun++ = x; *DPrun++ = y; } else { *DPrun++ = y; *DPrun++ = x; } x0 = x; y0 = y; } else nPoints--; } if(nPoints > 5 && (m_LOD_meters > .01)){ index_keep.Clear(); index_keep.Add(0); index_keep.Add(nPoints-1); index_keep.Add(1); index_keep.Add(nPoints-2); DouglasPeucker(DPbuffer, 1, nPoints-2, m_LOD_meters/(1852 * 60), &index_keep); // printf("DP Reduction: %d/%d\n", index_keep.GetCount(), nPoints); g_keep += index_keep.GetCount(); g_orig += nPoints; // printf("...................Running: %g\n", (double)g_keep/g_orig); } else { index_keep.Clear(); for(int i = 0 ; i < nPoints ; i++) index_keep.Add(i); } cntr[0] = index_keep.GetCount(); // Mark the keepers by adding a simple constant to X for(unsigned int i=0 ; i < index_keep.GetCount() ; i++){ int k = index_keep.Item(i); DPbuffer[2*k] += 2000.; } // Declare the gluContour and copy the points gluTessBeginContour(GLUtessobj); DPrun = DPbuffer; for(ip = 0 ; ip < nPoints ; ip++) { x = *DPrun++; y = *DPrun++; if(x > 1000.){ GLdouble *ppt_top = ppt; *ppt++ = x-2000; *ppt++ = y; *ppt++ = 0; gluTessVertex( GLUtessobj, ppt_top, ppt_top ) ; } } gluTessEndContour(GLUtessobj); free(DPbuffer); // Now the interior contours for(iir=0 ; iir < nint ; iir++) { gluTessBeginContour(GLUtessobj); int npti = poly->getInteriorRing(iir)->getNumPoints(); // Check and account for winding direction of ring bool cw = !(poly->getInteriorRing(iir)->isClockwise() == 0); if(!cw) { poly->getInteriorRing(iir)->getPoint(0, &p); x0 = p.getX(); y0 = p.getY(); } else { poly->getInteriorRing(iir)->getPoint(npti-1, &p); x0 = p.getX(); y0 = p.getY(); } // Transcribe points to vertex array, in proper order with no duplicates // also, accounting for tess_orient for(int ip = 0 ; ip < npti ; ip++) { OGRPoint p; int pidx; if(!cw) // interior contours must be cw pidx = npti - ip - 1; else pidx = ip; poly->getInteriorRing(iir)->getPoint(pidx, &p); x = p.getX(); y = p.getY(); if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS)) { GLdouble *ppt_temp = ppt; if(tess_orient == TESS_VERT) { *ppt++ = x; *ppt++ = y; } else { *ppt++ = y; *ppt++ = x; } *ppt++ = 0.0; gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ; // printf("tess from Poly, internal vertex %d %g %g\n", ip, x, y); } else cntr[iir+1]--; x0 = x; y0 = y; } gluTessEndContour(GLUtessobj); } // Store some SM conversion data in static store, // for callback access s_ref_lat = ref_lat; s_ref_lon = ref_lon; s_bSENC_SM = bSENC_SM; s_bmerc_transform = false; // Ready to kick off the tesselator s_pTPG_Last = NULL; s_pTPG_Head = NULL; s_nvmax = 0; gluTessEndPolygon(GLUtessobj); // here it goes m_nvertex_max = s_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 = s_bSENC_SM; m_ppg_head->nContours = m_ncnt; m_ppg_head->pn_vertex = 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 int nptfinal = 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 == tess_orient) { ty = *ppt++; tx = *ppt++; } else { tx = *ppt++; ty = *ppt++; } if(bSENC_SM) { // Calculate SM from chart common reference point double easting, northing; toSM(ty, tx, ref_lat, 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 = s_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( s_pwork_buf ); s_pwork_buf = NULL; free (geoPt); // Free up any "Combine" vertices created for(unsigned int i = 0; i < s_pCombineVertexArray->GetCount() ; i++) free (s_pCombineVertexArray->Item(i)); delete s_pCombineVertexArray; m_bOK = true; #endif // #ifdef ocpnUSE_GL return 0; }
// 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; }
void CMFCTessView::OnDraw(CDC* pDC) { CMFCTessDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here //some per-drawing init stuff glLoadIdentity(); //setup drawing dimensions, etc CPoint vptorg = m_pDC->GetViewportOrg() ; //note m_pDC, NOT pDC CRect rect ; GetWindowRect( &rect ) ; int dx = rect.Width() ; int dy = rect.Height() ; glViewport( 0, 0, dx, dy ); glMatrixMode( GL_MODELVIEW ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // create bitmaps for the device context font's first 256 glyphs HDC hdc = m_pDC->GetSafeHdc() ; wglUseFontBitmaps(hdc, 0, 256, 1000); glListBase(1000); float R ; if( pDoc->m_ContourList.GetCount() > 0 ) { CalculateExtents() ; // Collect overall figure extents (in meters) R = Radius ; //11/29/03 experiment to eliminate probs w/non-square windows float glleft = -R ; float gltop = +R ; float nearplane = -R ; //rev 07/25/03 float farplane = R ; //rev 07/25/03 float glleft2 = glleft ; float gltop2 = gltop ; float glright2 = ( glleft + 2*R ) ; float glbottom2 = ( gltop - 2*R ) ; //adjust for non-square viewing window float dxdy = (float)dx/(float)dy ; //=1.00 for square window if( dxdy > 1 ) { glOrtho( glleft2*dxdy , glright2*dxdy, glbottom2, gltop2, nearplane, farplane ) ; } else { glOrtho( glleft2 , glright2, glbottom2/dxdy, gltop2/dxdy, nearplane, farplane ) ; } glTranslatef( -m_Center.x, -m_Center.y, -m_Center.z ) ; } else { CString txtstr ; glOrtho( -1.f , 1.f, -1.f, 1.f, -1.f, 1.f ) ; glTranslatef( 0.f, 0.f, 0.f ) ; txtstr = "Nothing to draw" ; glColor3f( 0.f, 0.f, 0.f ) ; glRasterPos3f(0.0F, 0.0F, 0.0F ); glCallLists(txtstr.GetLength(), GL_UNSIGNED_BYTE, txtstr); //clean up & exit glFlush(); glDeleteLists(1000, 256) ; SwapBuffers( m_pDC->GetSafeHdc() ); return ; } glPushMatrix() ; //01/09/05 implement tessellation GLUtesselator *tobj; tobj = gluNewTess(); //added 02/09/05 as part of mem leak fix while( gm_VertexPtrList.GetCount() > 0 ) { GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ; delete[] pV ; pV = NULL ; } gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *) ())beginCallback); gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *) ()) vertexCallback); gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *) ())endCallback); gluTessCallback(tobj, GLU_TESS_ERROR,(void (CALLBACK *) ())errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *) ())combineCallback); glShadeModel(GL_SMOOTH); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, m_WindingRule ); //only one polygon, but multiple contours gluTessBeginPolygon(tobj, NULL); POSITION pos = pDoc->m_ContourList.GetHeadPosition() ; while ( pos ) { CContour* pCtr = (CContour*)pDoc->m_ContourList.GetNext( pos ) ; ASSERT( pCtr != NULL && pCtr->m_NumVertex > 0 && pCtr->m_ppVertexArray != NULL ) ; int numcorners = pCtr->m_NumVertex ; gluTessBeginContour(tobj); for( int cnridx = 0; cnridx < numcorners; cnridx++ ) { GLdouble* glvert = pCtr->m_ppVertexArray[cnridx]; gluTessVertex( tobj, glvert, glvert ) ; TRACE( "Draw: Sent vertex(%f,%f,%f,%f,%f,%f)\n", glvert[0],glvert[1],glvert[2],glvert[3],glvert[4],glvert[5] ) ; } gluTessEndContour(tobj); } //end of all contour definitions gluTessEndPolygon(tobj); //clean up & exit glFlush(); glDeleteLists(1000, 256) ; // delete our 256 glyph display lists SwapBuffers( m_pDC->GetSafeHdc() ); gluDeleteTess( tobj ) ; //added 02/09/05 as part of mem leak fix while( gm_VertexPtrList.GetCount() > 0 ) { GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ; delete[] pV ; pV = NULL ; } }
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); }
void SeedGLWidget::selectRegion() { /*if (_seedRegions.empty()) { return; }*/ glViewport (0, 0, 1024, 1024); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fboId); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glClearColor (0.0f, 0.0f, 0.0f, 0.0f); glClear (GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, _widgetWidth-_planeWidth, _widgetHeight, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(1, 1, 1); gluTessBeginPolygon(tessObj, NULL); gluTessBeginContour(tessObj); for (int i=0; i<_penTrack.size(); ++i) { gluTessVertex(tessObj, _penTrack[i], _penTrack[i]); } gluTessEndContour(tessObj); gluTessEndPolygon(tessObj); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); GLubyte * tempBuffer = new GLubyte [1024*1024]; glBindTexture(GL_TEXTURE_2D, _texId); glGetTexImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, tempBuffer); GLdouble modelMatrix[16]; GLdouble projMatrix[16]; int viewport[4]; int viewportWidth = _viewportHeight*(_widgetWidth-_planeWidth)*1.0/_widgetHeight; glViewport (0, 0, 1024, 1024); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, viewportWidth, 0, _viewportHeight, -2000, 2000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(_translateX, _translateY, 0); glTranslatef(viewportWidth/2.0, _viewportHeight/2.0, 0); setRotationMatrix(); _volumeData->setTransformMatrix(); glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); int minX = floor(_minDrawX*1023.0/(_widgetWidth-_planeWidth-1)); int maxX = ceil(_maxDrawX*1023.0/(_widgetWidth-_planeWidth-1)); int minY = floor((_widgetHeight-_maxDrawY)*1023.0/(_widgetHeight-1)); int maxY = ceil((_widgetHeight-_minDrawY)*1023.0/(_widgetHeight-1)); for (int i=minX; i<=maxX; ++i) { for (int j=minY; j<maxY; ++j) { if (tempBuffer[j*1024+i]>0) { double x, y, z; gluUnProject(i, j, 0, modelMatrix, projMatrix, viewport, &x, &y, &z); //add to seed region list switch (_viewpoint) { case 1: //AXIAL z = _seedData->_aSliceIdx; break; case 2: //CORONAL y = _seedData->_cSliceIdx; break; case 3: //SAGITTAL x = _seedData->_pSliceIdx; break; } if (_bAddRegion) { _seedData->addSeedPoint(x,y,z, _currentSeedIndex); } else { _seedData->removeSeedPoint(x,y,z,_currentSeedIndex); } } } } delete tempBuffer; _seedData->setASlice(_aSlicePos); _seedData->setPSlice(_pSlicePos); _seedData->setCSlice(_cSlicePos); }
// tesselates the contours in preparation for a 3D output; // returns true if all was fine, false otherwise bool VRML_LAYER::Tesselate( VRML_LAYER* holes, bool aHolesOnly ) { if( !tess ) { error = "Tesselate(): GLU tesselator was not initialized"; return false; } pholes = holes; Fault = false; if( aHolesOnly ) gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NEGATIVE ); else gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); if( contours.size() < 1 || vertices.size() < 3 ) { error = "Tesselate(): not enough vertices"; return false; } // finish the winding calculation on all vertices prior to setting 'fix' if( !fix ) { for( unsigned int i = 0; i < contours.size(); ++i ) { if( contours[i]->size() < 3 ) continue; VERTEX_3D* vp0 = vertices[ contours[i]->back() ]; VERTEX_3D* vp1 = vertices[ contours[i]->front() ]; areas[i] += ( vp1->x - vp0->x ) * ( vp1->y + vp0->y ); } } // prevent the addition of any further contours and contour vertices fix = true; // clear temporary internals which may have been used in a previous run clearTmp(); // request an outline gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE ); // adjust internal indices for extra points and holes if( holes ) hidx = holes->GetSize(); else hidx = 0; eidx = idx + hidx; if( aHolesOnly && ( checkNContours( true ) == 0 ) ) { error = "tesselate(): no hole contours"; return false; } else if( !aHolesOnly && ( checkNContours( false ) == 0 ) ) { error = "tesselate(): no solid contours"; return false; } // open the polygon gluTessBeginPolygon( tess, this ); if( aHolesOnly ) { pholes = NULL; // do not accept foreign holes hidx = 0; eidx = idx; // add holes pushVertices( true ); gluTessEndPolygon( tess ); if( Fault ) return false; return true; } // add solid outlines pushVertices( false ); // close the polygon gluTessEndPolygon( tess ); if( Fault ) return false; // if there are no outlines we cannot proceed if( outline.empty() ) { error = "tesselate(): no points in result"; return false; } // at this point we have a solid outline; add it to the tesselator gluTessBeginPolygon( tess, this ); if( !pushOutline( NULL ) ) return false; // add the holes contained by this object pushVertices( true ); // import external holes (if any) if( hidx && ( holes->Import( idx, tess ) < 0 ) ) { std::ostringstream ostr; ostr << "Tesselate():FAILED: " << holes->GetError(); error = ostr.str(); return false; } if( Fault ) return false; // erase the previous outline data and vertex order // but preserve the extra vertices while( !outline.empty() ) { delete outline.back(); outline.pop_back(); } ordmap.clear(); ord = 0; // go through the vertex lists and reset ephemeral parameters for( unsigned int i = 0; i < vertices.size(); ++i ) { vertices[i]->o = -1; } for( unsigned int i = 0; i < extra_verts.size(); ++i ) { extra_verts[i]->o = -1; } // close the polygon; this creates the outline points // and the point ordering list 'ordmap' solid.clear(); gluTessEndPolygon( tess ); // repeat the last operation but request a tesselated surface // rather than an outline; this creates the triangles list. gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE ); gluTessBeginPolygon( tess, this ); if( !pushOutline( holes ) ) return false; gluTessEndPolygon( tess ); if( Fault ) return false; return true; }
void MapDrawFunction(AG_Event *event) { GLdouble vz = -2.0; GLfloat ambient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat diffuse[4] = { 1.f, 1.0f, 1.0f, 1.0f }; GLfloat specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; int wireframe = 0; enum { FLATSHADING, SMOOTHSHADING } shading = FLATSHADING; int i; GLfloat pos[4]; glLoadIdentity(); glPushAttrib(GL_POLYGON_BIT|GL_LIGHTING_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_POINT_SMOOTH); glEnable(GL_DEPTH_TEST); //glEnable(GL_LIGHTING); //glEnable(GL_LIGHT0); // Create light components //GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 0.1f }; GLfloat diffuseLight[] = { 1, 1, 1, 1.0f }; GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f }; GLfloat position[] = { cursorwX, cursorwY, 0.5f, 1.0f }; // Assign created components to GL_LIGHT0 //glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.002f); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); glClearColor(0.0f,0.0f,0.0f,1.0f); glPushMatrix(); glTranslated(0.0, 0.0, vz); GLfloat visi[4]={1.0,0.0,0.0,1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, visi); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, visi); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, visi); glColor3f(0.9,0.9,0.6); mapdraw(); for (int i=0;i<sceneVertices.size();i++){ glBegin(GL_LINE_LOOP); for (int j=0;j<sceneVertices[i].size();j++){ glVertex3f( sceneVertices[i][j][0], sceneVertices[i][j][1], 0.0f); }; glEnd(); }; glColor3f(0.9,0.9,0.0); for (int i=0;i<mapEnvCollision.h()+1;i++){ glBegin(GL_LINE_LOOP); for (int j=0;j<mapEnvCollision[i].n();j++){ glVertex3f( mapEnvCollision[i][j].x(), mapEnvCollision[i][j].y(), 0.0f); }; //glVertex3f( sceneVertices[i][0].x(), sceneVertices[i][0].y(), 0.0f); glEnd(); }; gluTessBeginPolygon (tess, NULL); gluTessBeginContour (tess); GLdouble data[visiBounded.outer_boundary().size()][3]; CGAL::Polygon_2<Kernel>::Vertex_iterator vit; i=0; for (vit=visiBounded.outer_boundary().vertices_begin();vit!=visiBounded.outer_boundary().vertices_end();++vit) { data[i][0]=vit->x(); data[i][1]=vit->y(); data[i][2]=0; gluTessVertex (tess, data[i], data[i]); i++; } /* for (i=0; i<visiPoly.n();i++) { data[i][0]=visiPoly[i].x(); data[i][1]=visiPoly[i].y(); data[i][2]=0; gluTessVertex (tess, data[i], data[i]); } */ gluTessEndContour (tess); gluEndPolygon (tess); glBegin(GL_LINE_LOOP); for (int i=0;i<visiPoly.n();i++){ glVertex3f(visiPoly[i].x(),visiPoly[i].y(),0.0f); } glEnd(); glColor3f(1.0,0.0,0.0); glBegin(GL_LINE_STRIP); for (int i=0;i<motionPath.size();i++){ glVertex3f(motionPath[i].x(),motionPath[i].y(),0.1f); } glEnd(); //glPopMatrix(); GLfloat marker[4]={1.0,0.0,0.0,1.0}; //glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, marker); glColor3f(1.0,0.0,0.0); guest1.Draw(); glGetDoublev(GL_MODELVIEW_MATRIX,modelview); glGetDoublev(GL_PROJECTION_MATRIX,projection); glGetIntegerv(GL_VIEWPORT,viewport) ; glColor3f(1.0,1.0,1.0); glBegin(GL_TRIANGLES); glVertex3f(cursorwX,cursorwY+1/sqrt(2)*10,1.0f); glVertex3f(cursorwX-1/sqrt(2)*10,cursorwY-1/sqrt(2)*10,1.0f); glVertex3f(cursorwX+1/sqrt(2)*10,cursorwY-1/sqrt(2)*10,1.0f); glEnd(); glPopMatrix(); glPopAttrib(); };
void ProtoTessellator::beginPolygon() { //tessellatedPrims = tessPrims; gluTessBeginPolygon(tesselator, NULL); }
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); }
void XMGPolygon::SetCoordArray ( const XMGVector2X* src_arr_coord, XMGTexUnit unit, GLuint src_idx_shape, GLuint src_idx_facet ) { XMGPolygonImpl* impl = (XMGPolygonImpl *) m_impl; XMGRenderImpl* impl_parent = (XMGRenderImpl *) XMGRender::m_impl; XMGTess* data; XMGShape* shape; XMGFacet* facet; GLuint idx_tess; GLuint idx_shape; GLuint idx_facet; GLuint idx_vertex; GLuint num_shape; GLuint num_facet; GLuint num_vertex; GLuint off_src; XMGVector2F* farr_coord; XMGVector2X* xarr_coord; XMGRender::SetCoordArray ( src_arr_coord, unit, src_idx_shape, src_idx_facet ); if ( impl_parent->m_has_face[ 0 ] == XMG_FALSE && impl_parent->m_has_face[ 1 ] ) { return; } if ( src_idx_facet != XMG_FACET_ALL ) { shape = impl_parent->m_vec_shape[ src_idx_facet ]; facet = shape->m_vec_facet[ src_idx_facet ]; if ( facet->m_vec_contour.size ( ) == 0 ) { return; } } off_src = 0; for ( impl_parent->RangeArray ( src_idx_shape, impl_parent->m_vec_shape.size ( ), idx_shape, num_shape ); idx_shape < num_shape; idx_shape++ ) { shape = impl_parent->m_vec_shape[ idx_shape ]; for ( impl_parent->RangeArray ( src_idx_facet, shape->m_vec_facet.size ( ), idx_facet, num_facet ); idx_facet < num_facet; idx_facet++ ) { facet = shape->m_vec_facet[ idx_facet ]; if ( idx_facet < 2 ) { switch ( impl_parent->m_geo_type ) { case XMG_GEO_CONE : case XMG_GEO_CWALL : idx_tess = 1; break; default : idx_tess = idx_facet; break; } if ( impl->m_tess[ idx_tess ] ) { data = impl->m_data[ idx_tess ][ idx_shape ]; data->Init ( XMG_TESS_COORD ); gluTessBeginPolygon ( impl->m_tess[ idx_tess ], (GLvoid *) data ); gluTessBeginContour ( impl->m_tess[ idx_tess ] ); for ( idx_vertex = 0, num_vertex = shape->m_num_basic; idx_vertex < num_vertex; idx_vertex++ ) { data->m_arr_vertex[ idx_vertex * 8 + 6 ] = XMG_X2F ( src_arr_coord[ off_src + idx_vertex ].m_x ); data->m_arr_vertex[ idx_vertex * 8 + 7 ] = XMG_X2F ( src_arr_coord[ off_src + idx_vertex ].m_y ); if ( shape->m_idx_hole != 0 && shape->m_idx_hole == idx_vertex ) { gluNextContour ( impl->m_tess[ idx_tess ], GLU_INTERIOR ); } gluTessVertex ( impl->m_tess[ idx_tess ], &data->m_arr_vertex[ idx_vertex * 8 ], &data->m_arr_vertex[ idx_vertex * 8 ] ); } gluTessEndContour ( impl->m_tess[ idx_tess ] ); gluTessEndPolygon ( impl->m_tess[ idx_tess ] ); if ( impl_parent->m_type_coords[ unit ] == XMG_TYPE_FLOAT ) { XMGAssert ( farr_coord = (XMGVector2F *) kdMalloc ( sizeof ( XMGVector2F ) * facet->m_num_ext ) ); for ( idx_vertex = 0, num_vertex = facet->m_num_ext; idx_vertex < num_vertex; idx_vertex++ ) { farr_coord[ idx_vertex ] = data->m_vec_coord[ idx_vertex ]; } impl_parent->SetBuffer ( impl_parent->m_id_coords[ unit ], farr_coord, sizeof ( XMGVector2F ) * facet->m_off_ext, sizeof ( XMGVector2F ) * facet->m_num_ext ); kdFree ( farr_coord ); } else { XMGAssert ( xarr_coord = (XMGVector2X *) kdMalloc ( sizeof ( XMGVector2X ) * facet->m_num_ext ) ); for ( idx_vertex = 0, num_vertex = facet->m_num_ext; idx_vertex < num_vertex; idx_vertex++ ) { xarr_coord[ idx_vertex ] = data->m_vec_coord[ idx_vertex ]; } impl_parent->SetBuffer ( impl_parent->m_id_coords[ unit ], xarr_coord, sizeof ( XMGVector2X ) * facet->m_off_ext, sizeof ( XMGVector2X ) * facet->m_num_ext ); kdFree ( xarr_coord ); } } } off_src += facet->m_num_vertex; } } }
void XMGPolygon::SetVertexArray ( const XMGVector3X* src_arr_vertex, const GLuint* arr_idx_hole ) { XMGPolygonImpl* impl = (XMGPolygonImpl *) m_impl; XMGRenderImpl* impl_parent = (XMGRenderImpl *) XMGRender::m_impl; XMGTess* data[2]; XMGShape* shape; XMGFacet* facet; XMGContour* contour; GLuint idx_tess; GLuint idx_shape; GLuint idx_facet; GLuint idx_vertex; GLuint idx_vec; GLuint num_shape; GLuint num_vertex; GLuint num_vec; GLuint off_vertex; GLuint off_ext; XMGVector3X src_vertex; XMGVector3X* arr_vertex; off_vertex = 0; off_ext = impl_parent->m_num_vertex; impl_parent->m_ext_vertex = 0; for ( idx_shape = 0, num_shape = impl_parent->m_vec_shape.size ( ); idx_shape < num_shape; idx_shape++ ) { shape = impl_parent->m_vec_shape[ idx_shape ]; shape->m_idx_hole = arr_idx_hole ? arr_idx_hole[ idx_shape ] : XMG_HOLE_NULL; // Set tess vertices if ( impl->m_tess[ 0 ] || impl->m_tess[ 1 ] ) { for ( idx_tess = 0; idx_tess < 2; idx_tess++ ) { if ( impl->m_tess[ idx_tess ] ) { data[ idx_tess ] = impl->m_data[ idx_tess ][ idx_shape ]; data[ idx_tess ]->Init ( XMG_TESS_VERTEX ); gluTessBeginPolygon ( impl->m_tess[ idx_tess ], (GLvoid *) data[ idx_tess ] ); gluTessBeginContour ( impl->m_tess[ idx_tess ] ); } } for ( idx_vertex = 0, num_vertex = shape->m_num_basic; idx_vertex < num_vertex; idx_vertex++ ) { for ( idx_tess = 0; idx_tess < 2; idx_tess++ ) { if ( idx_tess == 0 ) { if ( impl->m_tess[ idx_tess ] ) { src_vertex = src_arr_vertex[ off_vertex + idx_vertex ]; } else { continue; } } else if ( idx_tess == 1 ) { if ( impl->m_tess[ idx_tess ] ) { switch ( impl_parent->m_geo_type ) { case XMG_GEO_SOLID : src_vertex = src_arr_vertex[ off_vertex + num_vertex + idx_vertex ]; break; case XMG_GEO_BSOLID : if ( shape->m_idx_hole ) { src_vertex = src_arr_vertex[ idx_vertex < shape->m_idx_hole ? shape->m_idx_hole - idx_vertex - 1 : num_vertex + shape->m_idx_hole - idx_vertex - 1 ]; } else { src_vertex = src_arr_vertex[ num_vertex - idx_vertex - 1 ]; } src_vertex.m_z = 0; break; } } else { continue; } } data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 0 ] = XMG_X2F ( src_vertex.m_x ); data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 1 ] = XMG_X2F ( src_vertex.m_y ); data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 2 ] = XMG_X2F ( src_vertex.m_z ); if ( shape->m_idx_hole != 0 && shape->m_idx_hole == idx_vertex ) { gluNextContour ( impl->m_tess[ idx_tess ], GLU_INTERIOR ); } gluTessVertex ( impl->m_tess[ idx_tess ], &data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 ], &data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 ] ); } } idx_facet = 0; for ( idx_tess = 0; idx_tess < 2; idx_tess++ ) { if ( impl->m_tess[ idx_tess ] ) { gluTessEndContour ( impl->m_tess[ idx_tess ] ); gluTessEndPolygon ( impl->m_tess[ idx_tess ] ); // Set contours with original facet = shape->m_vec_facet[ idx_facet ]; facet->ClearContour ( ); if ( shape->m_idx_hole == XMG_HOLE_NULL ) { XMGAssert ( contour = new XMGContour ( ) ); contour->m_draw_limit = XMG_LIMIT_LINE; contour->m_off_vertex = facet->m_off_vertex; contour->m_num_vertex = facet->m_num_vertex; facet->m_vec_contour.push_back ( contour ); } else { XMGAssert ( contour = new XMGContour ( ) ); contour->m_draw_limit = XMG_LIMIT_LINE; contour->m_off_vertex = facet->m_off_vertex; contour->m_num_vertex = shape->m_idx_hole; facet->m_vec_contour.push_back ( contour ); XMGAssert ( contour = new XMGContour ( ) ); contour->m_draw_limit = XMG_LIMIT_LINE; contour->m_off_vertex = facet->m_off_vertex + shape->m_idx_hole; contour->m_num_vertex = facet->m_num_vertex - shape->m_idx_hole; facet->m_vec_contour.push_back ( contour ); } // Set contours with tessed facet->m_off_ext = off_ext; for ( idx_vec = 0, num_vec = data[ idx_tess ]->m_vec_num_vertex.size ( ); idx_vec < num_vec; idx_vec++ ) { XMGAssert ( contour = new XMGContour ( ) ); contour->m_draw_limit = XMG_LIMIT_TRI; contour->m_disp_mode = data[ idx_tess ]->m_vec_mode[ idx_vec ]; contour->m_off_vertex = off_ext; contour->m_num_vertex = data[ idx_tess ]->m_vec_num_vertex[ idx_vec ]; facet->m_vec_contour.push_back ( contour ); off_ext += contour->m_num_vertex; } idx_facet++; facet->m_num_ext = data[ idx_tess ]->m_vec_vertex.size ( ); impl_parent->m_ext_vertex += facet->m_num_ext; } } } off_vertex += shape->m_num_input; } XMGRender::SetVertexArray ( src_arr_vertex, XMG_SHAPE_ALL ); if ( impl->m_tess[ 0 ] || impl->m_tess[ 1 ] ) { off_vertex = 0; num_vertex = impl_parent->m_ext_vertex; XMGAssert ( arr_vertex = (XMGVector3X *) kdMalloc ( sizeof ( XMGVector3X ) * num_vertex ) ); for ( idx_shape = 0, num_shape = impl_parent->m_vec_shape.size ( ); idx_shape < num_shape; idx_shape++ ) { for ( idx_tess = 0; idx_tess < 2; idx_tess++ ) { if ( impl->m_tess[ idx_tess ] ) { data[ idx_tess ] = impl->m_data[ idx_tess ][ idx_shape ]; for ( idx_vertex = 0, num_vertex = data[ idx_tess ]->m_vec_vertex.size ( ); idx_vertex < num_vertex; idx_vertex++ ) { arr_vertex[ off_vertex ] = data[ idx_tess ]->m_vec_vertex[ idx_vertex ]; off_vertex++; } data[ idx_tess ]->ClearVector ( ); } } } impl_parent->SetBuffer ( impl_parent->m_id_vertex, arr_vertex, sizeof ( XMGVector3X ) * impl_parent->m_num_vertex, sizeof ( XMGVector3X ) * impl_parent->m_ext_vertex ); kdFree ( arr_vertex ); } }
void init (void) { GLUtesselator *tobj; GLdouble rect[4][3] = {50.0, 50.0, 0.0, 200.0, 50.0, 0.0, 200.0, 200.0, 0.0, 50.0, 200.0, 0.0}; GLdouble tri[3][3] = {75.0, 75.0, 0.0, 125.0, 175.0, 0.0, 175.0, 75.0, 0.0}; GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0, 325.0, 200.0, 0.0, 1.0, 1.0, 0.0, 400.0, 50.0, 0.0, 0.0, 1.0, 1.0, 250.0, 150.0, 0.0, 1.0, 0.0, 0.0, 400.0, 150.0, 0.0, 0.0, 1.0, 0.0}; glClearColor(0.0, 0.0, 0.0, 0.0); startList = glGenLists(2); tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3dv); gluTessCallback(tobj, GLU_TESS_BEGIN, beginCallback); gluTessCallback(tobj, GLU_TESS_END, endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, errorCallback); /* rectangle with triangular hole inside */ glNewList(startList, GL_COMPILE); glShadeModel(GL_FLAT); gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); gluTessVertex(tobj, rect[0], rect[0]); gluTessVertex(tobj, rect[1], rect[1]); gluTessVertex(tobj, rect[2], rect[2]); gluTessVertex(tobj, rect[3], rect[3]); gluTessEndContour(tobj); gluTessBeginContour(tobj); gluTessVertex(tobj, tri[0], tri[0]); gluTessVertex(tobj, tri[1], tri[1]); gluTessVertex(tobj, tri[2], tri[2]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); glEndList(); gluTessCallback(tobj, GLU_TESS_VERTEX, vertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN, beginCallback); gluTessCallback(tobj, GLU_TESS_END, endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, combineCallback); /* smooth shaded, self-intersecting star */ glNewList(startList + 1, GL_COMPILE); glShadeModel(GL_SMOOTH); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); gluTessVertex(tobj, star[0], star[0]); gluTessVertex(tobj, star[1], star[1]); gluTessVertex(tobj, star[2], star[2]); gluTessVertex(tobj, star[3], star[3]); gluTessVertex(tobj, star[4], star[4]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); glEndList(); gluDeleteTess(tobj); }
void MapPainterOpenGL::DrawArea(const Projection& projection, const MapParameter& /*parameter*/, const MapPainter::AreaData& area) { if (area.fillStyle->GetFillColor().IsVisible()) { glColor4d(area.fillStyle->GetFillColor().GetR(), area.fillStyle->GetFillColor().GetG(), area.fillStyle->GetFillColor().GetB(), area.fillStyle->GetFillColor().GetA()); gluTessProperty(tesselator, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); gluTessBeginPolygon(tesselator, NULL); gluTessBeginContour(tesselator); for (size_t i=area.transStart; i<=area.transEnd; i++) { gluTessVertex(tesselator, (GLdouble*)&coordBuffer->buffer[i], (GLdouble*)&coordBuffer->buffer[i]); } gluTessEndContour(tesselator); if (!area.clippings.empty()) { // Clip areas within the area by using CAIRO_FILL_RULE_EVEN_ODD for (std::list<PolyData>::const_iterator c=area.clippings.begin(); c!=area.clippings.end(); c++) { const PolyData& data=*c; gluTessBeginContour(tesselator); for (size_t i=data.transStart; i<=data.transEnd; i++) { gluTessVertex(tesselator, (GLdouble*)&coordBuffer->buffer[i], (GLdouble*)&coordBuffer->buffer[i]); } gluTessEndContour(tesselator); } } gluTessEndPolygon(tesselator); } if (area.fillStyle->GetBorderWidth()>0 && area.fillStyle->GetBorderColor().IsVisible()) { double borderWidth=projection.ConvertWidthToPixel(area.fillStyle->GetBorderWidth()); glColor4d(area.fillStyle->GetBorderColor().GetR(), area.fillStyle->GetBorderColor().GetG(), area.fillStyle->GetBorderColor().GetB(), area.fillStyle->GetBorderColor().GetA()); glLineWidth(borderWidth); glBegin(GL_LINE_LOOP); for (size_t i=area.transStart; i<=area.transEnd; i++) { glVertex3d(coordBuffer->buffer[i].GetX(), coordBuffer->buffer[i].GetY(), 0.0); } glEnd(); } }
int PolyTessGeo::BuildTessGL(void) { #ifdef ocpnUSE_GL int iir, ip; int *cntr; GLdouble *geoPt; wxString sout; wxString sout1; wxString stemp; #ifdef __WXMSW__ // If using the OpenGL dlls provided with Windows, // load the dll and establish addresses of the entry points needed #ifdef USE_GLU_DLL if(!s_glu_dll_ready) { s_hGLU_DLL = LoadLibrary("glu32.dll"); if (s_hGLU_DLL != NULL) { s_lpfnTessProperty = (LPFNDLLTESSPROPERTY)GetProcAddress(s_hGLU_DLL,"gluTessProperty"); s_lpfnNewTess = (LPFNDLLNEWTESS)GetProcAddress(s_hGLU_DLL, "gluNewTess"); s_lpfnTessBeginContour = (LPFNDLLTESSBEGINCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessBeginContour"); s_lpfnTessEndContour = (LPFNDLLTESSENDCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessEndContour"); s_lpfnTessBeginPolygon = (LPFNDLLTESSBEGINPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessBeginPolygon"); s_lpfnTessEndPolygon = (LPFNDLLTESSENDPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessEndPolygon"); s_lpfnDeleteTess = (LPFNDLLDELETETESS)GetProcAddress(s_hGLU_DLL, "gluDeleteTess"); s_lpfnTessVertex = (LPFNDLLTESSVERTEX)GetProcAddress(s_hGLU_DLL, "gluTessVertex"); s_lpfnTessCallback = (LPFNDLLTESSCALLBACK)GetProcAddress(s_hGLU_DLL, "gluTessCallback"); s_glu_dll_ready = true; } else { return ERROR_NO_DLL; } } #endif #endif // Allocate a work buffer, which will be grown as needed #define NINIT_BUFFER_LEN 10000 s_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble)); s_buf_len = NINIT_BUFFER_LEN * 2; s_buf_idx = 0; // Create an array to hold pointers to allocated vertices created by "combine" callback, // so that they may be deleted after tesselation. s_pCombineVertexArray = new wxArrayPtrVoid; // Create tesselator GLUtessobj = gluNewTess(); // Register the callbacks gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (GLvoid (__CALL_CONVENTION *) ())&beginCallback); gluTessCallback(GLUtessobj, GLU_TESS_BEGIN, (GLvoid (__CALL_CONVENTION *) ())&beginCallback); gluTessCallback(GLUtessobj, GLU_TESS_VERTEX, (GLvoid (__CALL_CONVENTION *) ())&vertexCallback); gluTessCallback(GLUtessobj, GLU_TESS_END, (GLvoid (__CALL_CONVENTION *) ())&endCallback); gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (GLvoid (__CALL_CONVENTION *) ())&combineCallback); // gluTessCallback(GLUtessobj, GLU_TESS_ERROR, (GLvoid (__CALL_CONVENTION *) ())&errorCallback); // glShadeModel(GL_SMOOTH); gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); // gluTess algorithm internally selects vertically oriented triangle strips and fans. // This orientation is not optimal for conventional memory-mapped raster display shape filling. // We can "fool" the algorithm by interchanging the x and y vertex values passed to gluTessVertex // and then reverting x and y on the resulting vertexCallbacks. // In this implementation, we will explicitely set the preferred orientation. //Set the preferred orientation tess_orient = TESS_HORZ; // prefer horizontal tristrips // Get total number of contours m_ncnt = m_pxgeom->n_contours; // Allocate cntr array cntr = (int *)malloc(m_ncnt * sizeof(int)); // Get total number of points(vertices) int npta = m_pxgeom->contour_array[0]; cntr[0] = npta; npta += 2; // fluff for( iir=0 ; iir < m_ncnt-1 ; iir++) { int nptr = m_pxgeom->contour_array[iir+1]; cntr[iir+1] = nptr; npta += nptr + 2; // fluff } // printf("xgeom npta: %d\n", npta); geoPt = (GLdouble *)malloc((npta) * 3 * sizeof(GLdouble)); // vertex array // Grow the work buffer if necessary if((npta * 4) > s_buf_len) { s_pwork_buf = (GLdouble *)realloc(s_pwork_buf, npta * 4 * sizeof(GLdouble)); s_buf_len = npta * 4; } // Define the polygon gluTessBeginPolygon(GLUtessobj, NULL); // Create input structures // Exterior Ring int npte = m_pxgeom->contour_array[0]; cntr[0] = npte; GLdouble *ppt = geoPt; // Check and account for winding direction of ring bool cw = true; double x0, y0, x, y; OGRPoint p; wxPoint2DDouble *pp = m_pxgeom->vertex_array; pp++; // skip 0? if(cw) { // poly->getExteriorRing()->getPoint(0, &p); x0 = pp->m_x; y0 = pp->m_y; } else { // poly->getExteriorRing()->getPoint(npte-1, &p); x0 = pp[npte-1].m_x; y0 = pp[npte-1].m_y; // x0 = p.getX(); // y0 = p.getY(); } // pp++; gluTessBeginContour(GLUtessobj); // Transcribe points to vertex array, in proper order with no duplicates // also, accounting for tess_orient for(ip = 0 ; ip < npte ; ip++) { int pidx; if(cw) pidx = npte - ip - 1; else pidx = ip; // poly->getExteriorRing()->getPoint(pidx, &p); x = pp[pidx].m_x; y = pp[pidx].m_y; // pp++; if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS)) { GLdouble *ppt_temp = ppt; if(tess_orient == TESS_VERT) { *ppt++ = x; *ppt++ = y; } else { *ppt++ = y; *ppt++ = x; } *ppt++ = 0.0; gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ; //printf("tess from xgeom, external vertex %g %g\n", x, y); } else cntr[0]--; x0 = x; y0 = y; } gluTessEndContour(GLUtessobj); int index_offset = npte; #if 1 // Now the interior contours for(iir=0; iir < m_ncnt-1; iir++) { gluTessBeginContour(GLUtessobj); // int npti = cntr[iir]; int npti = m_pxgeom->contour_array[iir+1]; // Check and account for winding direction of ring bool cw = false; //!(poly->getInteriorRing(iir)->isClockwise() == 0); if(!cw) { x0 = pp[index_offset].m_x; y0 = pp[index_offset].m_y; } else { x0 = pp[index_offset + npti-1].m_x; y0 = pp[index_offset + 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++) { OGRPoint p; int pidx; if(!cw) // interior contours must be cw pidx = npti - ip - 1; else pidx = ip; x = pp[pidx + index_offset].m_x; y = pp[pidx + index_offset].m_y; if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS)) { GLdouble *ppt_temp = ppt; if(tess_orient == TESS_VERT) { *ppt++ = x; *ppt++ = y; } else { *ppt++ = y; *ppt++ = x; } *ppt++ = 0.0; gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ; // printf("tess from xgeom, internal vertex %d %g %g\n", ip, x, y); } else cntr[iir+1]--; x0 = x; y0 = y; } gluTessEndContour(GLUtessobj); index_offset += npti; } #endif // Store some SM conversion data in static store, // for callback access s_bSENC_SM = false; s_bmerc_transform = true; s_transform_x_rate = m_pxgeom->x_rate; s_transform_x_origin = m_pxgeom->x_offset; s_transform_y_rate = m_pxgeom->y_rate; s_transform_y_origin = m_pxgeom->y_offset; // Ready to kick off the tesselator s_pTPG_Last = NULL; s_pTPG_Head = NULL; s_nvmax = 0; gluTessEndPolygon(GLUtessobj); // here it goes m_nvertex_max = s_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 = s_bSENC_SM; m_ppg_head->nContours = m_ncnt; m_ppg_head->pn_vertex = 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 int nptfinal = npta; // No longer need the full geometry in the SENC, nptfinal = 1; m_nwkb = (nptfinal +1) * 2 * sizeof(float); m_ppg_head->pgroup_geom = (float *)malloc(m_nwkb); float *vro = m_ppg_head->pgroup_geom; ppt = geoPt; float tx,ty; for(ip = 0 ; ip < nptfinal ; ip++) { if(TESS_HORZ == tess_orient) { ty = *ppt++; tx = *ppt++; } else { tx = *ppt++; ty = *ppt++; } if(0/*bSENC_SM*/) { // Calculate SM from chart common reference point double easting, northing; // toSM(ty, tx, ref_lat, 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 = s_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) ); *p_run++ = x; pdouble_buf++; } 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( s_pwork_buf ); s_pwork_buf = NULL; free (geoPt); // All allocated buffers are owned now by the m_ppg_head // And will be freed on dtor of this object delete m_pxgeom; // Free up any "Combine" vertices created for(unsigned int i = 0; i < s_pCombineVertexArray->GetCount() ; i++) free (s_pCombineVertexArray->Item(i)); delete s_pCombineVertexArray; m_pxgeom = NULL; m_bOK = true; #endif //#ifdef ocpnUSE_GL return 0; }
void REGALGLU_CALL gluBeginPolygon( GLUtesselator *tess ) { gluTessBeginPolygon( tess, NULL ); gluTessBeginContour( tess ); }
void GLAPIENTRY gluBeginPolygon( GLUtesselator *tess ) { gluTessBeginPolygon( tess, NULL ); gluTessBeginContour( tess ); }
void tesselateComplexPolygon(Array<Vector3>& input, Array<Triangle>& output) { // Use the GLU triangulator to do the hard work. static GLUtriangulatorObj* tobj = NULL; if (tobj == NULL) { tobj = gluNewTess(); #if defined(G3D_OSX) #define CAST(x) reinterpret_cast<void (*)(...)>(x) #elif defined(G3D_LINUX) #define CAST(x) reinterpret_cast<void (*)()>(x) #else #define CAST(x) reinterpret_cast<void (__stdcall *)(void)>(x) #endif gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, CAST(_tesselateBegin)); gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, CAST(_tesselateVertex)); gluTessCallback(tobj, GLU_TESS_END_DATA, CAST(_tesselateEnd)); gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, CAST(_tesselateCombine)); gluTessCallback(tobj, GLU_TESS_ERROR, CAST(_tesselateError)); gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, GL_FALSE); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); #undef CAST } double v[3]; int i; TessData data; gluTessBeginPolygon(tobj, &data); gluTessBeginContour(tobj); for (i = 0; i < input.size(); ++i) { // Expand the input to double precision v[0] = input[i].x; v[1] = input[i].y; v[2] = input[i].z; gluTessVertex(tobj, v, &(input[i])); } gluTessEndContour(tobj); gluTessEndPolygon(tobj); for (int p = 0; p < data.primitive.size(); ++p) { const TessData::Primitive& primitive = data.primitive[p]; // Turn the tesselated primitive into triangles switch (primitive.primitiveType) { case GL_TRIANGLES: // This is easy, just walk through them in order. for (i = 0; i < primitive.vertex.size(); i += 3) { output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2])); } break; case GL_TRIANGLE_FAN: { // Make a triangle between every pair of vertices and the 1st vertex for (i = 1; i < primitive.vertex.size() - 1; ++i) { output.append(Triangle(primitive.vertex[0], primitive.vertex[i], primitive.vertex[i + 1])); } } break; case GL_TRIANGLE_STRIP: for (i = 0; i < primitive.vertex.size() - 3; i += 2) { output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2])); output.append(Triangle(primitive.vertex[i + 2], primitive.vertex[i + 1], primitive.vertex[i + 3])); } if (i < primitive.vertex.size() - 2) { output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2])); } break; default: //debugAssertM(false, GLenumToString(primitive.primitiveType)); // Ignore other primitives ; } } }
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); }
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 init_scene(int width, int height) { GLubyte* tex; GLUtesselator* tobj; GLfloat rect[4][3]={ {50.0f, 50.0f, 0.0f}, {200.0f, 50.0f, 0.0f}, {200.0f, 200.0f, 0.0f}, {50.0f, 200.0f, 0.0f} }; GLfloat tri[3][3]={ {75.0f, 75.0f, 0.0f}, {125.0f, 175.0f, 0.0f}, {175.0f, 75.0f, 0.0f} }; GLfloat star[5][6]={ {250.0f, 50.0f, 0.0f, 1.0f, 0.0f, 1.0f}, {325.0f, 200.0f, 0.0f, 1.0f, 1.0f, 0.0f}, {400.0f, 50.0f, 0.0f, 0.0f, 1.0f, 1.0f}, {250.0f, 150.0f, 0.0f, 1.0f, 0.0f, 0.0f}, {400.0f, 150.0f, 0.0f, 0.0f, 1.0f, 0.0f} }; GLfloat triangle[9][8]={ {450.0f, 50.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {525.0f, 200.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 1.0f}, {600.0f, 50.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f}, {500.0f, 50.0f, 0.0f, 0.666f, 0.000f, 0.333f, 0.333f, 0.000f}, {550.0f, 150.0f, 0.0f, 0.666f, 0.666f, 1.000f, 0.666f, 0.666f}, {500.0f, 150.0f, 0.0f, 1.000f, 0.666f, 0.666f, 0.333f, 0.666f}, {550.0f, 50.0f, 0.0f, 0.333f, 0.000f, 0.666f, 0.666f, 0.000f}, {575.0f, 100.0f, 0.0f, 0.333f, 0.333f, 1.000f, 0.825f, 0.333f}, {475.0f, 100.0f, 0.0f, 1.000f, 0.333f, 0.333f, 0.175f, 0.333f} }; glViewport(0, 0, (GLsizei)width, (GLsizei)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0f, (GLfloat)width, 0.0f, (GLfloat)height); glClearColor(0.0, 0.0, 0.0, 0.0); /* Create new triangulator */ tobj=gluNewTess(); /* Set triangulator's callbacks */ gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback); gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback); /* reset object */ object1.sequences=0; /* rectangle with triangular hole inside */ gluTessBeginPolygon(tobj, (void*)&object1); gluTessBeginContour(tobj); gluTessVertex(tobj, rect[0], rect[0]); gluTessVertex(tobj, rect[1], rect[1]); gluTessVertex(tobj, rect[2], rect[2]); gluTessVertex(tobj, rect[3], rect[3]); gluTessEndContour(tobj); gluTessBeginContour(tobj); gluTessVertex(tobj, tri[0], tri[0]); gluTessVertex(tobj, tri[1], tri[1]); gluTessVertex(tobj, tri[2], tri[2]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); /* Set triangulator's callbacks */ gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexColorCallback); gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback); gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineColorCallback); /* reset object */ object2.sequences=0; /* self-intersecting star */ gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); gluTessBeginPolygon(tobj, (void*)&object2); gluTessBeginContour(tobj); gluTessVertex(tobj, star[0], star[0]); gluTessVertex(tobj, star[1], star[1]); gluTessVertex(tobj, star[2], star[2]); gluTessVertex(tobj, star[3], star[3]); gluTessVertex(tobj, star[4], star[4]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); /* Set triangulator's callbacks */ gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexTexColorCallback); gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback); gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineTexColorCallback); /* reset object */ object3.sequences=0; /* self-intersecting star */ gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); gluTessBeginPolygon(tobj, (void*)&object3); gluTessBeginContour(tobj); gluTessVertex(tobj, triangle[0], triangle[0]); gluTessVertex(tobj, triangle[1], triangle[1]); gluTessVertex(tobj, triangle[2], triangle[2]); gluTessEndContour(tobj); gluTessBeginContour(tobj); gluTessVertex(tobj, triangle[3], triangle[3]); gluTessVertex(tobj, triangle[4], triangle[4]); gluTessVertex(tobj, triangle[5], triangle[5]); gluTessVertex(tobj, triangle[6], triangle[6]); gluTessVertex(tobj, triangle[7], triangle[7]); gluTessVertex(tobj, triangle[8], triangle[8]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); /* Destroy triangulator object */ gluDeleteTess(tobj); /* enable filtering */ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); tex=make_texture(256, 256); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, tex); free(tex); }
void init (void) { int i; GLUtesselator *tobj; GLdouble rect[4][3] = {50.0, 50.0, 0.0, 200.0, 50.0, 0.0, 200.0, 200.0, 0.0, 50.0, 200.0, 0.0}; GLdouble tri[3][3] = {75.0, 75.0, 0.0, 125.0, 175.0, 0.0, 175.0, 75.0, 0.0}; GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0, 325.0, 200.0, 0.0, 1.0, 1.0, 0.0, 400.0, 50.0, 0.0, 0.0, 1.0, 1.0, 250.0, 150.0, 0.0, 1.0, 0.0, 0.0, 400.0, 150.0, 0.0, 0.0, 1.0, 0.0}; glClearColor(0.0, 0.0, 0.0, 0.0); startList = glGenLists(2); tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3dv); gluTessCallback(tobj, GLU_TESS_BEGIN, beginCallback); gluTessCallback(tobj, GLU_TESS_END, endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, errorCallback); /* rectangle with triangular hole inside */ glNewList(startList, GL_COMPILE); glShadeModel(GL_FLAT); printf("a"); gluTessBeginPolygon(tobj, NULL); printf("b"); gluTessBeginContour(tobj); printf("c"); gluTessVertex(tobj, rect[0], rect[0]); gluTessVertex(tobj, rect[1], rect[1]); gluTessVertex(tobj, rect[2], rect[2]); gluTessVertex(tobj, rect[3], rect[3]); gluTessEndContour(tobj); printf(" d"); gluTessBeginContour(tobj); printf("e"); gluTessVertex(tobj, tri[0], tri[0]); gluTessVertex(tobj, tri[1], tri[1]); gluTessVertex(tobj, tri[2], tri[2]); printf("f"); gluTessEndContour(tobj); printf("g"); gluTessEndPolygon(tobj); printf(" h"); glEndList(); gluTessCallback(tobj, GLU_TESS_VERTEX, vertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN, beginCallback); gluTessCallback(tobj, GLU_TESS_END, endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, combineCallback); /* smooth shaded, self-intersecting star */ glNewList(startList + 1, GL_COMPILE); glShadeModel(GL_SMOOTH); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); gluTessVertex(tobj, star[0], star[0]); gluTessVertex(tobj, star[1], star[1]); gluTessVertex(tobj, star[2], star[2]); gluTessVertex(tobj, star[3], star[3]); gluTessVertex(tobj, star[4], star[4]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); glPushMatrix(); glTranslatef(-100.0, 200.0, 0.0); glBegin(GL_POLYGON); for (i=0; i<5; i++) { glColor3f(star[i][3], star[i][4], star[i][5]); glVertex3f(star[i][0], star[i][1], star[i][2]); } glEnd(); glColor3f(1,1,1); glBegin(GL_LINE_STRIP); glVertex3f(100, 100, 0); glVertex3f(100, -100, 0); glVertex3f(-100, 0, 0); glVertex3f(100, 0, 0); glEnd(); glPopMatrix(); glEndList(); gluDeleteTess(tobj); }
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(); }
//---------------------------------------------------------- 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; }