From Fabien Lavignotte, "I have used the osgUtil::DelaunayTriangulator to insert roads into a

terrain. The triangulator is quite tricky to use properly but works
quite well, constraint triangulation is not an easy task... I have
encounter some crash during the development that the following patch
fix.
The two fixes are :
 - Fix in removeVerticesInside() : needs to take into account UByte and
UShort version of DrawElements to avoid a crash later
 - Fix a crash in triangulate() : detect degenerate adjacency case to
exit early form the adjacent triangle traversal loop to avoid a crash
later"
This commit is contained in:
Robert Osfield 2009-11-19 11:16:58 +00:00
parent f38d1cdbb4
commit ec788e92f2

View File

@ -613,6 +613,24 @@ Triangle_list fillHole(osg::Vec3Array *points, std::vector<unsigned int> vind
return triangles; return triangles;
} }
template <typename TVector>
void removeIndices( TVector& elements, unsigned int index )
{
typename TVector::iterator itr = elements.begin();
while ( itr != elements.end() )
{
if ( (*itr)==index )
{ // remove entirely
itr = elements.erase(itr);
}
else
{
if ((*itr)>index) --(*itr); // move indices down 1
++itr; // next index
}
}
}
void DelaunayConstraint::removeVerticesInside(const DelaunayConstraint *dco) void DelaunayConstraint::removeVerticesInside(const DelaunayConstraint *dco)
{ /** remove vertices from this which are internal to dco. { /** remove vertices from this which are internal to dco.
* retains potins that are extremely close to edge of dco * retains potins that are extremely close to edge of dco
@ -631,24 +649,20 @@ void DelaunayConstraint::removeVerticesInside(const DelaunayConstraint *dco)
for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++)
{ {
osg::PrimitiveSet* prset=getPrimitiveSet(ipr); osg::PrimitiveSet* prset=getPrimitiveSet(ipr);
osg::DrawElementsUShort *dsup=dynamic_cast<osg::DrawElementsUShort *>(prset); switch (prset->getType())
if (dsup) {
for (osg::DrawElementsUShort::iterator usitr=dsup->begin(); usitr!=dsup->end(); )
{
if ((*usitr)==idx)
{ // remove entirely
usitr=dsup->erase(usitr);
}
else
{
if ((*usitr)>idx) (*usitr)--; // move indices down 1
usitr++; // next index
}
}
}
else
{ {
case osg::PrimitiveSet::DrawElementsUBytePrimitiveType:
removeIndices( *static_cast<osg::DrawElementsUByte *>(prset), idx );
break;
case osg::PrimitiveSet::DrawElementsUShortPrimitiveType:
removeIndices( *static_cast<osg::DrawElementsUShort *>(prset), idx );
break;
case osg::PrimitiveSet::DrawElementsUIntPrimitiveType:
removeIndices( *static_cast<osg::DrawElementsUInt *>(prset), idx );
break;
default:
osg::notify(osg::WARN) << "Invalid prset " <<ipr<< " tp " << prset->getType() << " types PrimitiveType,DrawArraysPrimitiveType=1 etc" << std::endl; osg::notify(osg::WARN) << "Invalid prset " <<ipr<< " tp " << prset->getType() << " types PrimitiveType,DrawArraysPrimitiveType=1 etc" << std::endl;
break;
} }
} }
vitr=vertices->erase(vitr); vitr=vertices->erase(vitr);
@ -1037,7 +1051,11 @@ bool DelaunayTriangulator::triangulate()
} else { } else {
if (!tradj->usesVertex(ip2)) osg::notify(osg::WARN) << "tradj error " << tradj->a()<< " , " << tradj->b()<< " , " << tradj->c()<< std::endl; if (!tradj->usesVertex(ip2)) osg::notify(osg::WARN) << "tradj error " << tradj->a()<< " , " << tradj->b()<< " , " << tradj->c()<< std::endl;
} }
const Triangle *previousTradj = tradj;
tradj=getTriangleWithEdge(e2,e1, &triangles); tradj=getTriangleWithEdge(e2,e1, &triangles);
if (tradj == previousTradj) {
tradj = 0;
}
} }
if (trisToDelete.size()>=900) { if (trisToDelete.size()>=900) {
osg::notify(osg::WARN) << " found " << trisToDelete.size() << " adjacent tris " <<std::endl; osg::notify(osg::WARN) << " found " << trisToDelete.size() << " adjacent tris " <<std::endl;