前言

  今年一月份的时候有遇到 BlendShape 需要特殊处理的地方于是研究了 OpenMaya 底层的 MPxBlendShape 实现。链接
  不过那个时候还没有搞懂 MPxBlendShape 这个东东的实现原理,后来因为弄 RBF 表情驱动,又研究了 BlendShape 一些属性,方才懂了一些。
  可以看我 2019-5-25 更新的说明。
  今天看到有人求解 BlendShape 的中间值过渡,我就在这里整理一下我目前所知道的。

BlendShape 节点

BlendShape操作

  我们可以到节点编辑器下创建一个 BlendShape 来查看 BlendShape 有的属性
  通过帮助可以打开 BlendShape 的属性详解页面,里面有 BlendShape 每一个属性的说明。

  当然上面的属性繁杂,通常我们只需要关注几个属性即可。
  我们可以去创建一个 BlendShape 链接来查看链接的属性。

BlendShape操作

  打开节点编辑器查看被连接的属性

BlendShape操作

  可以看到这么多属性只有 inputTargetItem 是被连接了的
  并且还是连接到了 6000 序号上,到这里肯定会很疑惑,之前连接属性都是从零开始的,咋这里就直接蹦到 6000 去了,而且后面还有个 6001 (O_O)?
  其实帮助文档中有说明的

BlendShape操作

  通过文档可以知道序号值是 权重值 * 1000 + 5000 得到的。
  默认 BlendShape 的权重值为1 因此这里得到的数值就是 6000
  至于 6001 则是因为 Maya 节点属性会自动递增保留一个可连接的空属性
  那么更进一步 inbetween 的中间值就是 5500 指代 0.5 的权重了

  我们可以连接 inbetween 属性验证一下我们的想法

BlendShape操作

  打开添加 BlendShape 的面板

BlendShape操作

  换句话说,如果中间过渡权重超过 1 或者 小于 0 那相应的序号应该是 大于 6000 或者 小于 5000 了

BlendShape操作

代码操作

  理解上面的原理之后,要去找到 BlendShape 的中间权重也就不困难了
  废话不多说直接上代码。

pymel 获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import pymel.core as pm

# NOTE 获取 BlendShape 节点
BS = pm.ls("blendShape1")[0]

# NOTE 获取连接节点的数量
BS.inputTarget[0].inputTargetGroup[0].inputTargetItem.numConnectedElements()
# Result: 4 #

# NOTE 获取连接节点的序号
BS.inputTarget[0].inputTargetGroup[0].inputTargetItem.getArrayIndices()
# Result: [4500, 5500, 6000, 6500] #

# NOTE 获取连接的属性
BS.inputTarget[0].inputTargetGroup[0].inputTargetItem.elements()
# Result: [u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500]',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500].inputGeomTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500].inputRelativePointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500].inputRelativeComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500].inputPointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[4500].inputComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500]',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500].inputGeomTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500].inputRelativePointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500].inputRelativeComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500].inputPointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[5500].inputComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000]',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputGeomTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputRelativePointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputRelativeComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputPointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500]',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500].inputGeomTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500].inputRelativePointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500].inputRelativeComponentsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500].inputPointsTarget',
# u'inputTarget[0].inputTargetGroup[0].inputTargetItem[6500].inputComponentsTarget']

# NOTE 权重值转换
[(weight-5000)/1000.0 for weight in BS.inputTarget[0].inputTargetGroup[0].inputTargetItem.getArrayIndices()]
# Result: [-0.5, 0.5, 1.0, 1.5] #

cmds 获取

1
2
3
4
5
6
7
8
9
from maya import cmds

# NOTE 假设存在 blendShape1 节点
cmds.getAttr("blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem",multiIndices=1)
# Result: [4500L, 5500L, 6000L, 6500L] #

# NOTE 权重值转换
[(weight-5000)/1000.0 for weight in cmds.getAttr("blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem",multiIndices=1)]
# Result: [-0.5, 0.5, 1.0, 1.5] #

MEL 获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
getAttr -multiIndices "blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem";
// Result: 4500 5500 6000 6500 //

// 权重值转换
int $weights[] = `getAttr -multiIndices "blendShape1.inputTarget[0].inputTargetGroup[0].inputTargetItem"`;
float $originWeights[];
int $i;
for($i=0;$i<size($weights);$i++){
$originWeights[$i] = ($weights[$i]-5000.0) / 1000.0;
}
print $originWeights;
// -0.5
// 0.5
// 1
// 1.5

总结

  以上就是 BlendShape 处理中间权重的方法。
  比较推荐使用 pymel 的方法,借助 OpenMaya 可以轻松获取到更多信息。