株式会社デジタル・フロンティア-Digital Frontier

Header

Main

マニアックリグ その1

2012/10/10

Tag: ,,

どうも、こんにちは。TDチームの石田(@1null4null)です。
なにを紹介しようか、scriptか、リグか、Mayaについてか、いろいろ迷いましたが
今回もマニアックなリグネタに走ろうかと思います。
 

まずは背景から

弊社のアニメーションツールはモーションビルダー(以下MB)を使用しております。
MayaからMBセットアップをするのですが、MayaからMBに持っていけない機能がたくさんあり毎回セットアップチームを悩ませています。とは言いつつガチガチにセットアップをして重くなってしまってはアニメーションがスムーズに付けられず、これまた困った事になります。なのでアニメーションの付けやすさ重視で簡易的に組んでいます。ではどうやっているのかと言うとですね、、、

話しが長くなるので今回はそういった事には触れず、、、期待してた方すみません(笑)
一つ、弊社のセットアップチームから質問があったMayaで組む機能の一つ「rivet」をどうやってMBに持っていけるのか、について紹介していこうと思います。
「rivet」ってなに?というお人は「rivet maya」でおググりください。簡単に説明するとMeshとかNurbsSurfaceの面にTransformNodeをピッタリくっつける機能です。

いきなりなのですが、結論からいうと持っていけません!!

うちの優秀なTDさんがMB用のpluginを作ってくださっていますが、今回はpluginでなく「簡易的」に大体でいいのでそれっぽいのを一つ考えました。使うか使わないかはセットアップデザイナーの判断に任せています(w
あくまでマニアックです^^

今回の目標

MayaのskinClusterとconstrainはMBに持っていけるので、この二つを利用してMBへ持っていける「rivetっぽい」を仕込みます。

説明

まずは下図のようなデータを用意しました。
smoothBindされているモデルです。(最後にサンプルデータのリンクがあるので参考にどうぞ)
一応、下図ではrivetがありますがこれはMayaだけにあるNodeで作られているのでMBに持っていけないrivetです。

では下図のバーテックスがどのような動きをするか見てみましょう。
ウェイトは下図の通り入っています。

さて、ここらへんで種明かしを、「l_jt02」のジョイントをグルグル回してみてください。
選択されたバーテックスの軌跡を意識しつつグルグルと、、、おお、なんだか球体が見えますよね?え?わからない?
こんな感じです!!

smoothBindと言うものはどこかにある点を中心にバーテックスがグルグル回っているようなものなのです。
ここの中心点を探してあげてそこにTransformNodeを配置してジョイントと同じ回転をさせてあげればバーテックスのポジション(だいたい)が取れちゃうというわけなのです。

でも今回この方法で組むために条件があります。
バーテックスにウェイトが二つしか入らないことが条件です。頑張れば三つ四ついけると思いますがそこは割愛。
正直言いますと、時間がないので今後に期待。

中心点の取り方

しょうもないコードですがscriptを書きました。
使い方法は
バーテックスを選ぶ > 一番近いジョイントを選ぶ > scriptEditerで下記実行

なにをやっているか簡単に説明しますと
選択したジョイントとバーテックスの距離を出して、それにskinClusterのウェイト(選択したジョイントの)を乗算しているだけです。
そうすると中心が見つかります。
もちろん三つ以上ウェイトが入っているとずれます。地味にずれます。えへへ^^

import maya.cmds as cmds
import math
 
def main():
    sel = cmds.ls(sl=1)
    jt = cmds.ls(sel,type='joint')[0]
    vtxs = []
    for vtx in cmds.ls(sel,fl=1):
        if 'vtx' in vtx:vtxs.append(vtx)
    for vtx in vtxs:
        sc = get_skinCluster(vtx)
        vls = cmds.skinPercent(sc,q=1,v=1)
        infDic = {}
        for i,inf in enumerate(cmds.skinCluster(sc,q=1,inf=1)):
            infDic[inf]=vls[i]
 
        vtxPos = cmds.pointPosition(vtx)
        jtPos = cmds.xform(jt,q=1,ws=1,t=1)
        X = 0
        Y = 0
        Z = 0
        if jtPos[0] > vtxPos[0]:X = 1
        if jtPos[1] > vtxPos[1]:Y = 1
        if jtPos[2] > vtxPos[2]:Z = 1
        sp = get_pos(vtxPos,jtPos,1-infDic[jt],X,Y,Z)
 
        loc = cmds.createNode('transform',n='skinVtx_Pos#')
 
        cmds.setAttr(loc+'.t',jtPos[0]+sp[0],jtPos[1]+sp[1],jtPos[2]+sp[2])
        cmds.orientConstraint(jt,loc)
 
        vtxloc = cmds.createNode('transform',n='skinVtx#')
        vtxlocSp = cmds.createNode('locator',n='skinVtxShape#',p=vtxloc)
        cmds.setAttr(vtxloc+'.t',vtxPos[0],vtxPos[1],vtxPos[2])
        cmds.parent(vtxloc,loc)
 
def get_pos(p1=[],p2=[],v=0,X=0,Y=0,Z=0):
    x = (p2[0] - p1[0])
    y = (p2[1] - p1[1])
    z = (p2[2] - p1[2])
    if X:x = -1*math.sqrt(x*x)*v
    else:x = math.sqrt(x*x)*v
    if Y:y = -1*math.sqrt(y*y)*v
    else:y=math.sqrt(y*y)*v
    if Z:z=-1*math.sqrt(z*z)*v
    else:z=math.sqrt(z*z)*v
    return [x,y,z]
 
def get_skinCluster(vtx):
    sc = cmds.ls(cmds.listHistory(vtx),type='skinCluster')[0]
    if sc: return sc
    else : return None
main()

上記のscriptを実行しますと「skinVtx_Pos」というグループが出来ますので選択したジョイントの親に子付してあげれば「rivetっぽい」の完成です。
実はこれには欠点がありましてrivetはFaceのNormal方向にはちゃんと向いてくれるのですがこれは向きません。
しかもこれ面じゃなくて点ですね。
でも簡易的なセットアップなので大体でいいのです!!たぶん…^^
頑張ればなんとかなる!!

簡単ではありますが以上で説明は終わりです。

次回はその2へ、と続きたいところですがネタは思い付いていません(笑
使えそうで使えないリグネタはまだまだありそうなので頑張って続けていきたいと思います!!

<<サンプルデータ>>
skinCnst.mb (zip)

※注意※ 本記事内でダウンロード可能なサンプルシーンを使用したことによって引き起こるいかなる損害も
当方は一切責任を負いかねます。自己責任でご使用くださいませ。

Pocket

コメント

コメントはありません

コメントフォーム

コメントは承認制ですので、即時に反映されません。ご了承ください。

*