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 Truedef 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 zero2- 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
-
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)