« 平べったい目のリグ2 | Main | スクリプトを書いてみた2 »

September 08, 2013

スクリプトを書いてみた

こちらのブログ(気まぐれに(仮) 3DCG Blender)を見て、クロスシミュの結果をボーンに
コピーするのも面白そうと思い、手作業でスカートやボーンを作り始めたのですが、すぐにかなり
膨大な単純作業の繰り返しが待っていることに気づき(笑)少しでも楽をしたいので、スクリプト
に手を出してみました。

python自体初めてだしAPIやBlenderローカルの作法など何も知らないわけなので
悪戦苦闘。昔は無印Cでゲーム作ったり、Shadeのスクリプト書いたりしてたんですが、
とくに作法を覚えるまでが面倒くさいんですよね。年なもんでなかなか入ってこないしw

そんな中、
matoさんのぶろぐ凹みTips情報処理 I - 第15回:Python による Blender の制御
といった、とてもわかりやすくて有難い入門記事を参考にさせていただき、どうにかこうにか
「選択した頂点座標にVertexの子のEmptyとそのEmptyをCopy locationしたBone(Armature)を
生成する」スクリプト第1号と、「選択頂点のウエイトを設定し、それ以外のウエイトは0にする」
スクリプト第2号ができたのであります。

探せば他によほど便利な機能やスクリプトがごろごろとあるのでしょうが、まあ、なにぶん勉強
ということで。
今回はサンプル動画が多くなったんで、一本にまとめてYoutubeにアップしました。

↑の動画にあるようにまずはVertexと連動するボーンをスカートの全頂点に生成しなければならない
わけですが、なにせPythonいじって一日目、選択したオブジェクト内の全頂点上に一発で生成しちゃうよーん
な気の利いたものはできるはずもなくw編集モードに入って一個だけVertexを選択してスクリプトを実行
すると1組のEmptyとBoneを作って編集モードに帰ってくるまでという、切手を貼る作業がスタンプを押す程度
の効率アップでしかないわけですが、それでもこれがあると無いとでは大違い。

全頂点を手作業で選択しなければならないわけで、その過程でカーソルスナップして、オブジェクトモードに
してEmptyをVertexペアレントしてbone追加してCopyLocationコンストレイント設定してまた編集モードに
戻って…これを(そんなに多くは無いにしろ)全頂点分繰り返すなんてしていたらきっと発狂していたことでしょう:-)

で、そのスクリプトがこれ↓

################################################################
#Add a child Empty and a Bone with copy location constrait to that
# at a point of selected vertex
#
# Use in edit mode after select a vertex
################################################################

#!BPY
import bpy

list = ['PLAIN_AXES','ALLOWS','CIRCLE','CUBE']
emptytype = list[2]
emptysize = 0.3
pi = 3.14

scn = bpy.context.scene

bpy.context.area.type = 'VIEW_3D'
bpy.context.object
bpy.ops.view3d.snap_cursor_to_selected()

bpy.ops.object.mode_set(mode='OBJECT')
obj = scn.objects.active

bpy.ops.object.armature_add(view_align=False, enter_editmode=False, rotation=(0,pi,0))
amtr = scn.objects.active

bpy.ops.object.empty_add(type=emptytype)
bpy.context.object.scale = (emptysize, emptysize, emptysize)

ept = scn.objects.active
ept.select = True

scn.objects.active = amtr
bpy.ops.object.posemode_toggle()

amtr.select = True

bpy.ops.pose.constraint_add_with_targets(type='COPY_LOCATION')
bpy.ops.object.posemode_toggle()

scn.objects.active = obj

bpy.ops.object.editmode_toggle()
bpy.ops.object.vertex_parent_set()
bpy.ops.object.editmode_toggle()


ept.select = False

scn.objects.active = obj
obj.select = True
bpy.ops.object.editmode_toggle()

bpy.context.area.type = 'TEXT_EDITOR'

############################################################

↑スクリプトここまで

出鱈目な英語はともかくとしても、
***.select = True だけでは選択のフォーカス移動が実行されないのに小一時間
悩んだり、bpy.ops.view3d.snap_cursor_to_selected()がいくらやっても動作せず、
結局テキストエディターのエリアタイプを一旦3DViewにするというまことに怪しげ
な方法で回避してみたりと、無駄も多いわけのわからんものになっている
と思われますが、まあ我が家にはどんなにスパゲッティなプログラムでも
動かないよりはましという家訓があるので問題ありません:-)


実際には該当するオブジェクトを選択し、編集モードで頂点を1個選択した
ところでスクリプトを実行します:-)

で、次にやることはVertexの動きをBoneのキーフレームに落とす作業ですが、
上のスクリプトではBoneがそれぞれ別オブジェクトになっていて、これでは
Boneを使う意味があまりなくなるので、まず一つのArmatureにまとめます。

とりあえず体のメインとなるArmatureは一旦隠すなりして、Shift+G→Type等で
スカートのBone全体を一括選択してCtrl+J、その後メインのArmatureにさらに
Ctrl+Jして一体化。

これをやってもVertexを親に持つEmptyをCopyLocationしたコンストレイントは
そのまま保持しているので、まとめたArmatureを選択しPoseモードでスカートのBoneを
選択、スカートがクロスシミュで動いているのを確認しつつ3フレームおきにキーを打ち
ました。

ここで注意しなければならないのは通常のLocationやLocRotでキーを打つのは
スカートのオブジェクト自体が動いているわけではないので意味がなく、必ず
Visual Locationなり、Visual LocRotで打たなければならない点ですね:-)

この場合、タイムラインの録画ボタンの横でVisual Location等を選んでおき、3フレーム
カーソルキーで送るごとにその横の鍵ボタンを押すと結構楽です。

Skt03

まあ、本来ならnフレームごとに手作業で打つのなんてものこそスクリプトの出番と
思われるわけですがヽ(^o^;)ノ

打ち終わったらBoneのCopyLocationのターゲットだったEmptyをShift+G→Type等で
選択して一括削除。これでリレーションのループエラーが解消されます。ただしボーンに
コンストレイントの残骸が残りますが…これが気になる場合は手作業でひとつひとつ
削除を…w

で、スカートの物理演算関係のデータは必要ないのでClothを削除。体に施してあった
足のCollisionもついでに削除。

スカートがもとの形になったら、ArmatureをRestPositionにしてスキニング。
とりあえずWeightづけをAutomatic Weightでやってみたところ、少々動きが甘くなり、
質感も硬い感じに。(動画の中盤あたり参照)
さらにもとの形状より痩せることが多く、足が突き抜けたりするフレームが多くなり、
修正が面倒でした。ただ、それでもBoneの位置を修正するだけなので、作業自体は
簡単ですが。

これを解消し、もとのclothシミュの動きに近づけるにはやはり、スカートの各boneを
対応するVertexのみに作用するようにウエイトを修正しなければならないでしょう。

というわけで、スクリプトに味をしめた私はウエイトづけもちょっと楽にしようと、簡単な
スクリプトを作成。Weight PaintモードでBoneを選択し、編集モードに入って、そのBone
の位置の(人力選択した)VertexだけにWeightを設定、他は全部removeするというものです。

スクリプトを使わなくても最近のBlenderの進化は油断がならないので、あっさりそんな
ことはできるようになっているのかもしれない不安は他所に置き、これまた全頂点の
ウエイトをこつこつとスクリプトを使いながら修正。

そのスクリプトがこれ↓です。

#############################################
#set weight to selected vertex only
#
#useage: First, select a bone
# on wightpaint mode and into editmode ,
# select verticies to set weight.
##############################################

#!BPY
import bpy

bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.object.vertex_group_remove_from()
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.object.vertex_group_assign()
bpy.ops.object.mode_set(mode='WEIGHT_PAINT')

############################################################

↑スクリプトここまで

これも本来なら一発でBoneに近いVertexに自動的にウエイトづけするかっこいいスクリプト
が理想でしょうが…いまの僕にはこれが精一杯w

まあ、この程度ならBlenderを起動すると時々ハミパンのようにちらっと上に
見えたりすることがあるログコンソール?を眺めつつ、やりたい操作を
してみて、そこにAPIが表示された場合はそれを右クリックして反転したらコピー、
テキストエディタに貼り付けて、必要なら加工、表示されない場合は該当機能
にマウスをポイントして現れるツールチップの最後の奴を書いて動作確認、
動けばラッキーという感じで使えそうw

↑のスクリプトはこの両方を並べただけのものですが、それでも結構役にたったりします。
まあ、こうしたので少しずつ慣れていけばいいかな。

Shadeの場合は録画ボタンを押すと必要なスクリプトが丸ごと記録されるんで、それを
加工してもっと簡単に利用できたんですが、できればそういう機能がBlenderにも欲しいなぁ…
どこかにそんなアドオンとかないのかなぁ…


閑話休題。
動画の後半で修正したものと、Clothシミュのものを並べてますが、3フレームおきのキー
でも結構動きがトレースされた感じになっているのではないでしょうか。


↓上掲動画のblendファイル(blender 2.68aで作成)

クロスシミュにBoneを追加した状態のファイル

skirt_by_clothsim.blend (1.3MB)

Skt01

Boneで動かしたファイル(ウエイト修正済み)

skirt_by_bone2.blend (2.5MB)

Skt02

各ファイルは良識の範囲でご自由にお使いください:-)

※ところで動画の足はどっちに向かって歩いているんでしょうか(^.^;右上と思い始めたら右上に、
左下だと思ったらずっと左下に見えてくる…w

|

« 平べったい目のリグ2 | Main | スクリプトを書いてみた2 »

Comments

The comments to this entry are closed.