Welding bodypartseams quicker



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 20/07/2006 at 02:16, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   95/XL7 
    Platform:   Windows  ;   
    Language(s) :   C.O.F.F.E.E  ;

    ---------
    Hello everybody,
    I am developing a plugin that welds the seams of bodyparts belonging to an imported obj-object to create one mesh. It converts all polygonselections for bodyparts into pointselections and stores them in an array. Another array receives the names of the scanned selections. Afterwards I compare the x/y/z-Positions of every point in this array with each other, except they belong to the same selection. For every matching point then I recaluclate the polygons containing them in a way that every polygon references only one of them. The target is to get a mesh keeping the original point-count and pointindices but being welded together. (-> It shall be morphed later on.)
    It works but it is veeeeeery slow. My first attempt, just to weld all points of the same position in one row failed, due to the fact, that for example a face with a closed mouth has shared points of upper and lower lips too, which of course should not be welded together (looks strange slimy when the mouth is opened via morph ;) ), so I had to compare the containing selections too.
    Did anyone of you solve problems like this in a faster way with COFFEE yet and might give me a tipp?
     
    Thanks everybody,
    Ebiwahnkenobi



  • 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.


Log in to reply