When programmatically setting weights on Maya’s skinCluster, you might encounter a warning:
# Warning: Some weights could not be set to the specified value. The weight total would have exceeded 1.0. #
So, clearly a bug in your code, right? This is what I was assuming, until the obvious hit me: “ok, let’s find out the actual thresholds first”.
Behold, a test harness:
from maya import cmds
def test(testValue, expectationOk):
cmds.file(new=True, force=True)
p = cmds.polyPlane()[0]
cmds.select(cl=True)
j = cmds.joint()
sc = cmds.skinCluster(j,p)[0]
print "testing value: %03.19f" % testValue
print "threshold is %03.19f" % abs(1.0-testValue)
if expectationOk:
print "expecting no warning..."
else:
print "expecting a warning..."
cmds.skinPercent(sc, p+'.vtx[0]', transformValue=[(j, testValue)])
print "---"
test(1.000000000000000000, True)
test(1.000000000099999897, True)
test(1.000000000099999898, False)
test(0.999999999900000048, True)
test(0.999999999900000047, False)
The above code is pretty simple:
- Create a simple scene: a mesh, one joint, bind to skin cluster;
- Pick a random weight (near
1.0
) and set that on one vertex. - Depending how far from
1.0
it’s been chosen, Maya will either produce the warning or not. - Play a little game finding the limits of when the warning is produced and when it is not.
Output produced was:
testing value: 1.0000000000000000000
threshold is 0.0000000000000000000
expecting no warning...
---
testing value: 1.0000000000999997862
threshold is 0.0000000000999997862
expecting no warning...
---
testing value: 1.0000000001000000083
threshold is 0.0000000001000000083
expecting a warning...
# Warning: Some weights could not be set to the specified value. The weight total would have exceeded 1.0. #
---
testing value: 0.9999999999000001027
threshold is 0.0000000000999998973
expecting no warning...
---
testing value: 0.9999999998999999917
threshold is 0.0000000001000000083
expecting a warning...
# Warning: Some weights could not be set to the specified value. The weight total would have exceeded 1.0. #
---
I’d say it’s safe to assume that pseudo-formula Maya is using to produce the warning is:
if abs(1.0-actual_sum_of_weights)>=0.0000000001:
produce_a_warning()
Sounds like a pretty rough limit. Slightly higher errors should definitely not make a difference for mesh deformation.
Solution? Probably easiest is just to disable normalization in the skinCluster, if your weights setting code already takes care of that.
setAttr "skinCluster1.normalizeWeights" 0;
For now I guess I’ll add an assertion checking the weights ngSkinTools is producing and see if I can tweak normalization algorithm to be a bit more precise.