Transfering weights

On 19/09/2014 at 23:58, xxxxxxxx wrote:

I'm attempting to write a script that would transfer weights from one weght tag to another. The rigs are somewhat different and have different naming conventions, but the point count of the object is the same. I've cobbled up together a little script but I'm not getting a weight transfer of a test joint.

import c4d
from c4d import gui, documents
#This script copies weights from a figure to the
#custom c4d rig
  
  
class transferW(gui.GeDialog) :
   
    def CreateLayout(self) :
        #create the layout of the dialog
        self.SetTitle("Weight Transfer")
        self.GroupBegin(1001, c4d.BFH_SCALEFIT, 2, 3)
        self.AddStaticText(1002, flags=c4d.BFH_LEFT, initw=100, name="Source")
        self.sourceLink = self.AddCustomGui(1003, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
        self.AddStaticText(1003, flags=c4d.BFH_LEFT, initw=100, name="Target")
        self.targetLink = self.AddCustomGui(1004, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
         
        self.AddButton(1005, c4d.BFH_SCALE, name="Execute")
        self.GroupEnd()
        
        return True
   
    def InitValues(self) :
        #initiate the gadgets with values
        return True
   
    def Command(self, id, msg) :
        #handle user input
        if id==1005:
            self.TranferWeight()
        return True

def TranferWeight(self) :
        #Do the weight transfer
        sourceWeights = self.sourceLink.GetLink() #Gets the link to the source weight tag
        targetWeights = self.targetLink.GetLink() #Get the link to the target weight tag
        
        jntCount = sourceWeights.GetJointCount()
        sIndex = 0; #Setup the source joint index
        dIndex = 0; #Setup the destination joint index
        
        #quick loop to find neck joint in the source genesis rig
        for i in range(0, jntCount) : 
            jnt = sourceWeights.GetJoint(i, doc)
            if jnt.GetName() == "neck":
                sIndex = i
                break
        #quick loop to find neck joint in the destination genesis rig
        jntCount = targetWeights.GetJointCount() 
        for i in range(0, jntCount) :
            jnt = targetWeights.GetJoint(i, doc)
            if jnt.GetName() == "neck":
                dIndex = i
                break
        
        print "Source Index: ",sIndex, "Dest Index: ", dIndex
        
        #Transfer weight
        sourceWeights.TransferWeightMap(doc, targetWeights, sIndex, dIndex, 0, c4d.NOTOK)
        
        c4d.EventAdd()
        
        return True
   
dlg = transferW()
dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=300, defaulth=50)

On 21/09/2014 at 10:16, xxxxxxxx wrote:

Welcome,

Two things that I'm seeing:
1- You're sIndex & dIndex variables will always return zero the way they are used.
They should probably be either global, or class member variables, so they don't reset themselves to zero

2- The Python version of TransferWeightMap() seems to be broken.
It sets the weight values to zero instead of the weight values from the source tag. OUCH!:angry:

Here's an example for both C++ and Python that I used to test it:

//C++ version works  
  
  BaseObject *sourceObj = doc->SearchObject("mesh1");  
  BaseTag *sourceWeights = sourceObj->GetTag(Tweights);  
  BaseObject *targetObj = doc->SearchObject("mesh2");  
  BaseTag *targetWeights = targetObj->GetTag(Tweights);  
  CAWeightTag *sw = (CAWeightTag* )sourceWeights;  
  CAWeightTag *tw = (CAWeightTag* )targetWeights;  
  
  String sname = sw->GetJoint(1,doc)->GetName();  
  String tname = tw->GetJoint(1,doc)->GetName();  
  GePrint(sname + "  " + tname);  
  
  Real s = sw->GetWeight(1,1);  
  Real t = tw->GetWeight(1,1);  
  GePrint(RealToString(s) + "  " + RealToString(t));  
  
  
  PolygonObject *sobj = (PolygonObject* )sourceObj;  
  LONG pntcount = sobj->GetPointCount();  
  //The WM lists joints in alphabetical order  
  //Copy the second WM joint from the source to the second WM joint in the target  
  sw->TransferWeightMap(doc, tw, 1, 1, NOTOK, pntcount, NULL);   
    
  EventAdd();  
  
/////////////////////////////////////////////////////////////////////////////////////////////////////////  
  
  
#Python version seems to be broken...It sets the weight values on the target to zero!!!  
  
import c4d  
def main() :  
    
  jointID = 1  
    
  sourceObj = doc.SearchObject("mesh1")  
  sourceWeights = sourceObj.GetTag(c4d.Tweights)  
  targetObj = doc.SearchObject("mesh2")  
  targetWeights = targetObj.GetTag(c4d.Tweights)  
  
  sname = sourceWeights.GetJoint(jointID,doc).GetName()  
  tname = targetWeights.GetJoint(jointID,doc).GetName()  
  print sname, "  " ,tname  
  
  s = sourceWeights.GetWeight(jointID,0)  
  t = targetWeights.GetWeight(jointID,0)  
  print s, "  " , t  
  
  pntcount = sourceObj.GetPointCount()  
  #The WM lists joints in alphabetical order  
  #Copy the second WM joint from the source to the second WM joint in the target  
  sourceWeights.TransferWeightMap(doc, targetWeights, jointID, jointID, c4d.NOTOK, pntcount)   
    
  c4d.EventAdd()  
  
if __name__=='__main__':  
  main()

Even if it did work properly. The TransferWeightMap() function is not the best choice for transferring weight values between two different rigs. Because this function will make your target mesh be deformed by the source rig's joints.
This is also the same thing that happens when using the VAMP tool. And why so many people have problems with it. It's not a good choice for copying and pasting the weight values between the weight tags in two different rigs.

I do know how to transfer the weights using different code though.
If you want it I'll post it.

-ScottA

On 22/09/2014 at 11:27, xxxxxxxx wrote:

Yeah, I came up with a slightly different technique that brute forces it after finding the the Transfer Maps just would not work. My code worked initially, but when I created the JointTransfer function to simplify code it fails at the GetName() for the target joint. Since I'm targeting this at a very specific rig I made some very specific assumptions about the script: The point count between the object will and should match, and the only thing that different is where the joint are placed and their names. Since the point counts are the same my thinking was to get the source point count and then based on the joint specified iterate through all the mesh points only applying weight where applicable to a specific joint. If there is a more optimized less error prone way I'd really appreciate it. That's for the help.

import c4d
from c4d import gui, documents
# this script copies weights from a figure to the
# custom c4d rig, point counts of both rigs need to
# match
  
global sourceWeights
global targetWeights
global meshPntCnt
  
class transferW(gui.GeDialog) :
   
    def CreateLayout(self) :
        #create the layout of the dialog
        self.SetTitle("Weight Transfer")
        self.GroupBegin(1001, c4d.BFH_SCALEFIT, 2, 3)
        self.AddStaticText(1002, flags=c4d.BFH_LEFT, initw=100, name="Source")
        self.sourceLink = self.AddCustomGui(1003, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
        self.AddStaticText(1003, flags=c4d.BFH_LEFT, initw=100, name="Target")
        self.targetLink = self.AddCustomGui(1004, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
         
        self.AddButton(1005, c4d.BFH_SCALE, name="Execute")
        self.GroupEnd()
        
        return True
   
    def InitValues(self) :
        #initiate the gadgets with values
        return True
   
    def Command(self, id, msg) :
        #handle user input
        if id==1005:
            self.TranferWeight()
        return True
    
    # transfer weights between source and target joint, takes the names
    # as args
    def JointTransfer(self, sJntName, tJntName) :
        global sourceWeights
        global targetWeights
        
        sJntIndex = 0; #Setup the source joint index
        dJntIndex = 0; #Setup the destination joint index
        
        # we need the joint count so we can do a name match search
        # through all the joints in the weight tags
        jntCount = sourceWeights.GetJointCount()
        
        #quick loop to find source joint in the source genesis rig
        for i in range(0, jntCount) : 
            jnt = sourceWeights.GetJoint(i, doc)
            if jnt.GetName() == sJntName:
                sJntIndex = i
                break
            
        #quick loop to find target joint in the destination genesis rig
        jntCount = targetWeights.GetJointCount() 
        print jntCount
        for i in range(0, jntCount) :
            jnt = targetWeights.GetJoint(i, doc)
            print jnt.GetName()
            if jnt.GetName() == tJntName:
                dJntIndex = i
                break
        
        # we are going to brute force this. we'll go through every vertex
        # on the mesh and check if this joint is weighted. if it is we'll
        # set the weight on our new mesh 
        for i in range(0, meshPntCnt) :
            #Get the weight of the current vertex
            weight = sourceWeights.GetWeight(sJntIndex, i)
            
            # if the weight is greater than 0 lets set it on the new joint
            if weight > 0:    
                targetWeights.SetWeight(dJntIndex, i, weight)
                #print "Index ", i,": ", weight #debug
                
        return
    
    #Do the weight transfer
    def TranferWeight(self) :
        global sourceWeights
        global targetWeights
        
        #Gets the link to the source weight tag
        sourceWeights = self.sourceLink.GetLink().GetTag(c4d.Tweights)
        
        #Get the link to the target weight tag
        targetWeights = self.targetLink.GetLink().GetTag(c4d.Tweights)
        
        #The mesh point count
        meshPntCnt = self.sourceLink.GetLink().GetPointCount()
        
        # use a custom function to transfer joints
        self.JointTransfer("abdomen", "abdomen")
        self.JointTransfer("abdomen2", "abdomen2")
        self.JointTransfer("chest", "chest")
        self.JointTransfer("lPectoral", "l_Pectoral")
        self.JointTransfer("rPectoral", "r_Pectoral")
        self.JointTransfer("neck", "neck")
        self.JointTransfer("head", "head")
        self.JointTransfer("lEye", "l_Eye")
        #self.JointTransfer("rEye", "r_Eye")
        self.JointTransfer("pelvis", "pelvis")
        self.JointTransfer("lThigh", "l_Thigh")
        self.JointTransfer("lShin", "l_Shin")
        self.JointTransfer("lFoot", "l_Foot")
        self.JointTransfer("lToe", "l_Toe")
        self.JointTransfer("lBigToe", "l_BigToe")
        self.JointTransfer("rThigh", "r_Thigh_1")
        self.JointTransfer("rShin", "r_Shin_1")
        self.JointTransfer("rFoot", "r_Foot_1")
        self.JointTransfer("rToe", "r_Toe_1")
        self.JointTransfer("rBigToe", "r_BigToe_1")
        self.JointTransfer("lCollar", "l_Collar")
        self.JointTransfer("lShldr", "l_Shldr")
        self.JointTransfer("lForeArm", "l_ForeArm")
        self.JointTransfer("lHand", "l_Hand")
        self.JointTransfer("lThumb1", "l_Thumb1")
        self.JointTransfer("lThumb1", "l_Thumb2")
        self.JointTransfer("lThumb1", "l_Thumb3")
        self.JointTransfer("lCarpal1", "l_Carpal1")
        self.JointTransfer("lCarpal2", "l_Carpal2")
        self.JointTransfer("lIndex1", "l_Index1")
        self.JointTransfer("lIndex2", "l_Index2")
        self.JointTransfer("lIndex3", "l_Index3")
        self.JointTransfer("lMid1", "l_Mid1")
        self.JointTransfer("lMid2", "l_Mid2")
        self.JointTransfer("lMid3", "l_Mid3")
        self.JointTransfer("lRing1", "l_Ring1")
        self.JointTransfer("lRing2", "l_Ring2")
        self.JointTransfer("lRing3", "l_Ring3")
        self.JointTransfer("rCollar", "r_Collar")
        self.JointTransfer("rShldr", "r_Shldr_1")
        self.JointTransfer("rForeArm", "r_ForeArm_1")
        self.JointTransfer("rHand", "r_Hand_1")
        self.JointTransfer("rThumb1", "r_Thumb1_1")
        self.JointTransfer("rThumb1", "r_Thumb2_1")
        self.JointTransfer("rThumb1", "r_Thumb3_1")
        self.JointTransfer("rCarpal1", "r_Carpal1_1")
        self.JointTransfer("rCarpal2", "r_Carpal2_1")
        self.JointTransfer("rIndex1", "r_Index1_1")
        self.JointTransfer("rIndex2", "r_Index2_1")
        self.JointTransfer("rIndex3", "r_Index3_1")
        self.JointTransfer("rMid1", "r_Mid1_1")
        self.JointTransfer("rMid2", "r_Mid2_1")
        self.JointTransfer("rMid3", "r_Mid3_1")
        self.JointTransfer("rRing1", "r_Ring1_1")
        self.JointTransfer("rRing2", "r_Ring2_1")
        self.JointTransfer("rRing3", "r_Ring3_1")
          
        c4d.EventAdd()
        
        return True
   
dlg = transferW()
dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=300, defaulth=50)

On 23/09/2014 at 07:40, xxxxxxxx wrote:

Here's the final working script in case anyone needs to do something similar in the future. It's very specific and works with one type of rig but it could be adapted.

import c4d
from c4d import gui, documents
from types import *
# this script copies weights from a figure to the a
# custom c4d rig, point counts of both rigs need to
# match
  
global sourceWeights
global targetWeights
global meshPntCnt
  
class transferW(gui.GeDialog) :
   
    def CreateLayout(self) :
        #create the layout of the dialog
        self.SetTitle("Weight Transfer")
        self.GroupBegin(1001, c4d.BFH_SCALEFIT, 2, 3)
        self.AddStaticText(1002, flags=c4d.BFH_LEFT, initw=100, name="Source")
        self.sourceLink = self.AddCustomGui(1003, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
        self.AddStaticText(1003, flags=c4d.BFH_LEFT, initw=100, name="Target")
        self.targetLink = self.AddCustomGui(1004, c4d.CUSTOMGUI_LINKBOX, "",
         c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 400, 0)
         
        self.AddButton(1005, c4d.BFH_SCALE, name="Execute")
        self.GroupEnd()
        
        return True
   
    def InitValues(self) :
        #initiate the gadgets with values
        return True
   
    def Command(self, id, msg) :
        #handle user input
        if id==1005:
            self.TranferWeight()
        return True
    
    # transfer weights between source and target joint, takes the names
    # as args
    def JointTransfer(self, sJntName, tJntName) :
        global sourceWeights
        global targetWeights
        global meshPntCnt
        
        sJntIndex = 0; #Setup the source joint index
        dJntIndex = 0; #Setup the destination joint index
        
        # we need the joint count so we can do a name match search
        # through all the joints in the weight tags
        jntCount = sourceWeights.GetJointCount()
        
        #quick loop to find source joint in the source genesis rig
        for i in range(0, jntCount) : 
            jnt = sourceWeights.GetJoint(i, doc)
            if(type(jnt) != NoneType) :
                if jnt.GetName() == sJntName:
                    sJntIndex = i
                    break
            
        #quick loop to find target joint in the destination genesis rig
        jntCount = targetWeights.GetJointCount()
        for i in range(0, jntCount) :
            jnt = targetWeights.GetJoint(i, doc)
            if(type(jnt) != NoneType) :
                if jnt.GetName() == tJntName:
                    dJntIndex = i
                    break
        
        # we are going to brute force this. we'll go through every vertex
        # on the mesh and check if this joint is weighted. if it is we'll
        # set the weight on our new mesh 
        for i in range(0, meshPntCnt) :
            #Get the weight of the current vertex
            weight = sourceWeights.GetWeight(sJntIndex, i)
            
            #Set the weight to target mesh and joint
            targetWeights.SetWeight(dJntIndex, i, weight)
                
        return
    
    #Do the weight transfer
    def TranferWeight(self) :
        global sourceWeights
        global targetWeights
        global meshPntCnt
        
        #Gets the link to the source weight tag
        sourceWeights = self.sourceLink.GetLink().GetTag(c4d.Tweights)
        
        #Get the link to the target weight tag
        targetWeights = self.targetLink.GetLink().GetTag(c4d.Tweights)
        
        #The mesh point count
        meshPntCnt = self.sourceLink.GetLink().GetPointCount()
        
        # use a custom function to transfer joints
        self.JointTransfer("abdomen", "abdomen")
        self.JointTransfer("abdomen2", "abdomen2")
        self.JointTransfer("chest", "chest")
        self.JointTransfer("lPectoral", "l_Pectoral")
        self.JointTransfer("rPectoral", "r_Pectoral")
        self.JointTransfer("neck", "neck")
        self.JointTransfer("head", "head")
        self.JointTransfer("lEye", "l_Eye")
        #self.JointTransfer("rEye", "r_Eye")
        self.JointTransfer("pelvis", "pelvis")
        self.JointTransfer("lThigh", "l_Thigh")
        self.JointTransfer("lShin", "l_Shin")
        self.JointTransfer("lFoot", "l_Foot")
        self.JointTransfer("lToe", "l_Toe")
        self.JointTransfer("lBigToe", "l_BigToe")
        self.JointTransfer("rThigh", "r_Thigh_1")
        self.JointTransfer("rShin", "r_Shin_1")
        self.JointTransfer("rFoot", "r_Foot_1")
        self.JointTransfer("rToe", "r_Toe_1")
        self.JointTransfer("rBigToe", "r_BigToe_1")
        self.JointTransfer("lCollar", "l_Collar")
        self.JointTransfer("lShldr", "l_Shldr")
        self.JointTransfer("lForeArm", "l_ForeArm")
        self.JointTransfer("lHand", "l_Hand")
        self.JointTransfer("lThumb1", "l_Thumb1")
        self.JointTransfer("lThumb2", "l_Thumb2")
        self.JointTransfer("lThumb3", "l_Thumb3")
        self.JointTransfer("lCarpal1", "l_Carpal1")
        self.JointTransfer("lCarpal2", "l_Carpal2")
        self.JointTransfer("lIndex1", "l_Index1")
        self.JointTransfer("lIndex2", "l_Index2")
        self.JointTransfer("lIndex3", "l_Index3")
        self.JointTransfer("lMid1", "l_Mid1")
        self.JointTransfer("lMid2", "l_Mid2")
        self.JointTransfer("lMid3", "l_Mid3")
        self.JointTransfer("lRing1", "l_Ring1")
        self.JointTransfer("lRing2", "l_Ring2")
        self.JointTransfer("lRing3", "l_Ring3")
        self.JointTransfer("lPinky1", "l_Pinky1")
        self.JointTransfer("lPinky2", "l_Pinky2")
        self.JointTransfer("lPinky3", "l_Pinky3")
        self.JointTransfer("rCollar", "r_Collar")
        self.JointTransfer("rShldr", "r_Shldr_1")
        self.JointTransfer("rForeArm", "r_ForeArm_1")
        self.JointTransfer("rHand", "r_Hand_1")
        self.JointTransfer("rThumb1", "r_Thumb1_1")
        self.JointTransfer("rThumb2", "r_Thumb2_1")
        self.JointTransfer("rThumb3", "r_Thumb3_1")
        self.JointTransfer("rCarpal1", "r_Carpal1_1")
        self.JointTransfer("rCarpal2", "r_Carpal2_1")
        self.JointTransfer("rIndex1", "r_Index1_1")
        self.JointTransfer("rIndex2", "r_Index2_1")
        self.JointTransfer("rIndex3", "r_Index3_1")
        self.JointTransfer("rMid1", "r_Mid1_1")
        self.JointTransfer("rMid2", "r_Mid2_1")
        self.JointTransfer("rMid3", "r_Mid3_1")
        self.JointTransfer("rRing1", "r_Ring1_1")
        self.JointTransfer("rRing2", "r_Ring2_1")
        self.JointTransfer("rRing3", "r_Ring3_1")
        self.JointTransfer("rPinky1", "r_Pinky1_1")
        self.JointTransfer("rPinky2", "r_Pinky2_1")
        self.JointTransfer("rPinky3", "r_Pinky3_1")
                
        # update scene and object  
        self.targetLink.GetLink().Message(c4d.MSG_UPDATE)
        c4d.EventAdd()
       
        
        return True
   
dlg = transferW()
dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=300, defaulth=50)