カテゴリー「XSI Rendering」の45件の記事

2014年2月24日 (月)

パッていしおん。

何年も前から、改造したり書き足したりしながら書いたツールなんですけどね。


パーティションのアレです。 複数の Pass で、次々にパーティションを作成しながらオブジェクトをブチ込んでいくとか、既にあるパーティションにズンドコ入れていくとか、そういうアレです。


それ以外にも、パーティションがらみのちょっとした機能がいろいろ付いてます。 あの Pass にあるあのパーティションをこちらの Pass でも再現したい、でもマテリアルアサインしたりオーバーライド作り直したりするのめんどくせえなあ、先に全部設定してから Pass を複製すれば良かったなあ、などという場面で役に立ってるんですが、どうですかね。

以前に単体でこのブログに載せたことがありましたね。  それを改良したり、色々付け加えたりしたものですね。







パッていしおん

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


Pa_menu


Pa_ppg







説明は全部ビデオです。 いっぱいツールが入ってるから、いちいちドキュメント書いてられない。 喋る方がずっとラクです。  HD にしないと文字読めないかも。














ではごきげんよう。





.

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

2014年2月12日 (水)

ポリゴンの境界にインクライン。

という話を m4g さんとしていたのですがね。 一応、ここにまとめておきます。



m4g さんはもともと、ワイヤフレームのレンダリングをしたかったらしいのですがね、俺が言う方法は、頑張ればそれにも使えるとは思うけど、もともとはワイヤフレームレンダではなく単に任意のポリゴンの境界にインクの線を出現させたかった、というものであります。 長年使ってきた方法です。



まずですね、オブジェクトに、このようなマテリアルを与えます。 UV も必要です。

Inky11

Toon_Host の中に Unblend Group というものがありますよね。これ、例えばマテリアルごとに数値を変えておくと、違う数値同士はアンブレンドする = ブレンドしない = つまり線を描く という機能ですね。 こいつとこいつの境界には絶対に線を描けよ! と指令していることになりますね。 

っていうか、こんな機能使わなくても、マテリアルが違えばもうその時点で境界に線が描かれるというのが Toon_Ink_Lens のデフォルト設定ですね。 でも、なんらかの都合でこのデフォルト設定を変えてマテリアル境界に線を描かないようにしている場合でも、この Unblend Group で違う数値を持つマテリアル同士では、必ずその境界に線が描かれるということだと思います。

で、このパラメータ、テクスチャが貼れちゃうんですね。 なので、マテリアルは同一でも、UV で指定された領域ごとに違う数値を持たせてやれば、その境界に線を引けるわけです。 1つのオブジェクトの中で、この部分は Unblend Group 1、この部分は Unblend Group 2・・・・という風に指定してあげるわけです。


上の画像の場合、6色のテクスチャを使っています。このテクスチャ画像は、必要な明るさの段階の数だけ色数があるなら、6色じゃなくともなんでもいいと思います。 一番暗い色は黒100%(ゼロ)、一番明るい色は白100%(1)にしておきます。

で、Change Range します。 元のテクスチャは黒100%から白100%までの明るさがあるので、Change Range の Old Range のスタート/エンドは、0 と 1 を入力します。 そしてそれを、6色テクスチャを使っているから6段階にリマップしてあげるということで、New の方に 1 と 6 を入力しています。 「この画像は元々 0-1 の明るさを持っているが、その 0-1 という範囲を、1-6 という6段階の数字に直して出力しろよ」 と言っていることになります。

こうして各ポリゴンは、UV で指定された位置によって、必ず1から6までのどれかの数値(整数)を引っさげて Unblend Group にブチ込まれることになります。 実際に6色しかない画像を使って1-6にリマップするんだから、結果は整数にしかなり得ません。 そして理論上、2-8 でも 21-26でも 9-3 でもいいと思います。6段階にさえなればそれでいい。たぶん。  もし8段階の明るさがあるテクスチャを使うなら、1-8とかにすればいいと思います。たぶん。



そして、上の画像の XSI男の目のあたりを見て欲しいのですが、UV 操作によってこの部分は周囲とは別の色になっています。 ポリゴンによって色が違うということは、その色によって別の数値が Unblend Group に渡されるので、線が引かれるはずです。

ただし、各ポリゴンは、テクスチャエディタ上でそれぞれ1点に集約(コラップス)しないとダメのようです。これをやらないと怪しい模様が出てきたりします。 サンプルポイント同士を補完しようとするから? なのかな? コラップスしていれば、UV上での座標は同一なので、補完されなくなり、整数以外の値が出てこなくなるから、とか? どうでしょうかね。


ってことでコラップスして、レンダリジョン描いてみました。
Inky12

左側、テクスチャエディタ上で、グレー部分のサンプルポイントと、黒部分のサンプルポイントが、コラップスされているのが分かると思います。

そして目の周辺にちゃんとインクラインが描かれている。 反対側の目を見てもらうとわかりますが、本来はラインが描かれないはずの領域です。しかし、目の周辺の領域とそれ以外の領域で違う数値が Unblend Group に渡されているので、線が描かれているわけです。 m4g さん、俺がいつもやってるのはこれです。


ってことで、この方法でやると、ポリゴン境界に確実に線を描くことができると思います。
Inky13


当然、ラインを描きたい場所は、必ずその描きたいラインに沿う形でポリゴンの境界が存在してなければならず、つまりそのようにモデリングしておかなければなりません。 ただの平面だったとしても、そこにラインでなんらかの模様を描きたければ、平面を分割して、平らのまま、分割した線をその形にモデリングしておくということです。



Inky14

例えばメカもので、メカメカしいパーティングラインをインクラインで出したい場合だとか、デカール類の境界線をインクラインで出したい場合、よく使っています。


しかしこれをワイヤフレームレンダリングに使うとなると、隣接するポリゴン同士が同じ色にならないように全ポリゴン分けていかなければいけないので、UV 作業が超大変ですね。

Inky15

うーん、大変だ。 しかも見落としミスをしやすいな。 この画像でも、見落としミスによって、ポリゴンの境界なのに線が描かれてない部分があります。 m4g さん、このやり方だと、全ポリゴンそれぞれでコラップスしていくツールとか、必要かもね。 m4g さんのようにプロシージャルにやる方法を考えた方が良さそうですね。




この方法の大きな欠点は、上に書いたようにモデリングが面倒なこと、UV 作業が面倒なこと、ですよね。 まあ、ワイヤフレーム的に使うのでなければ、その面倒さはもう仕方ないと思っていつもやってますけどね。

あと、閉じた線しか描けないことですかね 例えば文字の 「C]のように、ぐるっと一周つながっておらず一部開いた部分がある線というのは、その構造上できないと思います。 これについて何か方法があれば是非教えてください。



この方法、もともとどこで覚えたんだっけなあ。たぶん、Toddアキタさんのチュートリアルビデオを見たんだと思う。 それを見て、まとめて、シンプルなツリーに落とし込んでくれと丸○くんに頼んでできたレンダツリーだったような記憶があるんだが、どうだったっけね○山くん。




それともうひとつ、ポリゴン境界に頼らず、ポリゴンをまたいだ状態のテクスチャを貼ってそこにインクラインを出せないか、なのですが・・・・。

やってみると難しいんです。 これができれば完全に自由なのにね。
Inky21
テクスチャ画像は自由に描いた物です。マルもあれば四角もある。そして2色しか使ってないので、Change Range の出力は 1-2 にしてあります。

上の画像、なんか、ちゃんと出来ているように見えるでしょ? テクスチャ通りにインクラインが描けていると思うでしょ?


しかし寄ってみると、
Inky22
こうなんです。 線がガタガタです。

これ、テクスチャ画像の曲線部分はアンチエイリアスがかかるので、白か黒(1か0)以外の明るさのピクセルもあるからなんですよね。にも関わらず1-2という、1か2の2種類の数値しか持てない値に Change Range してしまっているので、このようなガタガタの線になるのだと思います。

じゃあアンチエイリアスがない画像にすればいいかというとそんなことはない。同じようにガタガタの線になります。アンチエイリアスしてないということは、元の画像ですでにガタガタの線が描かれているわけで、メンタル霊は忠実にそのガタガタを拾ってインクラインを描くだけです。


ちなみにこの部分だけは問題がないように見える。
Inky23
なぜなら、この部分は元のテクスチャ画像上でで水平線か垂直線しかなく、ゆえにアンチエイリアスがもともと無いからです。水平・垂直線ゆえに、アンチエイリアスがなくとも成立するのですね。 でも実際は、こんな水平・垂直線だけで済むインクラインなんてあり得ません。

試しに Change Range の値を変えてみると、このような変な模様が出てきました。
Inky24
このテクスチャ画像は、アンチエイリアスがかかっているために、もともと何段階かの明るさを持つ画像になっているわけで、それを1-6に押し込めたらこうなった、というものです。意味無し。


でもこの New Range のスタートとエンドを適当にがちゃがちゃいじっているうちに、上手く行ったように見えることもあります。
Inky25
これは適当に 8-2 なんて数値にしてみたら、変な模様が消えた! なんか、上手く行ってる?  でも線がちょっと太いような・・・・。


寄って見てみると、
Inky26
線がガタっている。


同じ箇所をもっと寄って見てみると、
Inky27
わっ 線が複数描かれていたっ
ダメだこれは使えねえ orz

やはり、アンチエイリアスのためにテクスチャ画像のピクセルの色が何段階かになっちゃっているのが原因ですよね。その境界に線を引けと言っているわけだから、アンチエイリアスのボケの中に含まれる明るさの違いの数だけ、線が引かれてしまうということなんですよね、たぶん。 ダメですねやっぱり。  

一方、上記のようなポリゴンコラップス方式は、もともとアンチエイリアスもクソもありません。ポリゴン(というかサンプルポイント)がまるごとコラップスされてある色の領域にまるまる入っているんだから、インクライン境界は画像のピクセルで作られるのではなく、UV で作られるとでも言うかなんというか。

でもまあ、あまり寄らないレンダリングには、上のようなテクスチャを貼る方式も使えるかもしれませんね。




どうでしょうかね。


あ、Max の Pencil って、どうなんですか。 こういうインクラインの制御、すごくできますか? タッチとかそういう制御もそうだけど、今回のこの話題のように、「どこに線を描いてどこに描かないか」の制御が、緻密に出来ますか? あるいは、Maya でも何かいい機能がありますか? 知っているお方、教えて下さい。


そしてもちろん XSI で、俺は他の方法でインクラインを制御してるぜというお方がいらっしゃいましたら、どうか教えて下さい。 この方法のまま、何年もどん詰まり、進化無し状態ですよ俺 orz  新しい知識や技を入れたいところです。。。。。





.

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

2013年8月30日 (金)

インク線の距離減衰。

先日某所でこの話が出たので、それをメモしておきます。 俺は2005年頃にごちゃごちゃいじっているうちに発見したんだったと思うけど、世間一般ではあまり知られてないのかな。どうなのかな。



アレですよ。 Toon_Ink_Lens。

もう何年も何年も放置プレイされている、進化のない輪郭線レンズシェーダ。

改良する気ないなら Pencil ちょうだい Pencil。

2005年とかから、ほんと変わってない気がする。





で、この Toon_Ink_Lens ですが、カメラから遠いオブジェクトまで同じ太さで線を描いてしまうとごちゃごちゃした絵になりやすいので、距離による太さの減衰を入れてあげて、遠くに行くほど線が細くなるように、よくやりますよね。


でも、オブジェクトの一番外側の境界線だけは細くならないんですよね。 アホか。 なんでこうなるの。早くどうにかして下さいよ嘔吐デスク様。

この記事は、その対処法のメモなんですがね。 まあ、俺はこんな風にしてますよというだけの話ですが。




例えばこういうシーンがあります。

It_1

よくある、男の整列のようすですね。





で、Toon_Ink_Lens が設定してあります。

It_2

Taper のタブで、Distance Amount を  にしています(デフォルトはゼロ = オフ)。  つまり距離による線の太さの減衰を最大に効かせている状態です。

一応パラメータの意味をざっくり書くと、 Near 15Far 50 ですから、カメラから距離が 15 の地点から減衰が始まり、50 の地点で減衰が終わります。 つまり、15 より近い部分は一番太い状態のまま変わらず、15 から細くなり始め、50 で最も細くなり、50 より遠い部分では最も細い状態で続くということになります。

Min は  です。 つまり、Near の距離の時に太さが Spread x 1 になるということです。 Spread はとなりのタブ(最初のタブ)である Basic Appearance の中の Spread で指定した線の太さです。 たとえばこの Spread を 2 に設定していたとしたら、2 x 1 = 2 なので、距離 15 までは 2 の太さが続くということです。

Max0.1 です。 "Min" が 1 なので、"Max" の方が値が小さいのは感覚的にヘンな気もしますが、値じゃなくて効き具合が Max だと考えればいいでしょう。 つまり、Far の距離である 50 に達したときに減衰の効き具合が最大になり、それは 0.1 だという。 2 x 0.1 = 0.2 なので、距離 50 では 0.2 という太さになっているという意味ですね。

その下の Profile のところで、この減衰のカーブが決められます。 Bias モードなら、Power 0.5 (デフォルト)ならリニアに減衰します。 つまり Near から Far に向かって、一定の割合で細くなって行きます。 0.25 とか 0.9 など、0 から 1 の間でどちらかに寄せた値を入れると、「最初の方でグイっと細くなってそれ以降あまり変わらず」 とか 「最初はあまり変わらないんだけど、ある距離を過ぎるといきなりグイっと細くなる」 というようなコントロールが効きます。 使いにくいけどね。







本題に戻りますが、この状態でレンダリジョンを描いてみると・・・・・

It_3b

もう誰がどう見てもスケキヨにしか見えません。





本題であるスケキヨはちょっとおいといて、線の太さの話に脱線しますが、ええと、男の顔の中身をよく見ると、目鼻などの線はちゃんと距離で細くなっていってるのが分かります。 しかし、一番外の境界線、つまり空間との境界をなす線は距離が遠くなっても細くなって行かないんですよね。


It_3


昔からこうです。 今も変わりません。 ほんと腹立ちます。



そこで、空間との境界も目鼻のように細くなっていくためには、どうなってればいいのかを考えたわけですよ。 


目鼻の線は、その線のいわばバックグラウンド(ヌケ)にあたる部分に、頭部そのもののポリゴンが存在します。 一方、頭部そのもののバックグラウンドは、何もない無の空間です。



ならば頭部のバックグラウンドにも何かあればいいんじゃいのか。


と思ってやってみたら上手く行っているように見えるというのがこの話です。

It_4

ほら、ちゃんと空間との境界も細くなって行くのが分かりますよね。 これをやりたかったんですよ。


上の画像の下部分を見ると分かると思いますが、スケキヨさんたちをすっぽり覆い尽くすように球体を置きました。 球じゃなくてもいいと思うんだけど、ひとまず無難に球を使いました。 これで、カメラから見たスケキヨのヌケは無ではなく、球体のポリゴンがあるという状態になったわけです。 そしてこの状態なら、空間との境界もちゃんと減衰してくれるわけです。 と言うよりは、ヌケに球体があるということは、そもそも空間との境界というものが存在してないわけですね。 ヌケが無ではなく何か存在してくれていればちゃんと減衰するらしいというのは目鼻の観察で分かってますからね。


とまあ、そんだけです。 この問題が出たら、何かで覆って、「無の空間」 との境界をそもそもなくしてしまえばいい、という話でした。








あと、たまに球体ではなくキューブとかで囲いたくなることもありますね。 下の画像のような、地面との接地(交差)部分に線が欲しい時とか。

It_5

でも、ヌケにキューブのエッジが見えてしまい、そこにインクの線が描かれてしまいます。 この線は要りません。



この線を消す方法は、形状でいじる、つまりエッジをベベって丸くしてやってもいいんでしょうけど、俺はマテリアルで対処してしまいます。

It_6

キューブのマテリアルに Toon_Host を与えてやって、Ink タブBoundaries のところにある Interior オフにします。 インテリア、つまり内側ですね。ブツの内側に描かれるべき線はいっさい描かないという設定です。 キューブのエッジは、キューブ内部に属するエッジですから、インテリアの線がオフならエッジの線も描かれません。 これで桶。


ちなみに Bypass でオフにしちゃうと、このキューブが関与する線は一切描かなくなってしまうから、当然スケキヨと地面との交差部分の線も描かれなくなってしまい、これでは意味がありません。 

Silhouette はキューブがキューブ以外のオブジェクトや空間との境界で描こうとする線ですから、これをオフにしてもダメです。 スケキヨはキューブにとっては自分以外ですから、そことの境界が描かれなくなってしまう、つまり、やはり交差部分に線を描いてくれなくなってしまうからです。


このシーンファイルのダウンロード  Ink_Sukekiyo.zip (XSI 2012)









さあ曲行きましょう。

スケキヨさんも大ファンで、親戚かもしれない犬神サーカス団さんです。



いやあ、いつもベタベタのネタで最高ですね。 素顔の凶子ねえさん、可愛いじゃない。


最近 「犬神サアカス團」 に名前を変えたみたいです。一度はライブを観に行きたいバンドですねえ。






.



. 

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

2013年8月20日 (火)

全体AO。

何年も前から同じこと何回もやってんのに、久しぶりにやろうとするとやり方を忘れているといういつものパターンでしてね。 だからメモります。 また忘れたらここでカンニングする。


全てのマテリアルにアンビエントオクルージョンを入れたくなることって、あるじゃないですか。 でも全部のマテリアルでレンダツリーいじるのは面倒ですよね。 スクリプト書いて一気に処理でもいいですけど、レンダツリーの構成がマテリアルによって全然違ったりして、一定の法則で AO シェーダを挟み込むようなスクリプトが書きづらいことも多いです。


なので 個々のマテリアルの方はいじらずに、レンズシェーダを使って全体にイッキに AO してしまおう というアレです。


たぶん6年も7年も前から、XSI Base みたいなところでよくこの質問が出ていたと思うんですよね。 「シーンの中のブツすべてに、AO 効果があるレンダがしたいのだが、簡単にできるかしら?」 という。  それを見てやり方を覚えたのですが、昨日久しぶりにやろうとしたらやり方忘れていて焦ったので、書いておきます。



Globalao


画像の通りなんですがね。 こんなやり方でいいでしょうかね? 他にもっといいやり方ありますかね?

色んなブツが、色んなマテリアルを持っています。色も違うし、シェーダの種類も違う。Phong だったり Lambert だったり Arch Mat だったり。

でもレンダされた絵には、マテリアルに関係なく全てのブツに AO 効果が入っています。 これをやりたかったんです。  青いキューブなんか、コンスタントシェーダなんですが、AO 効果が載せられているため、コンスタントシェーダであるにも関わらずキューブの形状が認識できます。




考え方としては、レンズシェーダを使って全体に効果を及ぼしてしまえというものです。

と言うのは、レンズシェーダは基本的に、そのレンズから見えるもの全てに対して何かをしようとするので、これを利用して特定の効果を全体に乗せるわけです。 この場合は AOシェーダの効果を乗算(Multiply)で乗っけています。 それぞれがどういうマテリアルを持っているかとかは関係ありません。 レンズシェーダは、とにかくそこに見えるもの全てに対して何かをするわけですから。 レンズシェーダも色々ありますが、基本的には何でもいいです。 見えるもの全部に対して効く、という特性はどのレンズシェーダでも同じですから。

ただし、そのレンズシェーダが持つ効果自体はオフにしてやらないといけません。 上の画像では、たまたま Lens_Background_Color という、背景色を黒以外にすることができるレンズシェーダを使っていますが、別に黒以外の背景色が欲しいわけではありません。専らレンズシェーダの持つ 「そこに見えるもの全てに対して何かする」 という特性を利用したいだけであって、レンズシェーダの持つ効果(この場合は背景色設定)は不要なわけです。 だから、enable のチェックボックスをオフにして、背景色を設定する効果はオフにしてやっているわけです。





一応手順を書いておくと、

まずカメラ、あるいは Pass に対してレンズシェーダを与えます。 上の画像の場合は Pass に与えています。

レンズシェーダの種類は何でもいいはずですが、レンズシェーダの効果をオフにできるスイッチがあるものを選ばねばなりません。上の Lens_Background_Color ってのはそれができるので、良いんじゃないですかね。 あと、Toon_Ink_Lens なんかでもいいと思います。 Toon_Ink_Lens には Bypass というスイッチがあるので、これをオンにしておくと効果をバイパスする、つまり Ink のラインを描く効果はオフになりますから。

そしてレンズシェーダの結果に対して、レンダツリーで何らかのシェーダなどを間に挟みこんで、欲しい効果を作り出します。 上の場合は AO シェーダを Mix 2 Colors の乗算モードで合成しています。  以上。



このレンズシェーダの 「見えるもの全てに」 の特性を使って、AO に限らず色々面白いことができそうな気がしますよね。 やったことないけど。





あ、本題から外れますが念のために言っておくと、上の例では AO を乗算モードで合成していますが、AO ってものは全体に乗算で合成するのが正しい使い方だ、とかそういうわけでは全然ありませんので、そこは誤解なきようご注意下さい。 

AO はアンビエントオクルージョンなんだから、基本的にはアンビエント部分(直接光が当たっていない部分)に対して合成してやるべきものとしてコンポジットのセオリーがあると思うんですが、実は俺はよく分かってません。 メンタル霊のスタッフだった、誰だっけ、あの人、ZAP さんだっけ、その人のブログで正しいとされる合成方法が記述されていたので、ちゃんとやる時はそれを調べて真似しましょう。 っていうか最近専業コンポジターが多くなったので、その人たちに聞けばすぐ分かる・・・のかな?

まあ、AO の効果をどう使うかはそのアーティストの勝手なので何でもいいんですけど、ただし、一時期、「AO ってものは全体に乗算合成するのが正しい(AOの使い方としてもともと想定されている)使い方だ」 と思い込んでいる人が多かったように見えたので、そういう使い方をしてもあなたの勝手だし俺もそういう使い方よくしてきたけど、本来の AO の使い方(合成方法)として正しいわけではないですよ、ということを念のため書いているだけです。







ちなみに俺の場合、実際の本番素材作りにおいて AO Pass が必要なとき、あるいはビューティPass などに AO 効果を乗せたいときに、このようにレンズシェーダを使ったことはあんまりなかったですね。 というのは、この方法だと AO シェーダの設定はひとつだけになってしまいますからね。 オブジェクトによって AO の設定を変えたくなることもあるので、結局は各自のマテリアルに対してひとつひとつ手作業することの方が多い気がします。


じゃあなんでこの方法をメモするのかというと、簡単お手軽に全体にババっと AO を乗せたいこともよくあるからですよ。

よくあるのはモデリングのチェック画像を作るときなどですね。 AO があるとブツの形状が認識しやすくなるので、モデリングのチェックには便利です。 でも全体が白黒の AO だとかえって見づらくて形状がよくわからない。 だからモデリング時には各オブジェクトに色分けして見やすくする程度の適当なマテリアルをサッと与えておいて、チェック画像をレンダするときにレンズシェーダを使って丸ごと AO を加えてやるという。 

俺の場合こんな風に、本番用じゃなくて仮のレンダ用にこの方法を使うことが多いですかね。





とかなんとか。

.

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

2013年6月25日 (火)

前後シェーダ。

昨日、某さんに質問されて答えたのですがね。その話を書いておきます。 意外と知られてないのかな前後シェーダは。


ポリゴンの(法線という意味での)オモテ面とウラ面で違うマテリアルを持たせるには? という話でした。



結論から言うと、法線のオモテウラで 「マテリアル」 を別々に持たせることは不可能であり、ひとつのマテリアルの中で Front-Back Switch シェーダを使ってオモテとウラのツリーを分岐させなさいという話です。 そんだけです。

Fb

まあ、そんだけです。 

これ以外の方法は知らないんですが、あるかな?



あ、あとは、メンタル霊の設定でレンダする面がどうなってるか気にするべきでしょうね。

Face

デフォルトは両面ですが、まあ大抵の場合はこれでいいでしょうけど、ウラだけ別レンダしたいとかなら要注意というか。


例えば Back にするとオモテ面はレンダされないわけですが、そのオモテ面の向こう側に同じオブジェクトのウラ面があった場合、オモテ面はいわば 「透過」 されるかのように無視されてウラ面がレンダされるので、その部分のアルファチャネルは白になります。 

なので、 「ウラだけレンダしたい、そしてアルファチャネルはウラが見えているところだけに生成されて欲しい、オモテ面が見えているところはアルファゼロで抜けていて欲しい」 というレンダをしたい場合は、単純にレンダする面を Back にすればいいという話ではなくなりますよね。



そういう時は、俺はこうしています。

Fb2

右下を見ると分かりますがレンダする面は both です。 両面です。

そしてオモテ面には、組ミ(くみ)シェーダをブッ刺します。組ミシェーダってのは俺が勝手にそう読んでいるだけであって、まあ、ただのコンスタントシェーダですが、RGBA 全てゼロにしてあるものです。 A もゼロというところがポイントで、こうするとアルファがゼロのまま抜けた絵が出来てくれます。 A がゼロなら RGB は何でもいいのかと言ったらそんなことはなく、RGB も A も全部ゼロの時にだけそう作用します。 詳しくは大昔のこちらの記事 を。

ということで、オモテ面は抜きになり、ウラ面は通常にレンダされるという、望みの状態になりました。 画像のレンダリジョンを見ると分かると思います。

もっとシンプルな方法あるかな・・・?





あと、この Front-Back Switch って、メンタル霊以外ではどうなるんだろう? V-Ray や Arnold でも使えるんですか?




一応マニュアルも見てみたら・・・・

http://download.autodesk.com/global/docs/softimage2013/en_us/userguide/index.html?url=files/shaderpresets162.htm,topicNumber=d30e688414

うーむ、あんまりいい説明じゃないですねえ・・・・。 レイが当たってどうしたとか、プリミティブサーフェスとか、なんだか必要以上にテクニカルな書き方をしている感じですね。 プリミティブサーフェスって何? あと、法線という言葉が出てこないと違和感ありますね。 「オブジェクトの両側に別の質感を与えたい場合に・・・」 とか書かれてるけど、「オブジェクトの両側」 ってなんだよそれ。 法線のオモテとウラの両側という話をしないといけないんじゃないの?  必要ない部分はテクニカルに書いといて、シェーダの仕様を説明する大事なところはテクニカル用語を使わずに平易な言い方で書くとか、なんですかそれは。


日本語版を見てみると・・・・・

http://download.autodesk.com/global/docs/softimage2013/ja_jp/userguide/index.html?url=files/shaderpresets162.htm,topicNumber=d30e500097

もっとひどいw  得意の、困ったらカタカナ方式って感じだw 

だいたいね、「面しているポリゴンの正面にあるプリミティブ サーフェイスにレイがあたるとき、表示されるカラーを定義します」 ってなんですかこの説明。 もう、さっぱり意味不明の言葉ですよね。  これ書いたあなた、ご自分でも当然意味わかってないですよね? ええ、ローカライズを担当したあなたのことです。 ひどい日本語ですね。 日本語じゃないのかな。 嘔吐デスク語なのかな。

しかも 「 ・・・・[Surface]シェーダの[減衰]パラメータに直接接続されます」 って、なんですかその 「減衰パラメータ」 ってのは。 そこ、原文は diffuse ですよ。 ディフーズって、拡散 の意味はあっても 減衰 の意味はないと思うんだがなあ。明らかに誤訳だと思います。 

「拡散されたら、結果的にエネルギーは減衰するじゃないか」とか言いそうですけどそれは屁理屈ですよ嘔吐デスク様。 そもそもね、ここはシェーダの diffuse の話をしているんだから、拡散とか減衰とかそういうコトバをただ使っただけではシェーダの説明として成り立たないじゃないですか。 原文に diffuse というコトバがある以上どうしても diffuse をホンヤクした日本語を含ませなければいけないのなら、せめて拡散反射光とでも言わないと。 まあ拡散反射光でも分かりにくいですけどね。 要は表面の色のことですよね。 ここは、得意のカタカナ作戦でディフューズと書いた方が良かったですよね。 こんな風にカタカナ作戦の適用方針がブレブレであることからも、訳している人が意味をわかってないことがバレバレで、非常に痛いです。 マニュアルって説明するためのものじゃないですか。 この、ちっとも説明になってない不思議な日本語を書いておいて、その不思議さを隠そうともせず、さあ日本語マニュアルできましたご覧下さいと言われてもですね、非常に痛いのです嘔吐デスク様。 ディスって申し訳ないですけど、本気でそう思うのです。 高額商品の取扱説明書がこんなだなんて、恥じるべきだと思いますよ俺は。


ちなみに Maya 様の取扱説明書は、XSI どころではないほどそれはそれはもう不思議ちゃんで、さすが世界の Maya 様、高度な文明の Maya様、識字率の低い XSI 村の人間には難しすぎて分かりません(゜∀゜)  理解できなさ過ぎるためまだ上手くディスれなくて、実に歯がゆいです。

.

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

2012年9月26日 (水)

メンタル霊のパラメータの名前。

よく Pass Override をやるんですがね。
例えばこの Pass だけリフレクションの反射回数を50回に上げたい、とか。


昔はその Pass に Mental Ray Option のローカルコピーを作るしかなかったのに、今は Pass Override ができて便利ですね。



でもね。
オーバーライドを作るとき、
オーバーライドしたいパラメータの名前がわかんないんですよこのハゲ。




例えば上に書いたリフレクションの回数などは、まだわかります。 TraceDepthReflection です。 オーバーライドするときドロップダウンする Explorer から探せます。


でもさっき、ある Pass で Primay RaysType を Scanline から Rasterizer に変えたかったんだけど、オーバーライドを作成する時に Primary Rays という名前のパラメータが見つからなくて苦労しました。


で、あれこれやってみたところ、Mental Ray の PPG上で Primary Ray の Type と表示されているパラメータは、実は Scanline という名前のパラメータでした。



ハァ?



インターフェース上は Primary Rays という名前で、そのパラメータの「値」はデフォルトでは Scanline と表示されており、ドロップダウンリストから選べる他の「値」としては RasterizerRaytracing があるわけですが、「値」ではなく内部的なパラメータ名(スクリプトネーム)が Scaneline って、どういうこと?  "Scanline" という名前を持つパラメータの値が "Scanline" だということですよ。 なんだそれは。

と思ってスクリプトエディタで履歴を見てみると、ドロップダウンから Scanline を選んだ時は、 Scanline というパラメータの値として 1 がセットされている。 Rasterizer を選ぶと 2  になっている。

つまり、「値」として Scaneline とか Rasterizer を選んでいるように見えて、実はそれはインターフェース上の見かけだけのことであり、実際には 1 とか 2 とかが「値」としてセットされてるということですね。 うーむ。

まあ、それは仕方ないかもしれない。俺も自分で書くツールでそうなってしまうこともある。 でもね、パラメータ名が Scanline ってなんなのよ。 UI 上は Primary Ray の Type って表示されてんだからさ。 おかしいでしょうそれ。 オーバーライドする時探せないじゃないですか。 いくらなんでもひどいでしょうこれは。 わざとやってんの嘔吐デスク様。 っていうかこれはアビッド様かなあ。 



これと同じようにね、オーバーライドしたい時って、いつも 「それ、なんていう名前のパラメータなんだろう?」 という所で困るのですよ。 だって UI 上と全然違う名前のものが多いんだもん。

あの変な Explorer からオーバーライドしたいパラメータを探して選ぶというインターフェースがまずいかんのですよね。そうではなく、例えばあらかじめオーバーライドしたいパラメータを PPG 上でマークしておき、Overdide の PPG の中に 「マーク中のパラメータに対してオーバーライドする」 とかいうボタンを作ればいいんじゃないでしょうかね。 自前でやろうかなあ。




非常にわかりにくいです。昔から。
嘔吐デスク様。
長年苦労してます。
悪意さえ感じます。
普通はスクリプトエディタなんて見ないんだから。
いいかげんどうにかして下さい。
いいですか。
頼みましたよ。
このハゲ。





.
.

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

2012年9月14日 (金)

パーティションの掟。

うーむ。

Background_***_Partition は、特別なんですよ。


新規のオブジェクトとかが自動的に入る場所ですからね。 レンダの事故が起こらないためにも、Background Partition のレンダビジビリティは基本的に Hide にしておきべきだと思いますし、そもそも Background Partition の名前を完全に変えてしまって、どれが Background Partition なのか分からなくなっている状態なんて、言語道断です。


そういういけないデータを扱うときは、もう、スクリプト書いていけない子を発見するしかありません。



JScript
------------------------------------------------------------------------

var oBackgroundPartitions = XSIFactory.CreateObject( "XSI.Collection" );//    全てのBGパーティションを格納する容器
var oPasses = ActiveProject.ActiveScene.Passes;
//    全てのPass
for ( var i=0; i<oPasses.count; i++ )
{
    var oPartitions = oPasses(i).Partitions;   
//    その Pass の全ての Partition
    for ( var j=0; j<oPartitions.count; j++ )
    {
        if ( oPartitions(j).Background ) oBackgroundPartitions.Add( oPartitions(j) );
//    BGPartition なら格納
    }
}

//    ここまでで、まずは全Passの BGPartition が引っかき集められた

var oFuckinBackgroundPartitionsRenamedInVeeeeryBadWay = XSIFactory.CreateObject( "XSI.Collection" );//いけない名前のBGPartitionを格納する容器
for ( var i=0; i<oBackgroundPartitions.count; i++ )
{
    var oPart = oBackgroundPartitions(i);
    if ( oPart.PartitionType == siObjectPartition ) TheName = "Background_Objects_Partition";
//あるべき名前(オブジェクト)
    else TheName = "Background_Lights_Partition";
//    あるべき名前(ライト)

    if ( !oPart.Name.match( TheName ) ) oFuckinBackgroundPartitionsRenamedInVeeeeryBadWay.Add( oPart );//いけない名前のやつを格納
}

//結果報告 & いけないやつセレクト
Logmessage( "全てのバックグラウンドパーティション : " + oBackgroundPartitions.count );
Logmessage( "Background_***_Partition を含まない名前にリネームされてしまっているバックグラウンドパーティション : " +  oFuckinBackgroundPartitionsRenamedInVeeeeryBadWay.count );
SelectObj( oFuckinBackgroundPartitionsRenamedInVeeeeryBadWay );

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

このスクリプトの場合は、Background_Objects_Partition (ライトの場合は Background_Lights_Partition)を含まない名前になってたら、悪い子だということにしてあります。 法則を変えたいなら TheName のところを変えれば良い。

幸い、スクリプトを書けば Background パーティションかどうかは見分けられるのですね。 Partition オブジェクトの Background プロパティです。 名前がどのように変えられていようとも、このプロパティで true が帰ってくるパーティションは、Background パーティションです。 手で削除してみて削除できないパーティションならそれは Background パーティションなんですが、見分けるために削除してみるとか馬鹿らしいですよね。 まあ、こんなスクリプトを書かなければいけないシーンデータを扱うのが一番馬鹿らしいのですが。とかなんとか。




結果的にスクリプトによって判別はできましたが、スクリプトでトラッキングできればそれで良いわけではありません。ちゃんと掟を守らなければなりません。



俺的掟:

●バックグラウンドパーティション判別可能にせよ

Background_***_Partition をリネームする場合は、せいぜいアンダーバーを付けるとか程度にしておいて、ひと目でそれが Background パーティションであるということが分かるようにせよ



●バックグラウンドパーティションはハイドせよ


Background_***_Partition は、レンダしないパーティションにせよ。
 つまりレンダビジビリティは Hide にせよ。 ビュービジビリティはまあ、レンダ的にはどうでもいいや。



●男らしくせよ


レンダすべきパーティションのレンダビジビリティは全て Show にせよ。
 レンダしないパーティション(Background含む)は Hide にせよ。 つまりレンダ可否はオブジェクトレベルや Group や Layer に頼らず、一番強い存在である Partition でオンかオフにすることによって一元管理せよ。 No Effect 禁止。 男らしく白黒はっきりせよ。 女も男らしくせよ。



これがレンダ事故を避けるためには必須です。 異論を待つ。




.

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

2012年9月12日 (水)

淫婦裏嫉妬。

これもたった今気づいたんですがね。

インプリシットオブジェクトって、パーティションに参加できるんですか?

Implisit

できてますよ?

インプリシットって、レンダできないオブジェクトじゃないですか。ヌルとかカーブとかレンダできない種類のオブジェクトは普通パーティションに入れないですよね。 でもどうやらインプリシットだけは入ることができる。 なんで? 昔からこうでしたっけ?  他と違ってインプリシットだけ、レンダできない種類のオブジェクトであるにも関わらず、パーティションに入ることができる理由は、何でしょうかね? それとも最近の XSI は、インプリシットをレンダする機能が付いたのでしょうか?


いやまあ、GUI 上で色んな操作をしている上では問題にならないんですけどね。 問題になるのはスクリプト書いている時でね。 こういうこと知らないと、ツールを開発するときにここがトラップになってつまづいたりするわけですよ。 処理対象外にしていたはずのものが対象になっていたりその逆だったり、まさかインプリシットがパーティションに入れるとは思ってなかったものでそこらへんはノーマークで、関係のない部分をいじくってスクリプトを壊してしまい動いていたものも動かなくなってモニタを青山通りに連続遠投するとか、よくやります。


スクリプトで、パーティションに入ることのできるオブジェクト(レンダ可能なオブジェクト)かどうかを一発で判別できる機能が欲しいと思いませんか。 昔から思っているんですけど。 パーティションに入れる種類のオブジェクトって、ポリゴンメッシュ、サーフェスメッシュ、ポイントクラウド、インスタンス、あとなんでしょうかね?  その辺を一括で判別できるよう、siRenderableGeometryID とか X3DObject.IsRenderable とか、そういうの付けて欲しいんだよなあ。 スクリプト書きがすげえ楽になるはずです。嘔吐デスクさま。



っていうか、パーティションに参加可能・不可能(レンダ可能・不可能)を判別するもっといい方法、何かありますかね?

俺はいつも、愚直に Type とか調べて 「もしこいつがポリゴンかサーフェスかポイントクラウドかインスタンスだったら云々」 とか書いてます。 こういう書き方だと、見落としている Type があるといけないなあ、といつも思ってます。




.


.

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

2012年5月17日 (木)

テクスチャリンク切れはもううんざりですよね。

ええ、うんざりです。





ひとまずやっつけで。



JScript
----------------------------------------------------------------

DefPath = "";


var oImageSources = FilterImageSource( Selection );
if ( oImageSources.count == 0 )
{
    Logmessage( "ドルァ" );
}
else
{
    var oP = XSIFactory.CreateObject( "CustomProperty" );
    oP.name = "テクスチャリンク切れはもううんざりですよね。";
    oP.AddParameter2( "sPath", siString, DefPath );
    var oL = oP.PPGLayout;
    oL.AddSpacer( 0, 150 );
    var oItem = oL.AddItem( "sPath", "Path", siControlFolder );
    oItem.SetAttribute( siUINoLabel, true );
   
    Inspect = InspectObj( oP, null, null, siModal, false );
    if ( !Inspect )
    {
        PicPath = oP.sPath.value;
        for ( var i=0; i<oImageSources.count; i++ )
        {
            var oSrc = oImageSources(i);
            OldPath = oSrc.FileName.value;
            aPath = OldPath.split( "\\" );
            NewPath = PicPath + "\\" + aPath[ aPath.length-1 ];

            Logmessage( OldPath + " -> " + PicPath + aPath[ aPath.length-1 ] );   
            oSrc.FileName.value = NewPath;
        }
    }
    else
    {
        Logmessage( "モルァ" );
    }
}


function FilterImageSource( in_Objs )
{
    var oCol = XSIFactory.CreateObject( "XSI.Collection" );
    for ( var i=0; i<in_Objs.count; i++ )
    {
        if ( in_Objs(i).type == "ImageSource" )
        {
            oCol.Add( in_Objs(i) );
        }
    }
    return oCol;
}

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



使い方。
ExplorerSources/Clips モードにします。
テクスチャのリンクが切れている Image Source を選択します(複数可)。
スクリプトを実行します。
ダイアログで、テクスチャがあるフォルダを選択してOK押します。
するとテクスチャのリンクが指定したフォルダ以下のその画像ファイルに貼り直されます。
以上。



エラーチェックも何もしていません。 そのフォルダに実際にそのテクスチャ画像ファイルがあろうとなかろうと、強制的に Image Source の FileName パラメータを書き換えます。 
なので目的の画像ファイルが存在しないフォルダを選んでしまうと、そもそもリンク切れではなかったものがリンク切れになってしまうことすらあり得ます。


基本的に、テクスチャ画像ファイルのファイル名は同一のままフォルダだけ移動させたとかそういう時に使います。そのフォルダ以下に、元のファイル名と同名でテクスチャ画像ファイルがあると分かっている時以外は、使ってはいけません。かえっておかしくなります。





いずれ改良するつもりですが、現状は最低限仕様です。危険です。


ちなみにスクリプトの冒頭でデフォルトのフォルダPathを書いておけば、起動した時にその Path が既に入力されている状態になっているので、少し楽かも知れません。

  DefPath = "";


この "" の中に、C:\\junki\\Pictures などと書いておけばいいということです。 なぜかバックスラッシュは2個 \\ と書かねばなりません。 これ、なぜなのでしょう。 エスケープなんとか? 違いますか。



今後の改良点:

フォルダの存在の有無のチェック
フォルダ選択だけでなく、ファイル選択によっても Path を選べるようにする
テクスチャ画像ファイルが無かった場合はスルー
ImageSource 以外のものを選んでいても動くようにする
(例えば ImageClip とか、MatLib とか)


とかなんとか。
やるかも知れません。やらないかも知れません。分かりません。



ではでは。

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

2012年4月 6日 (金)

このPassでもそのパッていしおん。

Pass分け分けPartition分け分けなわけですよ。



他の Pass 以下にあるパーティションをカレントPass(現在 Pass) に複製するスクリプトです。


もうちょっと細かく言うと、カレントPass ではなく他の Pass 以下に存在する Partition を、カレントPass 以下で再構築し、Partition に属するオブジェクトも同じ状態し、マテリアルやオーバーライドやビジビリティなどもろもろ設定も複製するという、スクリプトです。





JScript
------------------------------------------------------------------------

// ConoPassDemoSonoPatTayShion ver 0.0025

//    現在 Pass を取得
var oActPass = ActiveProject.ActiveScene.ActivePass;

//    選択しているもののうち、パーティションだけを引っかき集める(現在Pass以下のパーティションは無視)
var oParts = FilterPartition( oActPass, Selection );


//    新規に作られた/発見されパーティションの入れ物
var oNewParts = XSIFactory.CreateObject( "XSI.Collection" );

//    選択していたパーティションをループし、現在 Pass 以下に同名同種のパーティションがあるかどうか探し、
//    あればそのままメンバぶっ込むし、なければ新規に作ってぶっ込む

for ( var i=0; i<oParts.count; i++ )
{
    var oSrcPart = oParts(i);   
//    元のパーティション
    SrcPartType = oSrcPart.PartitionType;   
//    元のパーティションの種類
   

    //    現在 Pass 以下で、同名のパーティションを探す (Filter メソッドで、名前でより分け、見つかった最初のものを返す)
    var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);
    if ( oSamePartitionInThisFuckinPass )
    {
        DestPartType = oSamePartitionInThisFuckinPass.PartitionType;
        if ( SrcPartType == DestPartType )
        {

            //    名前も同じ、種類も同じパーティションが見つかった → 新規で作らず利用
            var oDestPart = oSamePartitionInThisFuckinPass;
            logmessage( "行き先パッていしおん (既にありますた) --> " + oDestPart + " -- Type : " + oDestPart.PartitionType );
        }
        else
        {

            //    同じ名前のパーティションが見つかったけど、種類(オブジェクト or ライト)が違った場合は、それと分かるように名前を付けて新規作成
            var oDestPart = oActPass.CreatePartition( oSrcPart.name + "_PartitionType" + SrcPartType, SrcPartType );
            logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
        }
    }
    else
    {
       
//    同じ名前のパーティションが見つからなかった場合は、新規作成
        var oDestPart = oActPass.CreatePartition( oSrcPart.name, SrcPartType );
        logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
    }

    //    行き先パーティションに、元パーティションのメンバ追加 (戻り値は、メンバ追加に問題があれば false になるらしい)
    NothingFuckinWrong = oDestPart.AddMember( oSrcPart.Members );
   

    //    Object Model でコケた時の保険
    if ( NothingFuckinWrong != true )
    {
        MoveToPartition( oDestPart, oSrcPart.Members );
        Logmessage( oDestPart + " : メンバ追加がなにやらヤヴァいらしいのでコマンドでやりますた。", siWarning );
    }
    else
    {
        Logmessage( oDestPart + " : メンバ追加しますた。" + oDestPart.Members.GetAsText() );
    }
    oNewParts.Add( oDestPart );
   
   

    //    元パーティションのもろもろを行き先パーティションにコピー
    oDestPart.viewvis.value = oSrcPart.viewvis.value;
    oDestPart.rendvis.value = oSrcPart.rendvis.value;
    oDestPart.selectability.value = oSrcPart.selectability.value;
    oDestPart.viewplaybackvis.value = oSrcPart.viewplaybackvis.value;
    oDestPart.ghosting.value = oSrcPart.ghosting.value;   
   

    //    元パーティションにマテリアルがあれば、新パーティションにも適用
    var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);
    if ( oPartitionMat )
    {
        oDestPart.SetMaterial( oPartitionMat );
        Logmessage( oDestPart.name + " : マテリアルアサインしますた --> " + oDestPart.Material );
    }
   

    //    元パーティションにオーバーライドがあれば、新パーティションにも複製
    var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );
    for ( var j=0; j<oOverrides.count; j++ )
    {
 
//    パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
        if ( !oOverrides(j).name.match( "VisibilityOverride" ) )
        {
            CopyPaste( oOverrides(j), null, oDestPart, 2 );
        }
    }
    var oNewOverrides = oDestPart.Properties.Filter( siOverrideType );
    for ( var j=0; j<oNewOverrides.count; j++ )
    {

 //    パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
       if ( !oNewOverrides(j).name.match( "VisibilityOverride" ) )
        {
            oNewOverrides(j).name = oOverrides(j).name + "_dup1";
            Logmessage( oDestPart.name + " : Override 複製しますた --> " + oNewOverrides(j).name );
        }
    }

}

//    行き先になった全てのパーティションを選択しておしまい
if ( oNewParts.count != 0 )
{
    SelectObj( oNewParts );
}
else
{
    Logmessage( "No fuckin' valid partitions selected. Fuck you.", siError );
}



//    Partition だけ返すファンクション(現在Passのは除外)

function FilterPartition( oActivePass, oObjects )
{
    var oParts = XSIFactory.CreateObject( "XSI.Collection" )
    for ( var j=0; j<oObjects.count; j++ )
    {
        if ( oObjects(j).IsClassOf( siPartitionID ) )
        {
            if (  oObjects(j).Parent.fullname != oActivePass.fullname )
            {
                oParts.Add( oObjects(j) );
            }
        }
    }
    return oParts;
}

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

※追記
早速修正しますた。赤い字のコメント部分

これでたぶんエラー出ない・・・と思う



今週使いまくってます。 まずまず使えるではないか。
まあ、自分で要るもの書いてんだから当たり前ですがね。





例えばですが、

Cono1

hogehoge という Pass で色んなパーティションがあり、色んなオブジェクトが入っています。 オブジェクトもライトも。 で、パーティションにはマテリアルやオーバーライドも付いています。



これを、HAGE という Pass 以下でも再現したい場合に使うスクリプトです。

完全に同じパーティション構成の Pass が欲しいのなら Pass を複製すればいいだけですが、なんらかの事情でもう Pass は作ってしまっていて、他の目的のパーティションも混在するのでそれを作り直すのは面倒だったりなど、新規に Pass を作るのではなく既存の Pass を活かしたまま、特定のパーティションだけこっちの Pass でも再現したい、という場合に使います。  俺はしょっちゅうありますこういう場面。






使い方は、まずはこれからパーティションを作りたい Pass をカレントPass にします。 そして、Explorer から、複製の元になるパーティションをいくつでも選びます。

Cono2

↑まだパーティションを作っていない HAGE Pass を現在 Pass にしました。 

そして、複製の元になるパーティション、つまりカレントPass ではない他の Pass (この場合は hogehoge Pass)に所属するパーティションを、複数選んでいます。



この状態でスクリプトを実行すると、

Cono3

カレントPass である HAGE Pass 以下で、hogehoge Pass 以下にあったパーティション(選んでいたもの)を再現します。 というスクリプトです。


パーティションの名前は同じ。
所属するオブジェクトも同じ。
パーティションの各種 Visibility も同じ。
マテリアルがあればアサイン。
オーバーライドも複製(名前は同名が存在できないので _dup1 とか付けてます)。
ええと、他に再現すべき属性はありますかね・・・?

以上。













スクリプティング的に特筆するとすれば、


    var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);


同名のパーティションを探すのに、PartitionCollection.Filter を使ってます。 ループするより Filter の方が短く書けて便利、なのかな。どうだろ。 実行速度はどうなんだろ。

Filter メソッドの戻り値も Collection なので、(0) を付けて最初の一人を指定してやらないと Partition Object にたどり着けません。 ここは常に (0) でいいと思います。なぜならば、パーティションは同名のものが存在できないからです。 なので名前でフィルタして見つかった「最初のひとり」と指定すれば、安全にその名前のパーティションを取得できると思います。








マテリアルを探すときは、LocalProperties です。


    var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);


カレントPass にあるパーティションのマテリアルは Partition.Material で取得できます。なければ null が入ります。 しかし今回は、カレントPass ではなく他の Pass にあるパーティションに割り当てられているマテリアルを取得したいのです。 カレントPass以外にあるパーティションに対して .Material とやってもダメです。 .Material は、現在の状態しか気にしてくれません。

.Material ってのは、カレントPassだろうが Group で上書きされてようがなんだろうが、結果として現在どのマテリアルになってんのか、を返すと考えればいいんじゃないでしょうかね。 どうでしょうかね。 間違ってたら教えて下さい。

やりたいのは、あっちの Pass でどうなっているのかを調べてこっちでも再現するということなわけですから、.Material を使って「現在状態」を調べても意味はないということですね。 なので、LocalProperties を使います。 LocalProperties は、マテリアルに限らず、そいつに与えられた色んなプロパティが取得されます。 なので当然、戻り値は Collection です。 今回はその中からマテリアルだけを取得したいので、また Filter メソッドを使います。しかし今度は上の例とは違って、名前ではなく、タイプでフィルタしています。siMaterialType ですね。

そしてここでも (0) を使って 「見つかった最初のマテリアル」 を取得しています。 パーティションに対して複数のマテリアルは与えられません。 つまり、パーティションの LocalProperties からマテリアルだけをフィルタできたら、そのマテリアルが唯一のマテリアルであるはずです。 だから (0) を使って大丈夫です。 たぶん。




その後の Override でも、全く同じことをしてますね。


   var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );


LocalProperties から、siOverrideType でフィルタしています。 マテリアルと違ってオーバーライドの方はいくつでも与えられますから、(0) などとは書かずに取得しています。従って oOverrides には Collection が格納されます。 よって、次のループでひとりずつ呼び出して処理をしています。 ただし、今回の場合はコピペコマンドですから、もしかしてループの必要がなかったかも知れません。つまり Collection(複数)に対して丸ごと効いたかも知れませんという意味です。実験してないです。今気付きました。




オーバーライドの複製は CopyPaste コマンドを使っているんですが、他に方法を知りません。知っていたら教えて下さい。

CopyPaste コマンドには戻り値が無いもんですから、結果としてペーストされたブツへのリファレンス、つまりこの場合はペーストされたオーバーライドを取得する手がかりが、何もありません。 となると、ペーストされたオーバーライドをリネームしようとすると困るわけです。

今回の場合はたまたまですが、ペースト先は 「新規に作られたパーティション」 である場合が多いので、もう、行き先のパーティションに存在するオーバーライドをたった今ペーストされたばかりのオーバーライドであるとみなし、若い順にリネームしています。 新規で作られたパーティションである限りは、この方法でオーバーライドの名前はちゃんと複製元と一致すると思います(_dupとかは付きますが)。  

しかし、同名のパーティションがカレントPass以下に存在した場合は新たに作らずにそのパーティションを使う流れになっているため、たまたまそのパーティションが元々オーバーライドを持っていたりすると、コピー元とコピー先でオーバーライドの数が違ってくることになり、にも関わらず数値で若い順からリネームしているので、複製元と複製先でオーバーライドの名前が一致しなくなるでしょう。 でもまあ、知りません。 オーバーライドの名前を調べて一致したら複製しないだとか上書きするだとかも考えられますが、面倒なのでそこまでしません。








とかなんとか。






仕事をサボって書くブログは、なんて楽しいんでしょう。




ウソです。

ちゃんと裏ではレンダ回してます。
このスクリプトでパーティション分けたシーンをレンダしてます。




でも、もう僕は疲れたよパトラッシュ。






.

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