« 2010年10月 | トップページ | 2010年12月 »

2010年11月

2010年11月27日 (土)

歯車導入。

Gear が出ましたね。
http://opensource.studionestbarcelona.com/gear.html



なにやらまだよくわからん化け物という感じもしますが、まあ、Lagoa なんかと比べたら化け物度は低いと思うし、自分の普段の役割から言っても使える部分は大いにあると思うので、できればいじくり回したいんだけど、めんどくせえなあというのも正直なところであります。




それは置いといて、マニュアルを読んでみると、インストールは .xsiaddon をポイっとドラッグ&ドロップすればおしまい、という簡単インストールではなかったので、自分はどうやってインストールしたか書いておきます。 基本的にマニュアルに書いてあることそのまんまなんですけどね。 まあ、マニュアルは英語だし、インストール説明の画像がないし・・・。


インストールした環境:
Windows 7 Professional 64bit
XSI 2011.5 ( 2011 SAP )
Python の手動インストール無し



1.Python をインストールする


ええと、すいません、俺、Python インストールしてません。

Gear をインストールするためには Python がインストールされていることが条件なわけですが、2011 では Python の手動インストールは免れるようでして、ここで大いに楽しているかもしれません。 2011 からは、XSI をインストールすると自動的に、少なくとも XSI からは Python が使える状態になってるんですよね。 なので、Gear インストールの大前提の部分をショートカットしております。 それで済んじゃったんです。 すいまそん。

Python のインストール方法に関しては、Gear のマニュアルには載っていません。 ↓ここを見ろということです。
http://softimage.wiki.softimage.com/index.php/Python_%28XSISDK%29#Installation



2. Gear で使う Python ライブラリをインストールする


俺、Python の仕組みはよくわかってないんですが、ライブラリと呼ばれるモジュール(基本的な働きを受け持つ小さなプログラム群)を読み込んでそいつらに大いに仕事をさせるような構造になってるんですかね? で、Gear で使う Python ライブラリを、Gear のツールの実体であるスクリプト群からいつでも呼び出せるように、Path を通しておくという作業が必要だそうです。 頓珍漢な言い方になっていたらすいません。

方法はいくつでもあるそうですが、一番簡単なのは、自分のマシンのシステムの環境変数に "PYTHONPATH" を追加する方法だそうです。


1.  まず、マイコンピュータ(コンピュータ)を右クリック > プロパティ


2.  システムの詳細設定 をクリック ↓
01


3.. 詳細設定タブ の 環境変数 をクリック ↓
02


4.  システム環境変数 の 新規 をクリック ↓
03


5. 出てきたダイアログで、変数名 に PYTHONPATH、 変数値 に、Gear に同胞されていた modules フォルダのフルパス ↓
04
modules フォルダはどこに置いておいてもいいんだと思います。Gear のダウンロードファイルを解凍して、modules フォルダだけどこか都合のいい場所に移動させればいいと思います。 たぶん。


以上で、Gear で使う Python ライブラリへのリンクは完了したようです。



3.XSI を再起動する


マニュアルにここで XSI を再起動しろとは書いてないんですが、俺の場合、XSI を再起動しないと次のステップが上手くいきませんでした(バージョン表示のスクリプトを走らせるとエラーが出て止まってしまう)。



4. ちゃんとライブラリにリンクできているか確認する

XSI のスクリプトエディタを開き、言語を Python にし、

 import gear
 gear.logInfos()


この2行をコピペして実行。 ↓
05
画像のようにバージョンの情報が表示されれば、ちゃんとリンクが完了している。

上に書いたように、2011以降の場合は手動で Python をインストールしなくても、スクリプトエディタで言語を Python に設定できちゃうんですね。 2011 以前のバージョンでは Python を手動インストールしないと、そもそもスクリプトエディタで Python を選べないわけですね。



5.  Gear の xsiaddon をインストールする


これは普通に、ドラッグ&ドロップとか、Plugin Manager からとか。俺の場合、Plugin Manager から、workgroup にインストールしました。



6. もうこれでインストール終了。いじり倒す

インストールされると、XSI のトップメニューに Gear というのが出現しました。↓
06
Gear の全てのツールはここからアクセスできるようです。が、マニュアルをナナメ読みした限りでは、スクリプトからしか実行できない機能もあるような書き方になっているように見えるな・・・・。 未検証です。


一応、動いているようには見えます。
07


にしても、まださっぱりわけわかりません。
とりあえずメニューにある項目を片っ端から試してみてるだけ。
エラーメッセージに怒られまくってます。正しいもの選んどけゴルァ、みたいな感じで。
まださっぱりです。
あなた、いじくり倒して俺に教えて下さい。
チュートリアルビデオ作って下さい。
いいですね。
頼みましたよ。




とりあえず、ぬるぬるエグゼ と ぬるぬるトライブ と全く同じ機能が入っているのを発見しました。 全くどうでもいいですが。

あと、PPGLayout と Logic を設定する UI を持ったカスタムプロパティを作れるのがすげえ。 セルフインストール形式にしなくても、オンザフライで UI の整理ができるということか・・・・。 まあ、使いやすいかというとそうでもなさそうなんですが・・・・。

カーブでできたアイコン多数もありがたいですね。

オブジェクト複数選んで実行すると全部をつなぐ Curve ができて Curve の頂点がオブジェクトにコンストレインされている、ってのも地味に便利そうですね。

Resample Curve が動かないのはなぜだろう。



リグ生成周り、デフォーム周りなどは壮大すぎて、まだ分け入ってません。そんな元気ないです。 だれかやって下さい。 頼みましたよ。



.

| | コメント (0) | トラックバック (0)

リージョンさん。 (XPOP普及委員会その15)

ずっと昔に書いたプラグインですがね。


リージョンさん。
Render Region の Mental Ray Options を XPOP で操作するプラグイン。

Regionsan_pop1
http://homepage3.nifty.com/jjj/XSIFiles/Plugin/JJJ_XSI_Plugins.html

要XPOP2。 XPOP2 がないと動きません。


レンダーリジョンのアンチエイリアスの設定とかを、Mental Ray Options の PPG を開かずに、XPOP のメニューからいじろうというツールです。



例えば Toon の Ink なんかを調整している時って、レンダーリジョンのアンチエイリアスやフィルタの設定が重要なんですよね。 レゾも大いに関係しますが、同じレゾならアンチエイリアスのサンプリングの設定が低いと線が途切れ途切れになりがちだったり。 なので Ink を調整する時はリジョンの Mental Ray Options を開いて本番用のアンチエイリアス設定にしたりとか、よくやってました。 でも作業の順番の都合上、Ink 以外の部分をいじったり、また Ink に戻ったりとういことをよくやってました。 こうなると、Ink 以外の部分ではそのアンチエイリアス設定では重すぎるわけです。無駄に重いのは嫌なので、そのたびに Mental Ray Options を開いて設定しなおし・・・・という風にやっていたのでした。 リジョンの右側に出てくるタテのスライダは、いっぺんに色んな値を変えやがるので、min だけ変えたい、とか Sampling Contrast だけ変えたい、ってことはできないんですよね。

とかいう作業にブチ切れて、XPOP を使ってこのプラグインを書いたのが3年くらい前でした。 XSI のバージョンは5だったと思う。 これが ver1.0。

で、XSI が6になってレンダリング周りが大幅に変わったので、このプラグインはもう使えませんでした。 なにせバージョン5まではレンダーリジョンって1つしかなかったでしたからね。 6からだったと思うけど、ビューポートごとにレンダーリジョンを持てたり、Mental Ray 以外のレンダラもサポートしたりして、レンダリング周りの SDK も大幅に変わりました。

しばらく放置していたんだけど、やっぱりリジョンの Mental Ray Option をいじる機会が多かったので書き直した、というのがこの ver2.0 です。 もうだいぶ前に書き直していたんですが、忘れていました。 しかしその時点では XPOP3 はなかったので、XPOP2 用に書かれています。


リジョンの表示チャネルを RGB とアルファで切り替えるというのも割とよく使うな。 まあ、これは単体スクリプトでやった方が便利だったりするんですが。




ところで 2011.5 でのレンダーリジョンは、大丈夫なんでしょうかね? 2011.5 ではレンダリング周りはまだいじれていなく、安定性を確認できていません。 レンダーリジョンは、 XSI のバージョンが上がるたびに何かしら不具合が出てきたようなイメージがありますが、そんなことなかったでしたっけ。 リジョン開いたまま値をいじってると簡単にクラッシュする、とかなんとか。



レンダーリジョンは、SDK 周りもまだ整備が遅れている感じがします。 少なくともこのツールを書いた時点(今年だと思う)では、あるべきオブジェクトがない、よって Object Model ではなくコマンドで対処するしかない、ゆえに単なる値のトグルでもいっぱいコード書かなければいけない、とか、そんな感じだった気がします。 2011.5 でも SDK の新機能でレンダーリジョンがらみは見当たらなかったし。







いやあしかし、ここ最近は仕事の都合で完全にレンダリングから遠ざかっています。 ゆえにこのツールもあんまり使いません。 たまに無性にレンダリングしたくなります。 でもレンダリングな仕事をしてると、切実にアニメーションをいじりたくなって来るんですよね。 人間って、いつまでも満たされない生き物ですね。 アレをしてればコレが欲しくなり、コレを手に入れるとやっぱりアレが良いなどと言い出す。 この満たされない思いに永遠に苛まれながら、今日も明日もCG作るしかありません。



久しぶりに曲行きましょう。



ダイアンバーチと言えば、↑この曲が有名でしょうかね? すんげえ良くできたPVですね。

メイキング映像もすんげえ面白い。

アナログ最高ですね。CGなんてやってられねえ、って気分になりますね。


でもやっぱり、ダイアンバーチさんを語るには、ガニ股ピアノに触れないわけにはいかないでしょう。

ちょっと上手くガニ股動画を探せなかったんですが、↑の動画では 3:00 くらいに確認できます。
 

↑こちらでは、全編ガニ股ですね。 過去に何度も、この人のガニ股ピアノを見たように思います。

なんて素敵なガニ股なんでしょう。 ダイアンさんはものすごく美脚なんですが、それとは必ずしも関係なく、その豪快な開きっぷりがたまらんです。 最初は友人に音を聴かされて、その歌唱力に惚れたのですが、あとでライブ映像見たらスヴァらしいガニ股で、ますます惚れました。

もしかして、キーボードが小さめの時に、ヒザに当たらないように自然とガニ股になるんではないかな?  上の動画では両方とも、ダイアンさんの体型に対してキーボードが小さく見えます。 っていうか、おそらく同じキーボードですねこれは。 ううむ、だとすると、どうにかしてこのキーボード以外を弾かせない工夫をするとか、彼女の機材を全て小さいサイズのものにすり替えてしうことができれば、いつでも大開脚が拝めるのではあるまいか。

などと妄想しています。 妄想です。







.

| | コメント (2) | トラックバック (0)

2010年11月20日 (土)

取得 その6。

取得その3 で、Texture Projection(UV) の取得のしかたを教えてくれというコメントが付きましてね。 そのコメント内のやりとりで一応は解決した感じなのですが、改めてまとめてみようと思いましてね。



ってことで、Texture Projection の取得のしかた、およびどうやってその方法にたどり着くかの思考過程について書いてみようと思います。




まずはともあれ、取得しましょう。 現在ユーザが選んでいるオブジェクトが持つ Texture Projection を取得する、ということにしましょう。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oClusters = oObj.ActivePrimitive.Geometry.Clusters;
    Logmessage( oObj + " が持っている Cluster の数 -- " + oClusters.count );

    for ( var j=0; j<oClusters.count; j++ )
    {
        var oCluster = oClusters(j);
        Logmessage( "  (Cls " + (j+1) + ") " + oCluster + " : Type = " + oCluster.type );

        if ( oCluster.type == "sample" )
        {
            var oClusterProperties = oCluster.LocalProperties;
            Logmessage( "    " + oCluster + " が持っている ClusterProperty の数 -- " +  oClusterProperties.count );
            
            for ( var k=0; k<oClusterProperties.count; k++ )
            {
                var oClusterProperty = oClusterProperties(k);
                Logmessage( "      (ClsProp " + (k+1) + ") " + oClusterProperty + " : Type = " + oClusterProperty.type );
                if ( oClusterProperty.type == "uvspace" )
                {
                    Logmessage( "      #### ↑ これは Texture_Projection っス。####" );
                }
            }
        }
    }
    Logmessage( "---" );
}

冗長な Logmessage が入っているので見づらいコードですが、まあこういうことです。

Texture Projection を持つオブジェクト(複数可)を選んで実行すると、
Gettp_result
こうなります。 ログを見ると、Texture_Projection が取得できているのがわかります。 




では解説。

でもコードの解説の前に、そもそも Texture Projection とは、どういう形でシーンに存在するのだ? ということを知らなければいけない、という解説をします。これを知らないと取得しようにないからです。

Explorer または SDK Explorer で見てみます。
Tp_explorer1

 cone > Polygon Mesh > Clusters > Texture_Coordinates_AUTO > Texture_Projection


という階層構造で Texture Projection が存在しているのがわかります。 この階層を把握することが重要です。 これがわかれば、あとは逆にたどっていけば良いのです。 どういうことかと言うと、


1.最終目的地である Texture_ProjectionTexture_Coordinates_AUTO 以下にあるんだから、Texture_Projection を取得しようと思ったらまずその親である Texture_Coordinates_AUTO を取得することが必要だ

2.Texture_Coordinates_AUTO を取得するためには、その親である Clusters の取得が必要だ

3.Clusters を取得するためにはその親である Polygon Mesh(Primitive) の取得が必要だ

4.Primitive を取得するにはその親である cone の取得が必要だ

5.cone というのはユーザが選んでいるシーン内の3Dオブジェクトだから、これの取得は Selection を使えばいいじゃないか


という風に、目的地から逆をたどって取得の方法を探るのが一般的だと思います。階層をすっ飛ばしてイッキに取得できる便利な方法もあったりしますが、まあそれは別の話として、基本はこの階層構造を認識できているかどうかが、ひとつのポイントになると思います。 このためにも、スクリプトを書くときは常に Explorer を見ながら、自分は今、階層のどこを取得してるのかを意識しておくといいと思います。




さて、これで取得の 「 順番 」 は想像が付きました。 次に SDK Explorer で最終目的地である Texture_Projection の仔細を見てみます。
Tp_explorer2
すると、Texture_Projection は ClusterProperty というものだということがわかります。Type は uvspace となっています。 ここから、「 Texture_Projection は ClusterPropety と呼ばれるものであり、かつ、ClusterProperty の中でも uvspace というタイプに分類されるんだな」 と想像します。 

そして、上記の階層構造の解析により、Texture_Projection の親は Texture_Coordinates_AUTO だとわかっているんだから、「 親である Texture_Coordinates_AUTO が ClusterPropery を所有している。その中でも uvspace というタイプのものを選別すれば、それは Textrue_Projection である」 と想像します。

考え方として重要なのは、SDK Explorer で調べた「Texture_Projection は ClusterProperty である」 という事実を、「自分自身が ClusterProperty だということは、親が所有する ClusterProperty の中に自分が含まれるんだ」 という風にとらえることですかね。

このとらえ方をベタにコードにしてみると、Texture_Coordinates_AUTO.ClusterProperty と書けば ClusterProperty を取得できることになります。 でも実際のコードはこの書き方になりません。 実際の書き方については後述します。




ともかくも、親オブジェクトが持つ ClusterProperty という認識がここでできました。では、次に親オブジェクトである Texture_Coordinates_AUTO とはいったい何なのか? を考えます。 同様に SDK Explorer で見てみると、
Tcood_explorer
はい、Cluster であることが分かります。Type は sample です。 
ってことは、親が所有する Cluster を取得して、その中の sample というタイプのものだけを取り出せばいいんだ」 と想像します。


このように、自分自身が○○である、とわかったら、親が持つ○○の中から自分を探せば良い、という認識を育てると良いような気がしていますが、どうですか。どうですかって言われても困りますよね。 でも、どうですか。 円熟スクリプターのあなた、どうですか。





ってことでもうめんどくさくなったので思考過程の説明は終わりにして、コードを順に解説します。


for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);

     .................
}


まあこれはもういいですよね。 Selection の for ループで i 番目の人を取得しています。ユーザが選んでいる(複数かも知れない)オブジェクトの中の1つを取り出したということです。 これで基点になる3Dオブジェクトを、オブジェクトとして取得できました。



次に Primitive を取得しますが、ここはひとつずつ取得するとめんどくさいので、その次に取得するべき Clusters までイッキに取得します。

 var oClusters = oObj.ActivePrimitive.Geometry.Clusters;

これはこういうもんだとカンニングで覚えちゃってもいいかとは思いますがね。
ちなみに、もしイッキに取得せずひとつずつ行くなら、

 var oPrimitive = oObj.ActivePrimitive;
 var oGeometry = oPrimitive.Geometry;
 var oClusters = oGeometry.Clusters;


と3行に分けて書いても結果は同じです。上の書き方では、長くなるのを嫌ってドットでつないでイッキに Clusters までたどり着いているというだけで、目的によってはこのように分けて書いた方が便利な場合もあるでしょう。

で、Explorer 上ではPolygon Mesh となっていますが、その横に P のアイコンがありますよね。 これを Primitive オブジェクトといいます。 3Dオブジェクトのカタチを決めているオブジェクトです。 例えばヌルにも Primitive があり、同様に P のアイコンがあり、ヌルのカタチを決めています。 X3DObject には全部 Primitive があります(たぶん)。 

そして Primitive オブジェクトを取得するには xxx.ActivePrimitive という書き方になります。 oObj.Primitive.Geometry.Clusters と書かずに oObj.ActivePrimitive.Geometry.Clusters と書いているのはそういった理由からです。 これはもう文法なので、覚えるしかない。

そしてその下に Geometry オブジェクトがあります。 この Geometry は、上記の階層の中には含まれていませんね。これについての説明は上手くできません。俺もよく分かってないからです。ともかく、Cluster は Primitive オブジェクトの直下に存在するのではなく、Primitive 直下に存在する Geometry のさらに下に存在するんです。これは丸暗記で勘弁してください。クラスタというものはこういう階層構造で存在するのだと覚えちまいましょう。  

少し正確に言うと、ここでは ActivePrimitive プロパティを使って取得できたPrimitive オブジェクトの Geometry プロパティを使っています。Primitive.Geometry という書き方をすると Geometry オブジェクトが返ってくるので、返って来た Geometry オブジェクトの Clusters プロパティを使って ClusterCollection にアクセスしているのです。

余談ながら、なんで Primitive にアクセスするためには ActivePrimitive と書かなければいけないのに、Geometry にアクセスするときは ActiveGeometry ではなくただの Geometry になるのか、その理由がよく分かりません。 何かロジカルな理由があるんでしょうか?

さらに余談ですが、例えばヌルは1点の情報しか持っていませんのでジオメトリは存在しないということになり、この Geometry オブジェクトも存在しません。Geometry オブジェクトが無いということは、ヌルにはクラスタが作れないということになります。 その一方、例えば Curve ですが、レンダリングできるジオメトリが無いという意味ではヌルと同じですが、3D空間上には1点ではない実体が厳然としてあります。だから Curve.Primitive の下にはヌルと違って Geometry が存在し、その下に Clusters も存在できます。





で、Clusters までたどり着いたわけですが、Logmessage で取得したものを表示させています。

    Logmessage( oObj + " が持っている Cluster の数 -- " + oClusters.count );

デバッグです。ちゃんと取得できているかどうかを確認するために、いちいち Logmessage を入れるクセを付けた方がいいと思います。

ここで重要なのは Clusters で取得できたものは ClusterCollection であり、Cluster そのものではないということです。Geometry オブジェクトのヘルプページに行き、Clusters プロパティのリンクをたどってみて下さい。Clusters プロパティのページに飛ぶわけですが、
Sdkg_clustersproperty
ClusterCollection が戻り値だよと明確に書かれています。 そもそもコレクションだからこそ count というプロパティが存在するわけです。  count は集合体(コレクション)の中に含まれるオブジェクトの 「数」 です。コレクションではない単体オブジェクトは数が最初から1だとわかっているので、count なんていう意味のないプロパティはありません。 だから、count を表示させようとして「そんなメソッドやプロパティはサポートされてねえぜゴルァ」とエラーが出たら、コレクションを取得しようとしているのに、どうやらコレクションではないもの(例えば単体オブジェクト)を取得しちまってるらしい、と気づくことができます。 これがデバッグです。 なんでも Logmessage でデバッグしましょう。


それにしてもこの日本語 SDK ガイド、「 Cluster を含む ClusterCollection 」 って紛らわしい翻訳ですね。なんとなく、Cluster 以外のものも含まれているんじゃないかという誤解を与えかねません。 ClusterCollection には Cluster オブジェクト以外含まれていないんだから、「 Cluster を含む ClusterCollection 」なんて書かないで「Cluster が入ったClusterCollection 」とか「Cluster が格納されている ClusterCollection 」 と言うべきなんじゃないの。わかってますか、ローカライズしたあなた。そうあなたです。




ってことで、このコレクションをループして Cluster ひとつひとつを取り出します。それが次。↓

 for ( var j=0; j<oClusters.count; j++ )

はい、これで ClusterCollection に入ったブツの数だけ繰り返すループが発生しました。ちなみにクラスタを持たないオブジェクトが処理対象になっていた場合、count はゼロになるので、ゼロ回のループが発生します=つまりループは発生しません。 なので、クラスタがないオブジェクトは無視されるだけで、特にエラーで止まったりはしません。



次に、

        var oCluster = oClusters(j);
        Logmessage( "  (Cls " + (j+1) + ") " + oCluster + " : Type = " + oCluster.type );


oCluster の中に oClusters の中の j 番目の人を格納しています。 oCluster への代入は必須ではありませんが、代入しないと以降の行で常に oClusters(j) と書かねばならずコードが見にくいですし、今はコレクションの中から単一のものを取り出せているぞと意識するためにも、ひとまず代入することにしています。

2行目の Logmessage は、またもやデバッグのために結果を表示しているだけです。単一のクラスタについて、名前と、クラスタのタイプを表示しています。 もしそのオブジェクトが、例えばエンベロープを持っていたら、pnt(ポイント)というタイプのクラスタもログされるはずですし、マテリアルのためのポリゴンクラスタがあったりすると、poly(ポリゴン)というタイプのクラスタもログされるはずです。 後で sample というタイプだけ抜き出すので、色んなタイプのクラスタの中からちゃんと目的の物が抜き出せているかチェックするために Logmessage しているということです。




さ、ではそのクラスタが、目的のタイプである sample かどうかを調べましょう。

    if ( oCluster.type == "sample" )

そのまんまです。 oCluster の Type プロパティが sample であるかどうかをチェックしています。 sample でない場合、つまり上記の pnt や poly というタイプのクラスタだった場合は、以下の { } の中は実行されず、スルーしてループが進みます。 

はい、これで sample クラスタだけを選別することができました。上記の SDK Explorer で調べた結果 Texture_Coodinates_AUTO の正体は sample クラスタだとわかっているんですから、ここで初めて Texture_Coodinates_AUTO を取得できたことになります。 イエイ。




今度は、取得できた Texture_Coodinates_AUTO の子供のうち、Texture_Projection の正体である ClusterProperty を探します。

        var oClusterProperties = oCluster.LocalProperties;
        Logmessage( "    " + oCluster + " が持っている ClusterProperty の数 -- " +  oClusterProperties.count );


はい、またコレクションとして取得しました。 取得できた結果 oClusterProperties に入ったのは、ClusterPropertyCollection です。 この取得のために、Cluster オブジェクトに使えるプロパティのひとつ、LocalProperties プロパティを使いました。

LocalProperties はどうやって調べたかと言うと、まず上記の SDK Explorer での調査でTexture_Projection は ClusterProperty だということがわかったんだから、素直に SDK ガイドで ClusterProperty のページを見ます。

Sdkg_clsprop
はい、赤線の部分のような記述がありました。 

む。 まずいなこの表記は。 ここの「クラスタプロパティ」はカタカナではなく ClusterProperty と書くべき所だ。こら、ローカライズしたあなた、わかってますか。 あなたです。 ま、俺も厳密に使い分けられてないですけどね。

ともかく、ClusterProperty を取得するには、親オブジェクトの LocalProperties プロパティを使えとマニュアルに書いてあるわけです。 ただし、実はこの記述を見つけられなかったとしても簡単に取得の方法がわかる場合があります。これは後述します。



はい、ともかく ClusterPropertyCollection が取得できました。Logmessage で確認もしました。


次に、例によってコレクションなのでループして1つ1つ取り出します。

        for ( var k=0; k<oClusterProperties.count; k++ )
        {
     ............
        }


はい、ただのループです。取得できた ClusterPropertyCollection の中身の数だけ繰り返します。 ではループの中身行きます。

    var oClusterProperty = oClusterProperties(k);
    Logmessage( "      (ClsProp " + (k+1) + ") " + oClusterProperty + " : Type = " + oClusterProperty.type );

はい、また例によって、必須ではないけれど ClusterPropertyCollection の中から個別の ClusterProperty を取り出して代入しただけです。 そしてしつこく Logmessage をしています。 取得できた個別の ClusterProperty のタイプを表示しています。



そしてようやく、

        if ( oClusterProperty.type == "uvspace" )
        {
            Logmessage( "      #### ↑ これは Texture_Projection っス。####" );
        }


そのタイプが uvspace であるかどうかの判別をしています。 uvspace だった場合は、それはもう Texture_Projection です。 なので、 if のあとの最初の角カッコ { } の中が、Texture_Projection を取得できた場合です。 この例では これは Texture_Projection っス と Logmessage しているだけですが、実際に自分がやりたい処理をここに書けばいいでしょう。 oClusterProperty の中身に入っているんだから、あとはこいつを煮るなり焼くなり揚げるなり自由です。 完成。 イエイ。




以上。 うはー なげえ。 解説が長すぎてかえってわけがわからなくなっているという、典型的なダメパターンですか? やかましいノルァ



でもほんとに長くてわかりにくいと思うので、Logmessage などを廃してコメントを付けた省略バージョンを載せときます。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);    //    ユーザが選んでいるものを取得
    var oClusters = oObj.ActivePrimitive.Geometry.Clusters;// そこから、ClusterCollection を取得

    for ( var j=0; j<oClusters.count; j++ )
    {
        var oCluster = oClusters(j);    //    ClusterCollection の中から、1つの Cluster を取得
        if ( oCluster.type == "sample" )    //    そいつが sample という Type だったら以下を実行
        {
            var oClusterProperties = oCluster.LocalProperties;    // LocalProperties を使って ClusterPropertyCollection を取得   

            for ( var k=0; k<oClusterProperties.count; k++ )
            {
                var oClusterProperty = oClusterProperties(k);    //    ClusterPropertyCollection の中から1つの Cluster Property を取得
                if ( oClusterProperty.type == "uvspace" )    //    Type が uvspace だったら、そいつはめでたく Texture_Projection(゚∀゚)
                {
                    Logmessage( "      #### ↑ これは Texture_Projection っス。####" );    //    ここにやりたい処理を書く
                }
            }
        }
    }
}


こんなんでどうですかね。 一度解説をナナメ読みした後では、こっちの方がわかりやすい気がします。




さて、まだ続きます。 省略した書き方です。



上の例では、Cluster の Type が sample かどうかを調べるのに if を使いました。 ClusterProperty の Type が uvspace かどうかを調べるためにも if を使いました。 構造としてはわかりやすいと思うんですが、コードが長くなりがちです。構造を一度わかってしまえば、もっと簡単に書きたくなるものです。 そして簡単に書く方法はあります。 以下のように書けます。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );//最初から sample という Type の Cluster しか取得しない

    for ( var j=0; j<oSampleClusters.count; j++ )
    {
        var oSampleCluster = oSampleClusters(j);
        var oUVs = oSampleCluster.LocalProperties.Filter( "uvspace" );//    最初から uvspace という type の ClusterProperty しか取得しない
        for ( var k=0; k<oUVs.count; k++ )
        {
            var oUV = oUVs(k);
            Logmessage( oUV + " は Texture_Projection ですので、煮るなり焼くなり揚げるなり蒸すなり、ご自由にどうぞ。" );
            //    ここにやりたい処理を書く。 Filter によって、Texture_Projection 以外は取得してないので、安心してどうぞ。
        }
    }
}


さっきのスクリプトを改造しました。結果は全く同様、Texture_Projection が取得できます。 ここで使っているのは Filter メソッドです。


 var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );

青字の部分までは、さっきのスクリプトと全く同じです(変数の名前は oSampleClusters に変えていますが)。 つまり、青字部分だけで ClusterCollection が取得できることはわかりますよね。

で、取得できた ClusterCollection に対して、Filter メソッドを使います。赤字部分です。 カッコの中は Type です。 

マニュアルで見ましょう。 該当ページへのたどり着き方は何度も書いているように、親である Geometry オブジェクトの Clusters プロパティをクリックすると、当然 Clustersプロパティのページに着き、Clusters は ClusterCollection を返すぜという記述があり、その ClusterCollection のリンクをクリックすると、当然 ClusterCollection のページに着き、そのページで ClusterCollection で使えるメソッドのひとつ Filter があるのでクリックする、という芋づるをたどります。

Sdkg_filter 細かいことはおいといて、カッコの中に書く最初の引数が Type だと書いてありますね。 先の SDK Explorer による調査で sample という Type が欲しいとわかっているので、そのまんま "sample" と書けばいいわけです。

すると、oSampleClusters には最初から Filter の条件に一致したオブジェクトしか格納されません。 さっきまでは、ともかく Cluster を全部取得して、その後で中身を1個1個調べて sample かどうかを if 分で判別していたわけですが、めんどくさいので最初から sample という type 以外は無視しろやゴルァ と書いているのです。 仮に sample というタイプのものが無かった場合は、oSampleClusters には何も入らないので、null かどうか、あるいは count がゼロかどうか、などで調べられるでしょう。 この例の場合は、もしゼロだったらそもそも次のループが発生しないので、スルーされるだけです。 楽ちんです。

で、取得できた oSampleCluster の中から(この中には sample タイプの Cluster しか入っていない)、ひとつずつループし、ClusterPropertyCollection を得るために LocalProperties を使っているんですが、同様に Filter で uvspace を指定しているので、oUVs の中には最初から uvspace 以外のものは入りません。 つまり Texture_Projection 以外のものは入りません。

   var oUVs = oSampleCluster.LocalProperties.Filter( "uvspace" );

楽ちんですね。



このように、コレクションに対しては Filter メソッドが効く場合が多いので、特定のものを判別したいときによく使います。 ま、でも、実際は Filter の存在を忘れて if とか書き出しちゃう場合も多いんですがね。







まだ続いてしまいます。





上で、「ClusterProperty を取得するには LocalPropertis を使え」という表記が見つけられなかったとしても大丈夫だ、という意味のことを書きました。 それについての説明です。


結論から書くと、以下の書き方でも挙動は同じです。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );

    for ( var j=0; j<oSampleClusters.count; j++ )
    {
        var oSampleCluster = oSampleClusters(j);
        var oUVs = oSampleCluster.Properties.Filter( "uvspace" );//Properties でOKよ
        for ( var k=0; k<oUVs.count; k++ )
        {
            var oUV = oUVs(k);
            Logmessage( oUV + " は Texture_Projection ですので、煮るなり焼くなり揚げるなり蒸すなり、ご自由にどうぞ。" );
        }
    }
}




LocalPropertiesProperties に変えただけです。

では、LocalProperties じゃなくて Properties でも良いのだ、という情報をどうやって得るかというと、

 1.Explorer のアイコンを見て想像する
 2.SDK Explorer の ClassName から想像する
 3.SDK Explorer の Supported Object Model Interfaces から判断する


この3つかなあ。


まず1なんですが、Texture_Projection は、Explorer 上で白黒のグラデーションアイコンですよね。 このアイコンは、XSI の中でそいつは Property だ、ということを表します。
Propertyicon

例えば Kinematics や Visibility なども同じアイコンなので、 Property です。


今回の場合、

 Texture_Projection を取得したい → アイコンを調べたら白黒グラデだ →
 じゃあこいつは Property なんだな → だったら親オブジェクト.Properties が効くんじゃねえの


という思考回路を働かせればいいと思います。 

本来は、最初に SDK Explorer で調べたように Texture_Projection の正体は ClusterProperty なわけですが、おそらくは ClusterProperty は Property の一種類であるので、アイコンは同じものだし、Properties プロパティによって取得できる、ということなんだと思います。

このように Explorer でアイコンを見てブツの種類やそいつに使えるメソッド・プロパティを想像するというのは、けっこう有効な方法だと思います。 例えば Cluster の場合はあの青いアイコンですよね。 あれを見れば「あ、クラスタだ」 とわかります。 Texture_Projection は白黒グラデアイコンだからプロパティであり、しかも青いアイコンの下だからクラスタにぶら下がっているんだ、という理解があるだけで、マニュアルを調べるのもすんげえ楽になりますからね。 Clusters は白いフォルダのアイコンですが、これは何らかの Collection である場合が多いです。今回の場合は ClusterCollection ですね。

ちなみに、Properties プロパティを使って白黒アイコンのものを取得できるからと言って、Properties プロパティを使って取得できるものは白黒グラデアイコンのものだけだ、という話にはなりません。 例えば Material も Properties を使って取得できるもののひとつです。 



次に2と3ですが、SDK Explorer から端緒をつかみます。
Tp_explorer2

2に関しては、はい、ClassName が ClusterProperty なので、ああ、これって Property の一種なんじゃねえの? と想像してるだけです。 想像したら試しに使ってみて、結果がどんな場合でも変わらなく正しい場合は、うん、これは正しいのだろう、と想像にまかせたままスクリプトを書いてしまいます。 例外が出てきたらそのとき考えればいいんです。


3に関しては、SDK Explorer の中で明示されていると言ってもいいかと思います。 Supported Object Model Interfaces のところに、Property と書いてあります。つまり、この ClusterProperty というオブジェクトは、Property と同じメソッド・プロパティをサポートしてるよという意味だと思いますたぶん。 Property と同じなら、Properties プロパティを使って取得できないわけがないじゃないですか。 ってことで、自分自身の親になるオブジェクトに対して Properties の呪文を唱えてやると、自分自身が含まれたコレクションが返ってくるぞと想像できます。


このように俺はいつも、アイコンや SDK Explorer の記述から取得の仕方を想像しながら進めてますね。 あんまりロジカルにわかってなくても、想像さえつけばなんとか端緒がつかめるので、端っこさえつかんでしまえば後は芋づるです。 スクリプト書くのは芋掘りと同じなんです。


その6おわり。ふう。




うーむ、カンニングというよりは、取得方法がわからないときの思考過程の紹介に労力を費やしてしまっている気がするな。 でもまあ、載せたコードをそっくりコピペすれば Texture_Projection は取得できるわけだから、まあカンニングにもなってますわね。

もっとスマートなコードの書き方もあるでしょうねえ。でも俺は上記のような思考過程をたどっている感じなので、おのずと出てくるコードはこんな感じになるんですよ。 スマートかどうか、簡潔かどうかなどはひとまずおいといて、あるロジック(ある思考過程)に基づいて書けたかどうかで、満足度が違う気がします。 ロジックを無視するのがコピペ=カンニングですかね。 でも何度も言うように、ロジックはカンニングしてるうちにわかってくるものなので、やっぱりカンニングは必要なわけですよ。




.ふう。
またネタを見つけたら書くかも知れません。
ふう。



.

| | コメント (0) | トラックバック (0)

2010年11月18日 (木)

ガッデムPlot。

右クリックで Plot ができるプラグイン。


ガッデム Plot
http://homepage3.nifty.com/jjj/XSIFiles/Plugin/JJJ_XSI_Plugins.html

Gp1


Plot という作業がよく必要になるんですが、いちいち左側の Plot メニューに行くのがめんどくさいと長年思っていました。 Animate モジュールでしかできないのも不便。 Marked Parameter とか、メニューの文字を読んで探すのは実にめんどくさい。 SRT 全部 Plot する場合とかならともかく、今このひとつのパラメータを Plot したいだけなのに、あれこれやらなければいけないのが嫌だったのです。


なので、アニメーションアイコンから右クリックで出てくるメニューの中に Plot を入れたという、ただそんだけなのです。 マウスの移動量が少なくなって、少しラクです。 気が晴れました。

右クリックしたパラメータのみを Plot するというのがポイントなのですが、逆に言えばそのパラメータしか Plot できないことになります。 でも、マークしたパラメータがあった場合はそちらを Plot するというモードもあるので、一応は汎用的に使える気がします。 Animate モジュールじゃなくとも Plot できるというのもポイントですかね。 まあ、SRT 全部 Plot したい場合とかは普通に標準機能を使ったほうがラクでしょう。





セルフインストール式のプラグイン内で、コンテクストメニュー(右クリック)メニューに独自のメニュー項目を入れ、クリックされた時に呼び出されるファンクション内で var oHoge = in_ctxt.GetAttribute("Target"); などとやると、クリックしたその対象物が取得できるということがわかったのが、収穫でした。 RenderTree や ICETree でノードを右クリックし、そのノードに対して何かやるというツールを書く時に便利そうです。たぶん。







しかし Plot って便利な機能ですよねえ。魔法のように感じることすらある。 いや、まあ、大げさですが。

例えば、あらかじめリグの付いたキャラクターを渡されて、 「このリグでアニメーション付けて下さい。 リグの改造は認めません」 などという制約を課された時ですよね。 スヴァらしいリグだった時は実に楽しい作業になるんですが、アレなリグだった時は実につらい作業になります。アレというのは必ずしもデキが悪いという意味ではなく、アニメーションの思想が根本的に違うというか何と言うかね。 リグには思想が現れます。作った人のアニメーション作成へのアプローチが如実に反映されます。単純な所では、このパーツを FK で動かすか IK で動かすかとか、そういう部分ですかね。 こういう根本の思想で自分と合わないリグを使わなければいけない時は、苦痛が109倍くらいになりますよね。 そもそもアニメーション作業をしない人が作ったと思われるリグもたまにあります。つらいです。

こんな時はもう、二人羽織り・三人羽織りですね。 もとのリグの階層構造はいじらないまま、独自に作ったリグ階層にコンストレインやエクスプレッションで接続しまくり、そちらのリグでアニメーションを付けます。 そして最後には元のリグ(コンストレインされている、改造してはいけない方のリグ)の SRT で Plot しちまいます。 Plot 後に独自階層は削除しちまえば、元のリグを改造せずにアニメーションを付けたのと同じ状態になります。

場合によっては「Plot しないでくれ。リグを改造するなと言ったのは後で動きをいじるかもしれないからであって、Plot して毎フレームにキーがある状態にされるとすごくいじりづらくなるから、意味ないよゴルァ」 と怒られるかもしれませんが、んなこた知りません。 「Plot したんじゃないですよ。 手付けでキーを打って行くうちに、結果的に全フレにキーが入ったというだけです。 細かい動きまでこだわった、微調整の結果です」 とか言い張ればいいんです。けけけけ。



Plot が無ければこういうことできないので、便利だなあといつも思っています。 でも、Plot 後に値が変わらない FCurve になる場合は Plot しないとか頭とケツだけにキーを打つとか、そういう賢い Plot ができると更に良いんですけどねえ。 できないですよね? XSI 様にこんな賢い Plot は?






.



.

| | コメント (2) | トラックバック (0)

2010年11月14日 (日)

JavaScript ではない。

XSI 上で動いている JScript はジェイスクリプトであり、JavaScript ではない。
JScript と JavaScript は、別のものである。




いや、XSI でスクリプトを書く上で特に知らなくてもいいことだし、俺もよくわかってないし、ほんと全くどうでもいいことなんですがね。



ただ、XSI 上の JScript のことを JavaScript と言う人がいたり、同じものだという説明をする人がいたり、JScript とは JavaScript を省略した言い方であるなどと思っている人も意外と多いので、そのたびに「うーん、違うはずなんだけどな・・・」 と長年思ってきたというだけです。


  JScript はマイクロソフトが開発したスクリプト言語である。
  サンが開発した JavaScript と互換性があるように作られている。(※)

くらいの認識しかないです俺は。 でも最低限、両者は別のものだという認識を持っている。

その認識があるとスクリプト開発が上手くいくかと言うと、全くそんなことはない。

よって、全くどうでもいい話でした。



参考リンク
http://ja.wikipedia.org/wiki/JScript
http://www2.airnet.ne.jp/sardine/complang/JScript.html
http://www.pasonatech.co.jp/techlab/develop_wiki/rep32.jsp



※訂正

つらつらと調べていたら、なにやら、JavaScript はサンが開発したわけではなく、ネットスケープ社が開発して最初は "LiveScript" と呼ばれていたけど、その後ネットスケープとサンが業務提携して、サンが "Java" を開発していたもんだから、LiveScript を改称して JavaScript と呼ぶようになった、という歴史があるみたいです。

よって上記「サンが開発した」の部分に打ち消し線を入れますた。





.

| | コメント (0) | トラックバック (0)

2010年11月13日 (土)

Set/GetGlobal。

ちょっとスクリプトの調べものしていたら・・・・・
っていうか、XPOP3 に付いてきたサンプルコードを読んでいたら・・・・・



ソースの中に、SetGlobal とか GetGlobal とか出てきたんですよ。
なんだろうこれ?
ソースを見てもそんな名前の function とかはない。
コマンドっぽい。
ってことは XSI のネイティブなコマンドなのか?


と思って調べてみたら、SDK ガイドに載ってました。


シーンの中にカスタムプロパティなどを作らずに、値を保存したり取り出したりできるらしい。

その XSI のセッションが終了するまで、つまり XSI を起動し直すまで有効ならしい。

ということは、シーンと一緒にその値をセーブしておくことはできないが、その場限りのちょっとした値の保持場所として使えるということらしい。


知らなかったよっ。
すんげえ便利じゃないですかこれ。



マニュアルを見ると ver5 からの機能のようだ。ってことはもう遥か昔から存在してたんだなあ。いやあ知らなかった。


例えばこんな風に書いてみます。

 SetGlobal( "Hoge", 25 );
 HogeValue = GetGlobal( "Hoge" );
 Logmessage( "Hoge = " + HogeValue );


1行目。 Hoge という入れ物に、25 という数値を、SetGlobal を使って格納する。
2行目。 HogeValue とう変数に、さっきの Hoge の中身を格納する。
3行目。 その中身をスクリプトエディタの中に表示させる。

実行すると、
Setglobal1
こうなりました。

んで、今度は1行目をコメントアウトします。 1行目は実行されなくしたということです。

 // SetGlobal( "Hoge", 25 );
 HogeValue = GetGlobal( "Hoge" );
 Logmessage( "Hoge = " + HogeValue );


すると、
Setglobal2
ちゃんとまた 25 がゲットできてます。

1行目は実行されないので、25 という値はこのスクリプトの中で格納されたわけではありません。 1回目のスクリプトで格納された値が生き残っているということになります。 

上の画像にあるように NewScene を実行した(新しいシーンを開いた)後も、ちゃんと 25 が生きてます。 XSI を終了させるまで生きているようです。


今までこういうことをやろうと思ったら、カスタムプロパティを作ってました。 でもめんどくさいし、特にシーンに実体が残るカスタムプロパティの場合は、例えばシーンルートがカスタムプロパティだらけになって、汚かったりしたわけですよ。 このやり方なら、シーンと一緒に保存されなくてもいいちょっとしたこと、その場限りで値を保持しておきたい場合なんかにとても便利です。



パッと思いつくのが、超 Isolate ですね。 全部のビューポートでイッキに Isolate Selection を実行するという古い自作ツールなんですが、実は未だによく使ってます。 で、この超 Isolate の状態をトグルするために、カスタムプロパティに値を保持していたんですね。 Isolate 状態かどうかをカスタムプロパティに保持しておき、次に超 Isolate が実行されたとき、オンならばオフに切り替え、オフならばオンに切り替え、というトグルをやっていたわけです。 でもこんなちょっとしたことでシーンにカスタムプロパティ作るのもどうかなあ、と思っていたんですよ。 でもこの Set/GetGlobal を使えばカスタムプロパティは必要ありません。

ってことで書き直してみると、

if ( GetGlobal( "ChoIsolate" ) )
{
    bChoIsolate = false;
}
else
{
    bChoIsolate = true;
}
SetGlobal( "ChoIsolate", bChoIsolate );
IsolateSelected( bChoIsolate, 0 );
IsolateSelected( bChoIsolate, 1 );
IsolateSelected( bChoIsolate, 2 );
IsolateSelected( bChoIsolate, 3 );



こんだけ。 カスタムプロパティも必要なく、超スッキリ。新バージョン完成。
いやあ、こんないいもの、早く教えてくださいよ Softimage さん。


ってことで超 Isolate はそのうちバージョンアップさせとくことにしよう。 ま、バージョンアップって言っても上のコードをそのまんまセルフインストール形式の雛形にぶち込むだけですがね。






SetGlobalObject
というものもありますね。 こちらはではなく、オブジェクトや配列を格納しておけるみたいですね。ほうほう。これも便利そう。



挙動を確かめるために、こう書いてみました。

 var oNull = ActiveSceneRoot.AddNull( "null" );
 SetGlobalObject( "NullObj", oNull )
 var oObj = GetGlobal( "NullObj" );
 Logmessage( oObj.size.value );


1行目。シーンルートにヌルをひとつ出し、oNull に格納
2行目。SetGlobalObject コマンドを使って、oNull をオブジェクトとして NullObj に格納
3行目。GetGlobal コマンドを使ってさっき格納した NullObj を oObj の中にオブジェクトとして取得
4行目。oObj にはオブジェクトとしてヌルが取得できているため、ヌルに対する操作は全部自由。 ヌルの持つ size パラメータの値を表示。

125"hoge" などという「値」を格納するのではなく、何かを「オブジェクト」として格納する、というのがこの SetGlobalObject のポイントですね。 オブジェクトとして格納できていれば、オブジェクトに対するメソッド・プロパティなど全て自由ですからね。

で、ためしにこのスクリプトを実行させ、ちゃんとヌルのサイズがログされたことを確認できたら、ヌルのサイズを適当に変えてみて下さい。 
次に、このスクリプトの最初の2行をコメントアウトしてから、再び実行させて見てください。 

ちゃんと変更後のヌルのサイズがログされましたよね?

2行目までをコメントアウトしたんだから、この2回目のスクリプト実行では SetGlobalObject は実行されていないわけです。 しかし、1回目の実行によって格納された NullObj が生きているために、以降 XSI を終了するまで NullObj を GetGlobal で呼び出せば、中に格納されているヌルにスクリプトからアクセスできるということですね。 オブジェクトとしてアクセスしているんだから、そのオブジェクトが持つ様々なメソッドやプロパティが使用可能です。 今回の場合は、「ヌルオブジェクトにぶら下がるプリミティブオブジェクトの中にあるパラメータのひとつ size にアクセスした」ということになります。


お、なんだか取得じみた話になってきた。
まあいいや、スクリプティングは全て取得なんだから。


ってことで、Set/GetGlobal は今後どんどん活用しましょう。



.

| | コメント (0) | トラックバック (0)

2010年11月 7日 (日)

レイちゃん。 (XPOP普及委員会その14)

レイヤなポップアップメニューのスクリプトを書きますた。


レイちゃん

http://homepage3.nifty.com/jjj/XSIFiles/Plugin/JJJ_XSI_Plugins.html

Laychanss
XPOP3 が必要です。



俺の場合 XSI のレイヤは、シーンを作る初期の段階では割とよく使い、実際のプロダクションに入るとデフォルトレイヤ以外は破棄することが多いんですが、ま、便利ですよねレイヤ。 でも 6 を押して出てくる Scene Layer Manager っていうんですか、アレが嫌いなんですよなんとなく。 操作感が悪い感じがするし、画面の面積をけっこう占有されるのも嫌でね。

だからなんとか Scene Layer Manager を使わずにできないかと思って、ずいぶん昔に XPOP2 ベースで書いたものなんですが、最近 XPOP3 が出たのでせっかくだからということで、なるべく XPOP3 の新機能を使いながら書き直してみた、というものです。

カレントレイヤを切り替えたり、レイヤのオンオフしたり、オブジェクトを指定のレイヤにぶち込んだり・・・・という、普通なら Scene Layer Manager でやる操作をポップアップメニューで代用できないかとやってみた、って感じですね。


しかし作ってみたら、案外便利じゃないんだこれが。別にどうということはない。すごくラクになった! という気があんまりしない。 うーむ、いいデキのツールにはならなかった気がします。 ますます、XPOP3 の実験・練習のためのツールという色合いが強くなってしまいました。 まあいいけど。




XPOP3 になって、色やフォントやフォントサイズを変えられるようになったので、その辺をちょっとくらいカスタマイズできるようにしてあります。

フォントサイズなんて、もういくらでも大きくできちゃうもんだから、こんな凶暴なポップアップにすることもできます。
Laychanbig( クリックでオリジナルサイズの画像)

画面全体を覆いつくす XPOP。  っていうか入りきってないし。




以下 XPOP スクリプター向け情報。

XPOPスクリプトは、まあ 3 の方が書きやすくなりましたね。 戻り値が数値ではなく、任意の文字列になりました。 なので、どの順番でどう書こうとも、数字を詰めたりすることを考えずに書けるようになったのはありがたいです。

例えば今までは、3番目の項目がクリックされたときは 3 という数値が返ってきていたんですね。 なのでその数値を見て処理を分岐させてました。 もし既存の 1 と 2 の間に新しい項目を挿入しようと思ったら、今まで 2 だったものを 3 にして、空いた 2 に新しい項目を挿入し、以降全部1つずつ数値をずらす、というようなコードの書き直しが必要でした。 でも 3 からは、各項目で任意の文字を戻せるので、後から項目をどう追加しようが、その後のルーチンはその文字列を見て分岐させればいいわけで、数値をひとつずつずらしていくようなつらい作業はしなくてもなりました。 これはなかなか大きな違いです。

ということで世界の XPOP スクリプターのみなさん、3 を使ってどんどん開発して下さい。



ただ、問題もありましてね・・・。 まだ使い始めたばかりなので詳しく検証できていませんが、どうも XPOP3 には問題がある、というか前にはなかった現象が出ている気がしてます。

まず、重い。 キーを押してからポップアップするまでに明らかにタイムラグがあります。ほんの一瞬だけど、ポップアップがもたつくのは嫌ですよね。やっぱり、フォントいじれたり色がいじれたりするので、描画に処理時間をとられているんだと思います。 アイコンが使えるのも XPOP3 の売りのひとつでしたが、各項目にアイコンを付けるとさらに重くなりました。 なので今回アイコンはあきらめています。

しかも、軽いシーンならそんなに気にならないんだけど、オブジェクトの数が多いような重いシーンでポップアップさせると、明らかに、かなーりもたつくんですよ。 ためしに XPOP2 で書いたいろんなプラグインを走らせてみると、別にシーンの重さには関係ないんですね。重いシーンだろうがなんだろうがポップアップするまでの時間に変わりはありません。 でも XPOP3 は、シーンの重さに比例してポップアップまでのタイムラグが長くなっています。 これは XPOP2 にはなかった挙動です。 「重いシーン」というのは、占有メモリ容量なのかオブジェクト数なのかポリゴン数なのか、その辺の検証はできていません。でもまあ一般的に、ブツがいっぱいあって複雑なリグも組まれていてマテリアルも多く etc ・・・・という、かなりごちゃごちゃしたシーンのことです。そういうシーンだと明らかにもたつきます。 うーむ、これは問題だな・・・。


それと、Expoler や Schematic の上にマウスカーソルがあるとポップアップしてくれないんですね。 いわゆる3Dビューポート上か、ボタンやメニューなどの XSI のインターフェース上にマウスがあれば問題ないんですがね。 ちなみに XPOP2 ではそんなことなく、Expoler と Schematic だろうがどこでもポップアップします。 うーむ、これも不便だ・・・・。



とかなんとか。
もうちょい検証して、クラウスさんに要望出してみるか・・・・。 機能的にはかなり良いアップデートなので、このままでは惜しい。



2010/12/12 追記:

.xsiaddon ファイルのダウンロードリンクが死んでいました。修正しました。
「ダウンロードできないよ」と誰も指摘してくれないのは、誰にも見向きもされていないということですねそうですね。


本文中で Explorer や Schematic 上ではポップアップしてくれないと書きましたが、単に割り当てるショートカットキーがまずかったようです。 Explorer や Schematic 上でのみ動くショートカットキーを、XPOP3 用にダブって登録してしまっていたためにポップアップしてくれなかったようです。 別のショートカットキーにしたらちゃんとポップアップしてくれました。失礼失礼。



.

| | コメント (0) | トラックバック (0)

2010年11月 4日 (木)

3ds 再び。

ちょっと実験用にモデルデータが欲しくてインターネットで探したんですが、未だに .3ds 形式のモデルデータ多いですよね。


んで、XSI 2011 SAP にインポートしようとしたら、3ds のインポート機能がないことに気づきました。 そう言えば前にもそんなこと書いたな、と思って探してみたら、2008年に書いてました。



んで、試しに全く同じことをやってみました。

すなわち、7.0 のプラグインフォルダから 3dsImport.dll をかっぱらってきて 2011 SAP のプラグインフォルダにぶち込む。

そしたら、できました。Import メニューに Import 3ds という項目が現れ、実際にインポートもちゃんとできました。 UV も来てます(正しく来てるかはわかんないけど)。 ただし、以前と変わらずすんげえ遅い。大してでかいデータでもないのに数分かかりました。これは元データによるのかもしれないし、UV が無ければ速いとか、そういうのもあるかも知れません。そこまで実験してません。知りません。



ま、とりあえず最新版 XSI でも 3ds を直接インポートする道はある、ということで。
良かった良かった。




しかし、当然これは嘔吐デスク様にとっては想定外の使い方になると思うので、全ては自己責任でやらねばなりません。これに伴うリスクは自分で負いやがり下さい。 特に 7.0 はアビッド様の製品です。アビッド様に帰属する dll ファイルを嘔吐デスク様のソフトウェアにインストールするというのは法規的に問題あるかもしれません。 このおぞましい混血によって危険なキメラを産み出すかもしれません。知りません。



.

| | コメント (0) | トラックバック (0)

« 2010年10月 | トップページ | 2010年12月 »