花粉がつらくなってきたので、引き籠ってmayaの環境を整えよう。
さてさて前回はメニューバーにツールを登録したわけで、今回は少しリグっぽい事を進めようかと。
リグを組むにあたって必要なものは膨大にありますが、ビジュアル面だとコントローラー(マニュピレーター)の見た目。
コントローラーの見た目をどう作るか
- nurbsCurveで作成
- nurbsSurfaceで作成
- カスタムロケーターで作成
まぁ色々ありますね。
カスタムロケーター
プラグインを作らねばならぬと・・・・
ちょっと今の自分にはハードル高めなので、未来への遺産としてメモ
nurbsCurveで作成 nurbsSurfaceで作成
この辺を参考にしてみれば、作れますね。
とりあえず nurbsCurveで作る事にします。
形状の取得
nurbsCurveで色んな形状つくりたいですが、いきなりコマンドから作るのは難しいので
- まず手動で作成
- 作成したカーブの形状情報を取得
- 形状情報を元に再現する
という流れで。
形状情報を元に再現する為に必要な情報を調べる為に、
OpenMaya.MFnNurbsCurve.create()
を調べてみる
cvs, knots, degree, form, is2D, rational, parent.....
なるほど。
-
cvs(CVの位置情報)
既存のnurbsCurveからCVの位置を取得したい。
眺めているとそれっぽいものを発見。
OpenMaya.MFnNurbsCurve.cvPositions()
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetCvPositions = FnShape.cvPositions(om.MSpace.kWorld)
MPointで返ってくるのか・・・・
もし [[x,y,z],[x,y,z].....]な感じのarrayで返ってきてほしいなら
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetCvPositions = []
for position in FnShape.cvPositions(om.MSpace.kWorld):
targetCvPositions.append(list(position)[:3])
と、こんな感じかしら。
-
knots
既存のnurbsCurveからknotを取得したい。
眺めているとそれっぽいものを発見。
OpenMaya.MFnNurbsCurve.knots()
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetKnots = FnShape.knots()
ok 取れた。
※以前は取得の方法が判らなかったので、生成時にknotsも別途算出して生成してました。
- degree と form
OpenMaya.MFnNurbsCurve.degree
OpenMaya.MFnNurbsCurve.form
はい。
一旦まとめると
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetCvPositions = FnShape.cvPositions(om.MSpace.kWorld)
targetKnots = FnShape.knots()
targetForm = FnShape.form
targetDegree = FnShape.degree
is2D, rational, parent この辺は今はいらないので無視。
形状の作成
取った情報からOpenMaya.MFnNurbsCurve.create()が実行できるかやってみる。
空のMFnNurbsCurveを作ってcreate
target = "curve1"
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetCvPositions = FnShape.cvPositions(om.MSpace.kWorld)
targetKnots = FnShape.knots()
targetForm = FnShape.form
targetDegree = FnShape.degree
NewFnShape = om.MFnNurbsCurve()
NewFnShape.create(targetCvPositions, targetKnots, targetDegree, targetForm, False, False)
形状情報のdict化
過去に作った形状をいつでも呼び出せるように、形状情報をdict化して呼び出せるようにしておく。
形状情報を取得してprint
import maya.api.OpenMaya as om
target = "curve1"
sellist = om.MGlobal.getSelectionListByName(target)
dagPath = sellist.getDagPath(0)
FnShape = om.MFnNurbsCurve(dagPath)
targetCvPositions = FnShape.cvPositions(om.MSpace.kWorld)
targetKnots = FnShape.knots()
targetForm = FnShape.form
targetDegree = FnShape.degree
targetInfoDict = {
"cvs":targetCvPositions,
"knots":targetKnots,
"form":targetForm,
"degree":targetDegree
}
print targetInfoDict
arrowって名前にしましょう
curveShapeDict = {
"arrow":{'knots': maya.api.OpenMaya.MDoubleArray([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]), 'cvs': maya.api.OpenMaya.MPointArray([maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(-0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0, 0, 0.5, 1), maya.api.OpenMaya.MPoint(0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1)]), 'form': 1, 'degree': 1}
}
import maya.api.OpenMaya as om
def createCurveShape(shapeName):
curveShapeDict = {
"arrow":{'knots': maya.api.OpenMaya.MDoubleArray([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]), 'cvs': maya.api.OpenMaya.MPointArray([maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(-0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0, 0, 0.5, 1), maya.api.OpenMaya.MPoint(0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1)]), 'form': 1, 'degree': 1}
}
NewFnShape = om.MFnNurbsCurve()
NewFnShape.create(is2D = False,rational =False,**curveShapeDict[shapeName])
createCurveShape("arrow")
あれ?上手く行かない。エラー出る。
# Error: TypeError: file <maya console> line 9: Required argument '' (pos 1) not found #
うーんちょっと眠くて考えるのが面倒だから、
import maya.api.OpenMaya as om
def createCurveShape(shapeName):
curveShapeDict = {
"arrow":{'knots': maya.api.OpenMaya.MDoubleArray([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]), 'cvs': maya.api.OpenMaya.MPointArray([maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(-0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0, 0, 0.5, 1), maya.api.OpenMaya.MPoint(0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1)]), 'form': 1, 'degree': 1}
}
NewFnShape = om.MFnNurbsCurve()
NewFnShape.create(
curveShapeDict[shapeName]["cvs"],
curveShapeDict[shapeName]["knots"],
curveShapeDict[shapeName]["degree"],
curveShapeDict[shapeName]["form"],
False,
False
)
createCurveShape("arrow")
はい、再現できた。
shapeだけ作ってtransformノードは自動でなので、transformノードを返すようにしようか。
dictを内包するのはちょっと違う気もするので、これも外に移動。
単純にcurveだけを作るようにしてしまうとこんな感じかしら
import maya.api.OpenMaya as om
def createCurveShape(cvs,knots,degree,form):
NewFnShape = om.MFnNurbsCurve()
NewFnShape.create(cvs,knots,degree,form,False,False)
return NewFnShape.parent(0)
def createCtrlNode(shapeName,nodeName):
curveShapeDict = {
"arrow":{'knots': maya.api.OpenMaya.MDoubleArray([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]), 'cvs': maya.api.OpenMaya.MPointArray([maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(-0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0, 0, 0.5, 1), maya.api.OpenMaya.MPoint(0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1)]), 'form': 1, 'degree': 1}
}
ctrlNode = createCurveShape(**curveShapeDict[shapeName])
dgModifier = om.MDGModifier()
dgModifier.renameNode(ctrlNode, nodeName)
dgModifier.doIt()
return ctrlNode
createCtrlNode("arrow","hoge_ctrl")
これだとサイズが指定できないので、サイズも指定できるようにしておこうかと思います。
import maya.api.OpenMaya as om
def createCurveShape(cvs,knots,degree,form):
NewFnShape = om.MFnNurbsCurve()
NewFnShape.create(cvs,knots,degree,form,False,False)
return NewFnShape.parent(0)
def createCtrlNode(shapeName,nodeName,size):
curveShapeDict = {
"arrow":{'knots': maya.api.OpenMaya.MDoubleArray([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]), 'cvs': maya.api.OpenMaya.MPointArray([maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(-0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0, 0, 0.5, 1), maya.api.OpenMaya.MPoint(0.30000001192092895508, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, 0.19999998807907104492, 1), maya.api.OpenMaya.MPoint(0.10000002384185791016, 0, -0.5, 1), maya.api.OpenMaya.MPoint(-0.099999994039535522461, 0, -0.5, 1)]), 'form': 1, 'degree': 1}
}
ctrlNode = createCurveShape(**curveShapeDict[shapeName])
dgModifier = om.MDGModifier()
dgModifier.renameNode(ctrlNode, nodeName)
dgModifier.doIt()
cmds.xform(om.MFnDagNode(ctrlNode).fullPathName(), scale = [size,size,size], ws = True)
cmds.makeIdentity(om.MFnDagNode(ctrlNode).fullPathName(), a =True, r=True, s =True)
return ctrlNode
createCtrlNode("arrow","hoge_ctrl",1.0)
xformのところがなんか不細工なので、なんとかしたいなぁ・・・・
とここでundoがおかしい。
というかundoできない。
はて?
openmaya for Python API では、undo・redo機能は提供されていません。
そもそも処理したことが待ち行列にスタックされないため、undoを行っても
openmaya for Python APIを実行する前の履歴が実行され、処理したことはそのまま残り続けます。
おー・・・・・どおりで。
変えましょう。
import maya.api.OpenMaya as om
def createCurveShape(cvs,knots,degree,form):
periodic = False
if form == 3:
periodic = True
curve = cmds.curve(point = cvs, knot = knots, degree = degree,periodic = periodic)
return curve
def createCtrlNode(shapeName,nodeName,size):
curveShapeDict = {
"arrow":{'knots': [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 'cvs': [[-0.09999999403953552, 0.0, -0.5], [-0.09999999403953552, 0.0, 0.19999998807907104], [-0.30000001192092896, 0.0, 0.19999998807907104], [0.0, 0.0, 0.5], [0.30000001192092896, 0.0, 0.19999998807907104], [0.10000002384185791, 0.0, 0.19999998807907104], [0.10000002384185791, 0.0, -0.5], [-0.09999999403953552, 0.0, -0.5]], 'form': 1, 'degree': 1}
}
ctrlNode = createCurveShape(**curveShapeDict[shapeName])
ctrlNode = cmds.rename(ctrlNode,nodeName)
cmds.xform(ctrlNode, scale = [size,size,size], ws = True)
cmds.makeIdentity(ctrlNode, a =True, r=True, s =True)
return ctrlNode
createCtrlNode("arrow","hoge_ctrl",1.0)
はい undo 効くようになりました。
GUIはまぁ適当に作っていこう。