当前位置:   article > 正文

blendShape节点与OpenMaya编辑方法_maya bs

maya bs

本文介绍的是Maya中blendShape的底层原理,并总结了一些通过Python代码编辑blendShape的方法。代码库为cmds和openMaya。注意,阅读本文需要一定的编程基础。

一、blendShape节点属性介绍

在“窗口>>节点编辑器”中打开节点编辑器,按下“Tab”并输入“blendshape”创建一个完全无数据的空blendShape;右键按住并移动到“显示所有属性”一栏再松开,可以看到节点的所有属性;可以点击名称处修改它的名字。

在节点编辑器中创建blendShape

可以看到BS节点中的属性有很多,但重点只有四个,我们使用上一节中“在形变编辑器中创建blendShape“的方法创建好BS后,右键点击“在节点编辑器中查看”选项,可以看到系统为您连好的BS节点。

  1. 原始几何体

原始几何体用来获取该BS的初始形状,与“pSphereShape1Orig”链接代表该BS从网格“pSphereShape1”的Orig节点中获取初始形状。(Orig节点是网格的原始节点,记录网格的最原始的数据,可能不与显示在窗口中的形状相同。)

  1. 输出几何体

BS将修改后的形状通过“输出几何体”属性输出,与“pSphereShape1”链接代表形变后的形状会赋予给“pSphereShape1”,使该网格显示在窗口中的形状发生改变。(不带后缀的节点是网格的显示节点,用来记录网格显示在窗口中的形状数据,即我们看到的形状。)

  1. 权重

一个BS中可能包含多个目标形状,这些形状的权重值和名字就记录在权重当中,由于大部分时候我们不会改变权重的大小,所以我通常使用该属性方便的遍历BS的目标形状名称、获取BS的目标形状数量。

  1. 输入目标

输入目标中包含的信息最多我们重点关注:输入目标[x],输入点目标,输入组件目标。每个输入目标[x]都代表一个目标网格;“输入点目标”中记录的是该目标网格会影响的点的ID;“输入组件目标”中记录的是该目标网格会影响的点的位移量。因此,我们可以通过改变这些数据实现快速批量控制BS。

图四:BS输入目标属性表

二、使用OpenMaya编辑BS

我尝试了cmds、mel、pymel、OpenMaya等库与语言后,选择了OpenMaya来实现BS的编辑,因为cmds、mel、pymel都是调用OpenMaya来实现BS的编辑,速度慢不说,可实现的功能也不多。因此,使用OpenMaya改写blendShape节点可以说是最优解,且AutoDesk官方给出了API,学习起来也很方便。

这里我将介绍,通过OpenMaya创建BS的目标网格的方法、通过OpenMaya修改BS的目标网格的方法。

首先要导入OpenMaya库,获取BS节点,在创建目标形状,最后给入形变数据。

  1. import maya.OpenMaya as OM
  2. # BS的名称
  3. BSName = "blendShape1"
  4. # 获取OpenMaya中的BS节点
  5. # OpenMaya中的BS节点为MFnDependencyNode
  6. BSNodeObj = OM.MObject()
  7. sel = OM.MSelectionList()
  8. sel.add(BSName, 0)
  9. sel.getDependNode(0, BSNodeObj)
  10. dgFn = OM.MFnDependencyNode(BSNodeObj)
  11. # 使用plug获取节点中的属性
  12. # findPlug('inputTarget')为图四中的输入目标接口
  13. # elementByLogicalIndex是Mplug的函数,用来返回plug的逻辑节点的元素,如果找不到,就创建它。此处的elementByLogicalIndex(0)代表输入目标[0]
  14. # child(0)返回的值为“输入目标[0]-输入目标组”
  15. plug = dgFn.findPlug('inputTarget').elementByLogicalIndex(0).child(0)
  16. # ------------------------------------------------------------------
  17. # 下面的函数用来创建一个新的目标形状,值得注意的是其中有个值为6000的逻辑地址,
  18. # 它根据该目标网格的权重值得到,6000=w*1000+5000
  19. tarId = 0
  20. tarName = "testTarName"
  21. # create target
  22. custPlug.elementByLogicalIndex(tarId).asMObject()
  23. custPlug.evaluateNumElements()
  24. # create LogicalIndex6000 on the target
  25. input_target_item_mPlug = custPlug.elementByLogicalIndex(tarId).child(0)
  26. input_target_item_mPlug.elementByLogicalIndex(6000)
  27. input_target_item_mPlug.evaluateNumElements()
  28. # create weight of the target
  29. weight_mPlug = custDgFn.findPlug("weight", False)
  30. weight_mPlug.elementByLogicalIndex(tarId).asFloat()
  31. weight_mPlug.evaluateNumElements()
  32. # assign the name to the new target
  33. cmds.aliasAttr(tarName, '{}.w[{}]'.format(BSName, tarId))
  34. # ------------------------------------------------------------------
  35. # 下面的函数用来给入BS形变数据
  36. # points记录顶点delta数据,可以完全自定义,形如:[ [0,0,0] , [1,1,1] , [0,0,1] ]
  37. # indices记录delta数据对应的顶点ID, 长度要与points一致,形如:[ 0,1,3 ]
  38. points = [ [100] , [111] , [001] ]
  39. indices = [ 0,1,3 ]
  40. # 将列表转换成MObject类型的数据
  41. point_list = OM.MPointArray()
  42. index_list = OM.MIntArray()
  43. # get point_list
  44. for pointDelta in points:
  45. point = OM.MPoint(pointDelta[0], pointDelta[1], pointDelta[2], 1.0)
  46. point_list.append(point)
  47. # writes the delta data in the inputPointsTarget plug
  48. dg_pointArray_fn = OM.MFnPointArrayData()
  49. dg_pointArray_data = dg_pointArray_fn.create(point_list)
  50. plug.elementByLogicalIndex(tarId).child(0).elementByLogicalIndex(6000).child(3).setMObject(dg_pointArray_data)
  51. # get index_list
  52. for index in indices:
  53. index_list.append(index)
  54. # initializes function sets, needed to create the MObjects and set their data
  55. dg_component_fn = OM.MFnComponentListData()
  56. dg_component_data = dg_component_fn.create()
  57. singleComponent_fn = OM.MFnSingleIndexedComponent()
  58. singleComponent_data = singleComponent_fn.create(OM.MFn.kMeshVertComponent)
  59. singleComponent_fn.addElements(index_list)
  60. dg_component_fn.add(singleComponent_data)
  61. plug.elementByLogicalIndex(tarId).child(0).elementByLogicalIndex(6000).child(4).setMObject(dg_component_data)
  62. # ------------------------------------------------------------------
  63. # 至此,一个完全自定义的目标形状就创建完了,提醒一下BS数据,可以直接从现有BS中获取,
  64. # 且不必转换来转换去的,还麻烦

参考链接:

1、OpenMaya API链接:

https://help.autodesk.com/view/MAYAUL/2023/CHS/?guid=MAYA_API_REF_py_ref_namespace_open_maya_html

2、外网参考

https://groups.google.com/g/python_inside_maya/c/_GiD2R89Dqg

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/418542
推荐阅读
相关标签
  

闽ICP备14008679号