void Collapse( PMVertex src )
{
PMVertex dest = src.collapseTo;
List<PMVertex> recomputeSet = new List<PMVertex>();
// Abort if we're never supposed to collapse
if ( src.collapseCost == float.MaxValue )
return;
// Remove this vertex from the running for the next check
src.collapseTo = null;
src.collapseCost = float.MaxValue;
worstCosts[ (int)src.index ] = float.MaxValue;
// Collapse the edge uv by moving vertex u onto v
// Actually remove tris on uv, then update tris that
// have u to have v, and then remove u.
if ( dest == null )
{
// src is a vertex all by itself
return;
}
// Add dest and all the neighbours of source and dest to recompute list
recomputeSet.Add( dest );
foreach ( PMVertex neighbor in src.neighbors )
{
if ( !recomputeSet.Contains( neighbor ) )
recomputeSet.Add( neighbor );
}
foreach ( PMVertex neighbor in dest.neighbors )
{
if ( !recomputeSet.Contains( neighbor ) )
recomputeSet.Add( neighbor );
}
// delete triangles on edge src-dest
// Notify others to replace src with dest
// Queue of faces for removal / replacement
// prevents us screwing up the iterators while we parse
List<PMTriangle> faceRemovalList = new List<PMTriangle>();
List<PMTriangle> faceReplacementList = new List<PMTriangle>();
foreach ( PMTriangle face in src.faces )
{
if ( face.HasCommonVertex( dest ) )
{
// Tri is on src-dest therefore is gone
faceRemovalList.Add( face );
// Reduce index count by 3 (useful for quick allocation later)
currNumIndexes -= 3;
}
else
{
// Only src involved, replace with dest
faceReplacementList.Add( face );
}
}
src.toBeRemoved = true;
// Replace all the faces queued for replacement
foreach ( PMTriangle face in faceReplacementList )
{
/* Locate the face vertex which corresponds with the common 'dest' vertex
To to this, find a removed face which has the FACE vertex corresponding with
src, and use it's FACE vertex version of dest.
*/
PMFaceVertex srcFaceVert = face.GetFaceVertexFromCommon( src );
PMFaceVertex destFaceVert = null;
foreach ( PMTriangle removed in faceRemovalList )
{
//if (removed.HasFaceVertex(srcFaceVert))
//{
destFaceVert = removed.GetFaceVertexFromCommon( dest );
//}
}
Debug.Assert( destFaceVert != null );
face.ReplaceVertex( srcFaceVert, destFaceVert );
}
// Remove all the faces queued for removal
foreach ( PMTriangle face in faceRemovalList )
{
face.NotifyRemoved();
}
// Notify the vertex that it is gone
src.NotifyRemoved();
// recompute costs
foreach ( PMVertex recomp in recomputeSet )
{
ComputeEdgeCostAtVertex( recomp.index );
}
}
#endregion