Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Login

    Transfering weights

    Scheduled Pinned Locked Moved PYTHON Development
    4 Posts 0 Posters 439 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H Offline
      Helper
      last edited by

      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)

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        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!😠

        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

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          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)
          
          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            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)
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post