THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 20/07/2006 at 09:54, xxxxxxxx wrote:
I've been working on this currently in C++ for imported Poser figures (eh hem). Amazing that there is no information or algorithms for this, isn't it?
Found the same situation with certain morphed figures having the stretchy polygons because of complete welding. Welding must occur at the seams only (between selections). My code isn't exactly simple either, but I do some preprocessing to speed up the process.
The preprocess is only done once and takes the vertex array and does a double loop. This compares a reference vertex to all of the others and sets any other to the reference vertex if they are 'equal' to be later used as a substitution index in the polygons indices.
// Allocate and Initialize substitutions for welding
//*---------------------------------------------------------------------------*
BOOL PoserFigure::AllocSubs(Real epsilon)
//*---------------------------------------------------------------------------*
{
GeFree(subs);
// Assign substitutions if vertices are same
// - Only needs to be done once per figure
Vector* verts = ToPoly(baseObject)->GetPoint();
if (!verts) return ErrorException::Throw(EE_DIALOG, logging, GeLoadString(IPPERR_MEMORY_TEXT), baseObject->GetName(), "PoserFigure.AllocSubs.verts");
LONG ind = ToPoly(baseObject)->GetPointCount();
if (!ind) return ErrorException::Throw(EE_DIALOG, logging, GeLoadString(IPPERR_MEMORY_TEXT), baseObject->GetName(), "Has no vertices");
LONG ind2 = sizeof(LONG)*ind;
subs = (LONG* )GeAlloc(ind2);
if (!subs) return ErrorException::Throw(EE_DIALOG, logging, GeLoadString(IPPERR_MEMORY_TEXT), baseObject->GetName(), "PoserFigure.AllocSubs.subs");
ClearMem(subs, ind2, 0xFF);
LONG a;
ind2 = ind-1;
for (LONG c = 0; c < ind2; ++c)
{
for (a = c+1; a < ind; ++a)
{
if ((subs[a] == 0xFFFFFFFFL) && VectorEqual(verts[a], verts[c], epsilon)) subs[a] = c;
}
}
return TRUE;
}
Note here that 0xFFFFFFFFL is used since vertex indices can be from 0 to MAX_LONG. VectorEqual() is an SDK C++ method that compares the vertex component values using an epsilon value to handle a degree of inaccuracy or specify the range to include in the equality.
The actual welding is even worse as it requires a nested loop between the two polygon selections. I compare the child subs[] for the polygon vertex index against the parent polygon vertex index and the parent subs[] for the polygon vertex index against the child polygon vertex index. Skipping subs[] values of 0xFFFFFFFFL, if the sub equals the index, that means the polygon vertex index is to be substituted by the other's polygon vertex index. This keeps the welds on the seam only. The naive approach of just replacing all substituted indices ends up with the inter-selection welding that causes the undesired stretchy polygons.
Good luck. Let us know if you conceive of a more efficient algorithm.