3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

mayaの環境を構築していく 8日目

Posted at

花粉がつらくなってきたので、引き籠って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()が実行できるかやってみる。

適当なnurbsCurveを用意
image.png

空の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)

はいできた
image.png

形状情報のdict化

過去に作った形状をいつでも呼び出せるように、形状情報をdict化して呼び出せるようにしておく。

再現したい形状を手動で作成
image.png

形状情報を取得して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")

はい、再現できた。

image.png

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はまぁ適当に作っていこう。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?