// 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; }
// tesselates the contours in preparation for a 3D output; // returns true if all was fine, false otherwise bool VRML_LAYER::Tesselate( VRML_LAYER* holes ) { if( !tess ) { error = "Tesselate(): GLU tesselator was not initialized"; return false; } pholes = holes; Fault = false; 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; // open the polygon gluTessBeginPolygon( tess, this ); pushVertices( false ); // close the polygon gluTessEndPolygon( tess ); if( Fault ) return false; // push the (solid) outline to the tesselator if( !pushOutline( holes ) ) 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 NULL; } if( Fault ) return false; // erase the previous outline data and vertex order // but preserve the extra vertices for( int i = outline.size(); i > 0; --i ) { delete outline.back(); outline.pop_back(); } for( unsigned int i = ordmap.size(); i > 0; --i ) ordmap.pop_back(); // 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; } ord = 0; // close the polygon; we now have all the data necessary for the tesselation gluTessEndPolygon( tess ); // request a tesselated surface gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE ); if( !pushOutline( holes ) ) return false; gluTessEndPolygon( tess ); if( Fault ) return false; return true; }