2007年04月29日

ラティス変形のプログラムを作ってみよう その1 modo 203

さて、今回からラティス変形を教材にPythonスクリプトの解説を続けて行くよ。一応ラティスはほぼ完成したのでゴールも見えてるし、コードも今のところ140行程度なので、勉強には丁度いい感じだよ。ここで言うラティス変形は自分の想像で作ったものなので、他のラティス変形と仕様が多少異なるかも知れないことを先に断っておくよ。

さて、まず仕様を定めよう。

  • X,Y,Z軸それぞれ任意の距離をもつ直方体を各軸に沿って等間隔に任意回数分割した時に出来るすべてのエッジを2ポイントポリゴンで置き換えたオブジェクトをラティスとする。
  • ラティスは1つのアイテムとして任意の位置に任意のスケールと回転角度で配置され、変形対象となるメッシュオブジェクトの子としてペアレントされる
  • ラティスはX,Y,Zのサイズと分割数を入力してスクリプトで生成する
  • ラティスへの変位は、相対モーフで与える
  • 変位を設定されたラティスが囲んでいる親のメッシュポイントは、ラティスの変位に比例して変形される

ラティス変形手順とりあえず今あるスクリプトでラティス変形の手順を示したのが左のGIFアニメだ。変形を受ける方のメッシュにモーフマップを施す必要は無いんだけど、モーフにしておくと、スクリプトを実行するたびに変形が累積されないで、いろいろ試すのにもってこいだ。完成したらそのマップをメッシュに「モーフを適用100%」で変形しちゃえばいいしね。



そのへんの操作はパネルを作ってやると良さそうだね。ワークフローは追って考えていくことにしよう。

さて、まずはアイテムの扱いからやっていこう。今回のスクリプトはアイテムを切り替えたり、アイテムのプロパティを元に座標変換したり、いろんなことをしなくちゃならない。そのための下準備だ。
以前にレイヤーについてやった時に各レイヤーを識別する方法としてレイヤーインデックスと言う通し番号があるって書いた。レイヤーを操作する時にはそのインデックスで指定するのは以前やったわけだ。そしてやっぱりアイテムも操作するには対象を指定しなくちゃならないから、レイヤーインデックスみたいなものが必要なわけだ。それがアイテムIDで、レイヤーインデックスが単なる通し番号だったのに対して、こっちは名前と他と重複しない適当な番号が合わさった文字列になっている。こんな感じだ。

mesh_0E537B340F16

実はレイヤーにもレイヤーIDって言うのがあって、取得してみるとアイテムIDと同じものが出てくる。たぶんこの2つは名前が違っても同じものなんじゃないかと思う。

現在選択されているアイテムについてアイテムIDを取得する方法はいろいろあるよ。一番手っ取り早いのは、アイテムを選択するコマンドselect.itemを使う方法だ。選択するコマンドで選択しているアイテムを取得するってのはちょっと奇異な感じがするかもしれないけど、そこにmodoのコマンドの面白い規則があるから、是非覚えてね。

select.item ?item:&item <mode:{set|add|remove|toggle}>

これはselect.itemコマンドのヘルプを出したときに出てくるSyntaxの記述だ。selectitemの後ろに「:」付きで書かれたitemとmodeはこのコマンドに与えられるコマンドパラメータだ。<>で囲まれているmodeの方は省略可能だ。必須はitemだけで、その前に「?」マークが付いている。これが重要。このようにコマンドの記述で?が付いているパラメータはクエリー可能なパラメータと言い、設定するだけじゃなくて設定されているものを逆に聞き出すことが出来るってことになっている。だからアイテムを選択するってコマンドでその選択するパラメータを「?」にすれば、選択しているアイテムを訊ねるってことになるわけだ。だから現在選択されているアイテムを得るには、

select.item ?

でいいわけだ。でもこれはクエリーできるパラメータがひとつの時だけで、正確には、

select.item item:?

と、「パラメータ名:?」という形でどのパラメータをクエリーするのかちゃんと書く。

それから、複数のクエリー可能なパラメータを持ったコマンドの場合、クエリーの対象じゃないパラメータも埋めておかないとPythonでは上手く値が取得できないみたいなので、「パラメータ名:ダミーデータ」という形で何でもいいから並べて書いとかなきゃならないようだ。クエリーで使う限りはこれらのダミーデータは無視されるので何でもいいよ。
もちろんスクリプトから使うには、lx.evalN()メソッドを使ってmodoにコマンドを送り込む必要があるし、選択されているアイテムは1つとは限らないからlx.evel()じゃなくてlx.evalN()の方がいいよ。

と、ここまで書いといてナンだけど、このコマンドには欠点があって、選択されているアイテムは何でもリストに入れちゃう。今回の場合、対象としたいのはメッシュアイテムだけで、テクスチャーだとか、ライトだとかカメラだとかは含めたくないわけだ。そんな時にアイテムを取得してから選別するのも大変だ。もちろんそういう方法も取れるけど、今回は専用のクエリーを使うことにした。

query sceneservice selection ? アイテムタイプ

これがそのクエリー。前にやったクエリーはlayerserviceに問い合わせていたけど、アイテムについてはscenserviceに問い合わせる。このクエリーはシーン内で選択されているアイテムをクエリー出来る。その時のパラメータとしてアイテムタイプを指定できるので、メッシュアイテムだけに絞って現在選択されているものを取得出来るわけだ。ファンクション化するとこんな感じ。

def selItems(itype):
    return lx.evalN("query sceneservice selection ? %s" % itype)

ファンクション化する程のモンじゃないけどね。ファンクションの引数itypeに入れられるパラメータは、 locator , mesh , light , camera , render , environment , textureLayer だ。これらを文字列データとして与えてやる。メッシュアイテムなら"mesh"ね。これで必ずアイテムIDはタプルに入った形で得られる。その中から必要な奴を[インデックス番号]を使って取り出せばいいわけだ。

このようにして得られたアイテムIDを使えばこのアイテムの位置、回転、尺度、なんかが簡単にクエリー出来る。

アイテムの座標

query sceneservice item.pos ? アイテムID

アイテムの回転角度

query sceneservice item.rot ? アイテムID

アイテムの尺度

query sceneservice item.scale ? アイテムID

アイテムの回転マトリクス

query sceneservice item.matrix ? アイテムID

アイテムの逆回転マトリクス

query sceneservice item.matrixInvrs ? アイテムID

アイテムの親アイテム

query sceneservice item.parent ? アイテムID

アイテムの子アイテム

query sceneservice item.children ? アイテムID

これらのクエリーとselect.itemコマンドを使って、今回のスクリプトはアイテム操作をして行くことになる。

今回のまとめ

  • コマンドパラメータの記述でパラメータ名に?が付いているものはクエリー可能である
  • コマンドパラメータの記述で<>で囲まれているパラメータは省略可能である
  • アイテムの識別にはアイテムIDを使う
  • 現在選択されているアイテムのIDを取得するには「select.item?」を使うのがお手軽だが、テクスチャなどの余計なアイテムも取得されてしまう事がある
  • 種類を絞り込んで選択アイテムを取得したければ、sceneserviceへのクエリーを使うとよい

それではまた次回

スクリプトまとめページ( Down Load はこちらから)  

カテゴリー別ページ

modo操作メモ



take_z_ultima at 13:36│Comments(0)TrackBack(0)modo | CG

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives