« 脱退グループ。 | トップページ | 新プリミティブ降臨。 »

2012年1月17日 (火)

アップベクちゃんご主人様捜索。

こいつのアップベクタ先はどのオブジェクトだっけ? という話ですよ。



シーンが複雑になってきて、ボーンの Chain Up Vector 先のオブジェクトが行方不明ということはよくあります。 人から渡されたシーンならなおさらですね。 もちろんスケマティックビューで接続線の先を探すこともできますが、もしも接続先のスケマティックノードが畳まれている状態だったらその線は表示されませんし、畳まれていなかったとしても横に長~いスケマティックになっていたりすると線の接続先までたどり着くのは大変だし、そもそもスケマティックビューを使わないなどというふざけた若僧が多いわけです最近は。



そういうふざけた若僧を甘やかすつもりはまったくありませんが、ともかくもアップベクタ先を見つけるのがめんどくせえ。 そう思ってました。




もしもチェインアップベクタがいわゆるコンストレインの種類であれば、Constrain > Select Constraining Objects で一発で選択できるし、スクリプティング的にも Constraint オブジェクトの Constraining プロパティからたどり着けます。 でもチェインアップベクタって、コンストレインじゃないんですよね。オペレータです。



↓Explorer で見ても、歯車アイコンですよね。歯車アイコンはオペレータです。 ICEオペレータとかと同じ。

Upv1

Kinematic Joint プロパティの下に存在するオペレータです。



俺、このオペレータというやつをよく分かってなくて、今までスクリプト書くときもなんとなく踏み込まないでいた領域だったかも知れません。 でも今日、作業していたシーンが複雑になってきて、アップベクタ先がわかんなくなって大いに混乱し、最後にはモニタ2個を室伏のようにぶんぶん振り回して窓から放って世界新を出してしまったので、しかたなくスクリプトで出来ないか調べてみました。 なんか、以前にもこんなスクリプトを書いたような気がしないでもないんだが、その記憶も曖昧で。




で、やってみたら、そんなに難しくなかったように思えました。 できました。

いや、ほんとはちゃんと分かってないので、そんなこと言えないんですけど。 どうやらちゃんと動いているっぽいから、たぶん大丈夫だろう、くらいの状態です。






------------------------------------------------------------

//    アップベクちゃんご主人様捜索

//    先に Chain Up Vector Operaror を選択中のオブジェクトから全部かき集める
var oUpVectorOps = XSIFactory.CreateObject( "XSI.Collection" );
for ( var i=0; i<Selection.count; i++ )
{

    //    安直に GetObject で取得。 たぶん "XXX.joint.SkeletonUpVectorOp" しかあり得ないと思うから。たぶんね。
    //    false 付けておかないと、目的のものが見つからなかった場合にエラー吐いて止まるので、false 必須です
    var oSkeltonUpVectorOp = Dictionary.GetObject( Selection(i).fullname + ".joint.SkeletonUpVectorOp", false );
    if ( oSkeltonUpVectorOp )
    {
        oUpVectorOps.Add( oSkeltonUpVectorOp );
    }
}

//    かき集めたオペレータをループして、拘束先を取得
var oUpVectorMasterObjects = XSIFactory.CreateObject( "XSI.Collection" );
for ( var i=0; i<oUpVectorOps.count; i++ )
{
    var oOp = oUpVectorOps(i);

    //    UpVector の場合、InputPort は常に1つしかないと思う。たぶん。 なので InputPorts(0)で大丈夫だと思う。たぶん。
    //    InputPorts(0)で Port オブジェクトを取得し、Target2 メソッドで拘束先である Kinematics.Global が取得され、
    //    Parent3DObject プロパティでその3Dオブジェクトを取得できる。 たぶんですよたぶん。

    var oTargetObject = oOp.InputPorts(0).Target2.Parent3DObject;
    oUpVectorMasterObjects.Add( oTargetObject );

    //    情報表示
    Str = oOp.Parent3DObject.fullname + " ( " + oOp.Parent3DObject.type + " ) -- UPV --> ";
    Str += oTargetObject.fullname + " ( " + oTargetObject.type + " )";
    Logmessage( Str );
}

//    かき集めた拘束先3Dオブジェクトを選択しておしまい。
SelectObj( oUpVectorMasterObjects );

------------------------------------------------------------





オブジェクト(ボーン)を選択して実行します。 すると、アップベクタ先のオブジェクトが選択された状態になります。存在していれば。

チェインアップベクタ専用です。 それ以外のアップベクタって何種類かあるのかな、普通のコンストレインの中のタブにもアップベクタがあるしよくわからんけど、ともかく、ボーンに対して行う Chain Up Vector しか考慮に入れてません。




一応、よくわかってないなりに、スクリプトの説明をしておきますね。




まず、チェインアップベクタというものの正体は、SkeletonUpVectorOp という名前のオペレータであるという所から始まります。 チェインアップベクタを実行すると、ボーンの Kinematic Joint の下にこのオペレータが発生しますね。 はい、まずはオペレータであり、 Kinematic Joint 以下以外には存在しないという存在パターンがつかめました。 存在パターンが限定できるってのは良いことです。取得が楽だからです。

そして、リネームしようとしても出来ない。 これまた実に好都合です。 リネームできるかどうか試してみるクセを付けるといいですね。 この場合は、出来ませんでした。 つまり、Kinematic Joint 以下に SkeletonUpVectorOp という名前で存在すればそれはもうチェインアップベクタのオペレータを指しているということですから、取得するのは簡単です。 


ってことで安直に、


 var oSkeltonUpVectorOp = Dictionary.GetObject( Selection(i).fullname + ".joint.SkeletonUpVectorOp", false );


このように書けばいいことになります。たぶん。たぶんですよ。 取得したいブツの名前が分かっている時は Dictionary.GetObject の呪文が楽です。

ただし、false を入れるのを忘れてはいけません。 もしアップベクタが無いボーンを選んでいた場合や、ボーン以外の、つまりチェインアップベクタがそもそも存在できないオブジェクトを選んでいた場合は、もちろん何も取得できません。 そしてこの false を忘れると、何も取得できなかった時にエラーで止まってしまいます。 これはよろしくありません。 

false さえ付けていれば、何も取得できなくてもエラーが出ません。 代わりに null が入ります。 なので次の行で null かどうかを調べれば取得できたかどうかが分かります。


ってことで、

  if ( oSkeltonUpVectorOp )

こう書いていますが、


  if ( oSkeltonUpVectorOp != null )

こう書いているのと同じ意味です。 null じゃなければ、つまりアップベクタオペレータを(スクリプティング的な意味での)オブジェクトとして取得できていれば、次が実行されるわけです。




次にオペレータの接続先を探すわけですが、ここでやはり大きなヒントになったのは、SDK Explorer でした。 スクリプトで未知の領域に踏み込むときは、まずはなんでもいいから SDK Explorer を開いて端緒をつかみます。 意味わかんなくても端緒さえつかめれば、芋づる式に出来ちゃったりしますから。


ってことで、SkeltonUpVectorOp を SDK Explorer で調べてみると・・・・

Upv2

あっ

Hage 発見! (゚∀゚)


自分でアップベクタ先に指定したオブジェクト Hage が、ちゃんと出ているではありませんか。 まさにこいつを取得したいわけですよ。 アップベクタを仕込んだボーンから始めて、この Hage にたどり着きたいのです。


そして見てみると、InputPortsTarget という所に載っていますよね。 これこそが端緒です。 俺は InputPorts も Target も意味を知りませんでしたが、この InputPorts だか Tartget だかというキーワードさえ見つかれば、あとは SDK ガイドで該当ページやそこからリンクが張られている周辺のページをごちゃごちゃ見てみれば、だいたいなんとかなったり、ならなかったりします。 今回はなんとかなりました。 いつもこうやって調べています。



で、まだちゃんと理解はしてないですが、どうやらオペレータというものには InputPort というものがあるらしい。 オペレータにとってのインプット、つまり何らかの情報を受け取るポート=窓口なんでしょうね。 この場合はアップベクタですから、アップベクタとして指定したオブジェクトのポジション情報がオペレータの窓口 = InputPort から入って来ると考えることができると思います。たぶんね。

InputPort はオペレータによっては複数あるようです。 そりゃそうですよね。パッと思いつくのは、例えば Extrude Along Curve などはカーブ2つから作るわけですし、Merge なんかも2つ以上のオブジェクトから成り立つわけですよね。 

ってことで InputPorts というプロパティがあり、結果は Collection です。 コレクション、つまり複数です。 たとえインプットが1つしかないオペレータでも、取得できるのは Collection です。 なのでそのうちから、目的のポートを1個特定しないといけない。


しかし上の SDK Explorer の画像を見るとわかりますが、SkeltonUpVectorOp の場合は InputPort が1つしかないんですね。 ほうほう。 こりゃ楽でいいわ。 


ってことで、


  Operator.InputPorts(0)


と書けば、コレクションの中から、目的のポート1つをもう取得できたことになります。コレクションとして返って来てはいるものの、1つしかないともう分かっているんだから、最初の1個(0番目)を指定すればいいということです。



で、ポートオブジェクトが取得できればポートオブジェクトに対して効くメソッドが全部使えるようになってますから俺はもう自由です。大空に羽ばたきます。


ってことで、Target2 というメソッドを使ってポートの接続先を取得します。


  Operator.InputPorts(0).Target2



この Target2 というメソッドもよく知りませんでしたが、SDK Explorer で Target と書いてある部分に目的のオブジェクトの名前(Hage)が載っていたもんですから、 ははー どうやら Target という何かがあるらしいぞ  と想像がつくわけで、そこまで想像できればあとは SDKガイドでうろうろしてるうちにどうにかなりますから、大したことはありません。


ただし、こうしてたどり着いた Target は XXX.Kinematics.global というものでした。プロパティですね。 ヌルなどの3Dオブジェクトそのものではなく、3Dオブジェクトが持つプロパティです。 アップベクタオペレータにとってはそのブツの 「ポジション」 がターゲットになるわけであって、ポジション情報というのはこの Kinematics.Global に格納されているから、Target2 で取得できるのは Kinematics.Global オブジェクトである、という風に考えていいんじゃないかと思います。

ここでは Kinematics.Global オブジェクトが取得できているので、こいつに対して使えるメソッドやプロパティは全部使えるようになっているわけです。もう俺は自由です。大宇宙に飛び出します。 


ってことで、Parent3DObject プロパティを使います。


  Operator.InputPorts(0).Target2.Parent3DObject


こう書いて、ようやく3Dオブジェクトにたどり着きました。 




あとは、情報を表示したり、たどり着いた3Dオブジェクトをコレクションにブチ込んでおいてあとでまとめて選択する、という処理を書いているだけです。





ってことで、ほんとにこれでいいのかな。 アップベクタ先の取得の仕方として正しいかどうか、実は自信がないんですが、一応今のところ想定通りに動いているように見えますよ。




いろいろ不正確かも知れませんなあ。
オペレータ弱いです俺。 スクリプトオペレータもよくわかりません。


ツッコミお待ちしています。

ごきげんよう。



.

|

« 脱退グループ。 | トップページ | 新プリミティブ降臨。 »

コメント

まさしく今欲しかった情報です!
なるほどー。InputPortsからたどってくんですね。
勉強になりました。

投稿: kissiy_178 | 2012年1月20日 (金) 00時53分

おー、役に立ちましたか。

あんまり自信ないんですけどねー やってみたら動いているから正しいように見えるというだけで。

何か発見したら教えて下さいね。

投稿: junki | 2012年1月20日 (金) 02時23分

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/217974/53755074

この記事へのトラックバック一覧です: アップベクちゃんご主人様捜索。:

« 脱退グループ。 | トップページ | 新プリミティブ降臨。 »