【笔记】【Maya工具】Python For Maya(OpenMaya)(四)Locator & CallBack for IK

一、Creating Custom Locator

maya提供标准locator定位器,我们也可以自定义定位器

  1. Draw/Define a shape(Opengl-function->MGLFunctionTable)
  2. Define a Bounding Box?
    1. isBounded()
  3. Define size of Bounding Box(Size of the locator)
    1. boundingBox()

1.1 Locators

  • MPxLocatorNode

    • draw()
    • isBounded()
    • boundingBox()
  • MGLFunctionTable

    • 为OpenGL的api提供了包装器
    • 我们不用自己进行实例化,只需要获取maya中的一个指针
    • MHardwareRenderer() <<OpenMaya Render\
    • ptr = OpenMayaRender.MHardwareRenderer.theRenderer()
    • ptr link to HardwareRenderer
      • glFunctionTable()->Opengl functions

1.2 实现结果

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#locators.py
import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaRender as OpenMayaRender


nodeName = "LeftFoot"
nodeId = OpenMaya.MTypeId(0x100fff)

# ptr to gl function table
glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
glFT = glRenderer.glFunctionTable()



class LocatorNode(OpenMayaMPx.MPxLocatorNode):

def __init__(self):
OpenMayaMPx.MPxLocatorNode.__init__(self)
def compute(self, plug, dataBlock):
return OpenMaya.kUnknownParameter
def draw(self, view, path, style, status):# drawing View,dagpath,(wireframe...)
view.beginGL()#这里的opengl依然是状态机

# Pushed current state
glFT.glPushAttrib(OpenMayaRender.MGL_CURRENT_BIT)

# Enable blend mode(to enable transparency)
glFT.glEnable(OpenMayaRender.MGL_BLEND)

# Defined Blend function
glFT.glBlendFunc(OpenMayaRender.MGL_SRC_ALPHA, OpenMayaRender.MGL_ONE_MINUS_SRC_ALPHA)

# Define colors for different selection modes
if status == view.kActive:
glFT.glColor4f(0.2, 0.5, 0.1, 0.3)
elif status == view.kLead:
glFT.glColor4f(0.5, 0.2, 0.1, 0.3)
else:# status == view.kDormant:
glFT.glColor4f(0.1, 0.1, 0.1, 0.3)

# Draw a shape
glFT.glBegin(OpenMayaRender.MGL_POLYGON)
glFT.glVertex3f(-0.031, 0.0, -2.875)
glFT.glVertex3f(-0.939, 0.1, -2.370)
glFT.glVertex3f(-1.175, 0.2, -1.731)
glFT.glVertex3f(-0.60, 0.3, 1.060)
glFT.glVertex3f(0.473, 0.3, 1.026)
glFT.glVertex3f(0.977, 0.2,-1.731)
glFT.glVertex3f(0.809, 0.1, -2.337)
glFT.glVertex3f(0.035, 0.0, -2.807)
glFT.glEnd()

glFT.glBegin(OpenMayaRender.MGL_POLYGON)
glFT.glVertex3f(-0.587, 0.3, 1.33)
glFT.glVertex3f(0.442, 0.3, 1.33)
glFT.glVertex3f(0.442, 0.3, 1.92)
glFT.glVertex3f(0.230, 0.3, 2.24)
glFT.glVertex3f(-0.442, 0.3, 2.25)
glFT.glVertex3f(-0.635, 0.3, 1.92)
glFT.glVertex3f(-0.567, 0.3, 1.35)

glFT.glEnd()

if status == view.kActive:
glFT.glColor4f(0.2, 0.5, 0.1, 1)
elif status == view.kLead:
glFT.glColor4f(0.5, 0.2, 0.1, 1)
else:# status == view.kDormant:
glFT.glColor4f(0.1, 0.1, 0.1, 1)
view.drawText("Left Foot", OpenMaya.MPoint(0,0,0), view.kLeft)
# Disable Blend mode
glFT.glDisable(OpenMayaRender.MGL_BLEND)

# Restore the state
glFT.glPopAttrib()

view.endGL()



def nodeCreator():
return OpenMayaMPx.asMPxPtr(LocatorNode())

def nodeInitializer():
pass


# 初始化,和maya pluginCommand是一样的
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.registerNode(nodeName, nodeId, nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kLocatorNode)
except:
sys.stderr.write("Failed to register node:" + nodeName)

def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterNode(nodeId)
except:
sys.stderr.write("Failed to deregister node" + nodeName)



1
2
3
import maya.cmds as cmds
cmds.loadPlugin("D:\\Autodesk\\plugin\\locators.py")
cmds.createNode("LeftFoot")

有组件,但是无显示,查阅api后发现,其实这个有给出例程,但是也是分了api1.0和api2.0版本的,教程写的大概是api1.0版本,1.0在maya2023、python3.9.3版本上大概不能使用,因此只能后面参考api2.0版的例程了。

而后面的IK部分也是完全无法使用了,需要学习新版本的api。只能笔记记录下思路

二、Maya Callbacks

回调是一种链接方式,链接特定事件的特定函数,并时刻关注这个函数的发生

回调允许我们针对特定的事件注册该函数(和java中的listener、Oracle中的Trigger相似)

OpenMaya中基于事件类别,对回调进行了分类

基类【MMessage】,其他回调的类都是这个基类的派生类callback(event, function)

2.1 Message消息

  • Message[eg MAnim Message]

  • Message[eg MCommand Message]

2.2 Callback回调

  • Removable

  • Id(callback create)

  • MAnim Message

    • Animation Message Callback
      • animation curve editing
      • keyframe editing
      • baked result change
  • MCommand Message

    • Command Message Callback
      • MEL command excution
  • MDG Message

    • for Dependency Graph Message
    • Node added/removed
    • Connection established/removed
  • MDAG Message

    • for dependency Graph Message
    • (主要跟踪或检查dag节点的切换)
    • Parent/child/Instance/added/removed
  • Event Message

    • “script Job”
    • OpenMaya.MEventMessage.getEventNames()
  • Lock Message

    • for lock message
    • plug locked/unlocked
      • values cannot be changed
    • Node locked/unlocked
      • cannot Re-parented/Renamed/deleted
  • Node Message

    • for Dependency Node Message
    • Attribute added/removed
    • plug of a Node is dirty
    • name of a Node is changed
  • Scene Message

    • Scene related Message
    • Before/After
      • New scene
      • Existing scene
      • Reference is loaded/unloaded
      • Maya is initialized/exist
  • Timer Message

  • UI Message

  • User-event message

三、Inverse-Forward Kinematics Solution

在这个插件中使用回调将IK和FK的功能结合起来

  • FK mode

    • 移动父节点,驱动子结点
  • IK mode

    • 移动子节点,在约束的条件下,自动解算父节点位置
  1. 在IK和FK中切换
    1. 选择polar vector/IK handle/子结点关节时,IK mode
    2. 选择任意一个父节点关节时,FK mode
  2. 施加约束

Custom-Node (IK FK)<-> Event Callback <-> Selection Change

Custom-Node (delete)<->DG Callback <-> addition/creation/deletion the DG nodes

Creating I-F K solution

Auto IK-FK Switching

  1. Find out which “Mode” we want to switch to
  2. Find information of all seven objects of 3-joint chain IK-system
  3. Perform operation based on the “Mode” we are at

image-20220705144129456

我这里暂时没有poleVectorControl

默认Mode =FK(joint1,joint2)

  • Mode = IK
    1. IK -Handle selected
    2. Joint3 selected
    3. Pole-vectorcontrol selected

image-20220705201445310

  • If Mode = FK

    1. set ikBlend = 0
    2. set visibility of Pole Vector Control = 0
  • If Mode = IK

    1. set ikBlend = 1
    2. snap Pole Vector Control to Joint2
  • set attribute of IK handle to non-Keyable

  • ikBlend

  • ikBlend- non-Keyable

  • Add translation after snapping Pole Vector Control