前言

  这次的问题是之前一起实习的朋友发来问我的,我上个月就帮他解决了问题,拖到现在才来记录一下填坑记录(:з」∠)
  说实话我是没想到有 Houdini 不用,居然会用 Maya MASH 插件来做效果的。
  朋友说那是因为那边的模型管理可以用 MASH 解决简单的效果,就不用劳烦特效部门了。

  不过 MASH 也是不争气,虽然有 Python API ,但是 Python API 居然也会有 BUG (:з」∠)

  我让他做了个小型可复现的 Demo 方便我去研究,大概的效果如下↓↓↓

alt

测试文件下载地址

MASH API 的问题

  网上搜索一下 MASH Python 就可以找到 API 文档了 链接

  MASH 的 API 也不复杂,比起 Pymel 来说简单多了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import MASH.api as mapi
import pymel.core as pm
mashNetwork = mapi.Network("MASH1")

min_time = pm.playbackOptions(q=1,min=1)
max_time = pm.playbackOptions(q=1,max=1)
for i in range(int(min_time),int(max_time)+1):
pm.currentTime(i,update=1)
mashNetwork.getCurrentFrameData()
loc_list = []
for pt in mashNetwork.position:
loc = pm.spaceLocator()
loc.t.set((pt[0],pt[1],pt[2]))
loc_list.append(loc)
pm.group(loc_list,n="frame_%s" % i)

  按照文档的用法,应该可以用 getCurrentFrameData 的方式更新对象内部的 position 数据。
  我使用 locator 进行位置可视化,可以看到生成的 locator 都是固定在原始位置上的。

alt

  位置信息没有根据动态进行更新。
  后面我只好去查 MASH.api 的代码看看是怎么实现。
  一查发现原来也是用 OpenMaya 获取对应节点信息的。

alt

  于是我用节点视图查看了一下节点连接获取的信息。

alt

  network 存储的 waiter 名称就是我们获取的 MASH1 节点。
  在节点视图下获取它的信息可能不是正确的,因为 BulletSolver 在 MASH1 后面。
  所以我打算获取 Repro 的信息,应该就是最终的数据。

  经过 pymel 的一番折腾,可以通过下面的代码获取 MASH 点的位置信息。

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
import MASH.api as mapi
from maya import OpenMaya
import pymel.core as pm

# NOTE 删除之前生成的 loc
pm.delete([grp for grp in pm.ls(assemblies=1) if grp.startswith("frame")])

data = {}
min_time = pm.playbackOptions(q=1,min=1)
max_time = pm.playbackOptions(q=1,max=1)
for i in range(int(min_time),int(max_time)+1):
pm.currentTime(i,update=1)

mashNetwork = mapi.Network("MASH1")
# NOTE 这个是 MASH1_Repro 节点
node = pm.PyNode(mashNetwork.instancer)
# NOTE 获取 MPlug 属性
obj = node.inputPoints.__apiobject__().asMObject()
inputPointsData = OpenMaya.MFnArrayAttrsData(obj)
positions = inputPointsData.getVectorData("position")

loc_list = []
# TODO 不能直接 for 循环 | 会导致 Maya 崩溃
for i in range(positions.length()):
pt = positions[i]
loc = pm.spaceLocator()
loc.t.set((pt.x,pt.y,pt.z))
loc_list.append(loc)
pm.group(loc_list,n="frame_%s" % i)
data[i] = mashNetwork.position
print (data)

alt

  这里通过 pymel 的方式获取到 OpenMaya1.0 的对象, pymel 的操作比较便捷,省去我很多前期的获取操作。
  得到 MASH1_Repro 下面就是获取节点内部的点信息。

alt

  inputPoints 是个复合属性,为了获取出 position 的数据还是折腾了好一会。
  后面是参照了 MASH API 的一些写法获取到了。
  最后获取到的顶点数据 positions 不能直接进行 for 循环遍历,会导致 Maya 崩溃。

  以上就是这次 MASH 获取顶点信息的踩坑过程。

总结

  垃圾Maya , 换上 Houdini 吧~