66 posts tagged “3dsmax”
仕事の合間を縫うようにmaxscriptを書く。
今回制作したのは、。Show Last RenderingとRAM Playerの中間的ツール。
画像保存しなくても、複数枚のレンダリング結果を比較することができる。ライティングやテクスチャ調整時のレンダリング結果を比較する時などに便利。
元は二年前くらいに作ったツールだけど、それをもう一度作り直してみた。アイディアとしては大したことはないけれど、動作の信頼性はかなり高い一品になりましたとさ。
もうひとつはシーン内で使用されてるテクスチャの一括パス置換ツール。
この手のアプローチは既に先人達が取り掛かっているので、max8のアセットトラッキングの機能を利用したアプローチで制作。
おもったより高速に動作するので、大量のテクスチャパス張替えに重宝すると思う。
上記二点はなかなか汎用性は高いとおもうので、Google Pageサイトで時期をみて公開する予定。
後は以前から業務で使用しているscript数点の細かいバグフィックスを行う。
通常運用してる分には問題ない部分だったけど、気付いてしまったのだからしょうがない。出来るときに直しておく。
正直、短時間でこんだけいろいろコード書けた自分に驚き。
まぁ大したもんではないとはいえ、ここ数年コツコツコード書いてきてたこと、それなりにチカラ付いてくるもんだね。
ある程度のレベルまでは『量が質を生む』ってのは、実践できたかな?
一ヶ月程前に作ったスクリプト数点が、場合によってうまく動作しないと報告があったので原因調査と修正。
一週間まるまるmaxscriptは弄ってなかったから、丁度よいリハビリ。
報告を受けたひとつは、オブジェクト名の文字列順番に関する問題。
配列等にオブジェクト名を格納して、ソート処理を行った場合、単純な文字列比較だと以下のような問題が発生する。
#("box_02","box_100","box_01","box_10")
--こうソートされることを期待
#("box_01","box_02","box_10","box_100)--実際の処理
#("box_01","box_02","box_100","box_10")
maxは末尾に数字の付いた名のオブジェクトをコピーすると、自動で語尾の数字もインクリメントしてくれる。しかし、01~99までは二桁でインクリメントされるが、100で桁数が上がったところから語尾数字が3桁になる。そのまま文字列だけの比較で配列をソートしてしまうと上記のような現象に遭遇する場合がある。
落とし穴なのは、単純な文字列比較ソートでも01~99までは問題なく動いてしまうことだ。
私も自分で書いたscriptの動作は確認しているつもりだったけど、試した時は30個の配列でしか試していなかったので、この問題に遭遇しなかったので、ついつい見過ごしてしまっていた。
ということで、これだといろいろよろしくないシチュエーションもあるので、キッチリqsortでソート用の関数を用意して、語尾の数字を取り出して厳密に処理してやる修正を加える。
手は抜くもんじゃありませんねorz
もうひとつは、マルチ/サブマテリアルに関する問題。
マルチサブは、複数マテリアルを配列でもっているのだけど、IDを飛ばして指定すると、指定したマテリアルの最大数とは関係なく、飛んだ番号の配列にundefinedのマテリアルを格納してしまうみたい。
たとえば、マテリアルの最大数を3として、3つのマテリアルのIDが順に1,3,5と指定した場合、以下のような動作を期待していたのだが...
#(mat_01,mat_03,mat_05)
--しかし実際は、こんな感じ。
#(mat_01,undefined,mat_03,undefined,mat_05)
最大マテリアル数決めてるぐらいなので、てっきり配列の数を確保し直して以下のようになっているものとばかり思っていたのでガッカリ。
実際自分で書いたscriptも、このundefinedの部分で引っかかっていた。とっとと修正する。
しかし、この仕様だとID飛ばして指定すると、とっても内部的にロスが大きそうなんだけど、なんかメリットあるのだろうか??
外部スタジオなどとの共同作業のプロジェクトにおいて、シーンデータの受け渡し時にテクスチャ等のパスの問題に悩まされることが多々ある。無論、テクスチャ名やディレクトリ構造等の決め事は事前にしてある前提においても、それらが配置されているネットワーク名やドライブ名の違いでパスが切れてしまうことは、よくある問題だ。
単発のプロジェクトであれば、シーンデータごとにテクスチャを収拾して相対パスで受け渡す。という方法もあるが、シリーズモノ等で大量のシーンデータが存在するような場合は、重複したマップも多くなるのであまり現実的な手段とはいえない。
そうなると、3dsMaxの基本設定で外部参照パスをひたすら追加していってとりあえずは凌ぐ、などの方法を取ることになるが、この方法の場合、ビットマップパスが大量にあったり(サブフォルダ的に配置されていたり)、大量のテクスチャを利用しているシーンのネットワークレンダリングの場合にビットマップの検索時のオーバーヘッドロスが大きくなるので、あくまで緊急回避的な手段であって、根本的な解決にはなっていない。
根本的解決を目指すならば、やはりビットマップパスをきっちり絶対パスで張り替えていくという判断になるが、手段として利用されるであろう3dsMaxのかなり初期のバージョンからあるBitmap/Photometric Paths Editorは、ビットマップが大量になると著しく実行速度が落ちる、サブフォルダーに対応してない、などなど、実際に作業するとメチャクチャ作業効率が悪いことに担当者は絶望すること請け合いである。
上記のようなことから、幾多の先人達によるmaxscript等でビットマップパスを一括で張り替えるツールが複数現存している理由でもある。
では、実際それらのツールがどのようにパスの張り替えを行っているのか、ソースコードを読み解いていくと、シーン内のマテリアルを総当りしてるアプローチがほとんどということに気づく。これはこれで至極まっとうな方法ではあるのだけれど、シーン内にマテリアルが多かったり、入れ子構造が深い、インスタンス化されている、などの想像できる条件分岐パターンはかなり幅があるので、多くのツールでは限定的な指定方法を採用するか、実行速度を犠牲にして対応しているようだ。
また、このアプローチの場合、シーン内に大量にビットマップパスがある場合など、条件によってはmaxscriptの使用メモリにかなり負荷がかかるようで、最悪処理中にMaxごとフリーズしてしまう可能性も高い。(実際いくつか試したツールでそうなった...)
それならばどうするか、他に良い方法はないのか、というところでMax8から導入された"Asset Tracking System"を利用したアプローチを試みる。"Asset Tracking System"は、元々データベースと連動させるバージョン管理ツールValutのMax上でのクライアントとして位置付けだが、シーン内に使われているビットマップパスの参照確認、パス張り替えツールとしても利用することができるという側面も持っている。特筆すべきことは、その動作速度が非常に早いところ。Bitmap/Photometric Paths Editorがシーン内のビットマップの検索に1~2分かかるようなシーンでも、10秒足らずで検索を終了する。
これを使わない手はない。幸い"Asset Tracking System"周りの操作は、maxscriptでもそれなりにサポートされている。
ということで、前置きが長くなったが、ビットマップパス一括張替えツール作った。
先人達のツールに対するメリットは、動作速度がとにかく速いってところ。そして、パスのルート側から何階層までを置き換えるか指定できるところだ。
従来のBitmap/Photometric Paths Editoでは特定の階層以下のパスを一括張り替えはできるのだけど、特定の階層以上のパス部分のみの張り替えは一工夫する必要があった。プロジェクト全体のメインディレクトリの構造は同じままで、それが配置してあるマシン名、ネットワーク名のみが違う、というようなシチュエーションのほうが遥かに多いので、この機能を盛り込んだ。
とはいうものの、今回のツールはまだまだ必要最低限の機能しか搭載しておらず。張り替え条件の細かい指定方法は、既存の先人達のツールには及ばない部分も多い。が、今後それらのツールのおいしい部分を取り込んでいければ、"Asset Tracking System"ベースの安定性と高速動作を生かした強力なツールになる可能性は十分に秘めている。
と、大したモノじゃないのに、さも凄そうに語ってみるw
ちょっとした思い付きで、以前書いたスクリプトの発展型を制作中。
で、今回ハマッたどうでもいいこと。
スライダーバーの.widthプロパティは、ロールアウト定義時にしか指定できません。
そもそもスライダーバーに.widthプロパティは存在しません。
やりたかったのは、ロールアウト上のスライダーバーの幅を条件に応じて可変させたかったのだけど、それがうまくできなかった、という話。
スピナーのscale値なんかもそうだけど、このあたりUIアイテムによって対応チグハグなのが嫌だよなぁ。widthプロパティなんかは基本プロパティとして、UIアイテム全部に定義されててもいいのに...
例によってサブロールアウトで包む方法で対処。
私が初めて作ったmaxplugin、"Transparent_ID"の紹介ページをGoogle Page Creatorで作った。
今思えば、まったくプログラムやったことが無い状態から、よく作ったもんだよなぁ。その後、社内でやっている作品のほとんどに使用してるわけだから、使用頻度はメチャクチャ高い。もちろん、現在のお仕事でも利用中。
作ってもあまり使われない、自分ですら使わなくなってしまうPluginやScriptも多いのだけど、コイツは本当に作ってよかったと心から思える。そんな一品です。
今回改めて機能の説明を書いたわけだけど、もっと改良したいポイントがいくつか浮き出たのは収穫だったかな。
仕事場にmax9用のテストマシンを調達できたので、max9用のコンパイルついでに少し手をいれたいところではある。
プロジェクトで、ちょっとした問題が発生し、シーン内でTranslucent Shaderを利用しているマテリアルに変更をかける必要が出来た。が、シーン内には大量のマテリアルがあり、それを手動で手直しするのは時間の無駄。それになによりオペレートのミスに繋がる恐れもある。
ということで、ツールを作ってみる。
ポイントになるのは、『Multi/Subマテリアル』や『Blendマテリアル』など、ひとつのマテリアルに複数のマテリアルが入れ子になっているものの検出。コード的には再帰的に摘出する関数を呼び出していけば入れ子部分の問題は解決するものの、問題はどれが入れ子になっているか、の検出方法だ。
例えば、『Multi/Subマテリアル』と『Blendマテリアル』では、入れ子部分のサブマテリアルへのプロパティのアクセス方法が違うのだ。たしかにチカラ技で、Case文か何かで『Multi/Subマテリアル』と『Blendマテリアル』、『Top/Bottomマテリアル』等で処理を分岐させていく方法もあるのだけど、さすがにそれはスマートじゃない。
ということで、汎用性を持たせる為にhoge.numSubsでプロパティの数調べて総当りでプロパティを取得、調査する、みたいな流れで実装。あれ?このコード、どっかでみたような...ああ、そうか!以前改良した『Matos_Changer』とアプローチおんなじなんだ。
他に、摘出したマテリアルをリストボックスに一覧表示。ダブルクリックしたら、マテリアルスロットに表示等のオマケ機能つけて完成。抜き出すパラメーターの定義部分のUIはあえて作らなかった。必要なら、その時合わせで定義書けばいいだけだし。だいたい、これで抜き出すパラメーターのUI作りこんでいくと、まんま『Matos_Changer』になってしまうw
まぁ、汎用性が高いアプローチなので、小物の割には作ったかいがあるスクリプトなんじゃないかなぁ。
某掲示板にて、こんな要望を出している人がいた。
ビューポートの向き切り替えるスクリプト探してるんですけど
Fキー2回でバックビューみたいなやつ
確かに、トグル動作させればビューポート関連のショートカット割り当てを減らせるのでなかなか良いアイディアかも。
ということで、チャチャッとコード書いてみる。
コードは単純なcase文だけの数行で終ってしまうので、オマケに以前作った軸変更ツールも付属してみたり。
配布はハルシノにしようかと考えたけど、せっかくGoogle Page Creatorを使い始めたのだから、そちらに紹介ページを作ってみることに。
Google Page CreatorのWYSIWYG 編集が、想像以上に貧弱なのでテーブルや箇条書きで思ったより手間取る。
で、なんとか作り終えて、さぁ公開!と思ったら、既にコードを掲示板に書かれた方がいたとさw
まぁ、せっかく作ったのだから公開しておこう
大量に同じオブジェクトを並べている場合に、1つ飛ばし、互い違いにパラメーターを変えたい場合がある。
実際に手動で作業をすると、N個おきにオブジェクトを選択するは以外に手間がかかる作業。[名前選択ツール]でちまちまひとつ飛ばしに選択するくらいしかないのではないだろうか?
ということで、選択中オブジェクト、もしくはシーン全体から"特定文字列"を含むオブジェクトのみをN個おきに選択するツール作った。maxの場合、同じオブジェクトをコピー配列として並べた場合、オブジェクト名を末尾に01、02と勝手にナンバリングした名前にしてくれる。その数字を利用してN個おきの選択を実現している。
このツール、もともとは数年前に単純な作業をラクしようと自分用の書き捨てコードがベース。UIもなく、毎度使う時に変数書き換えて使っていた。今回改めてUI付けて、いろいろな状況で使えるように汎用性持たせたら、意外とコード行増えた。やりたいことがシンプルなだけに、アプローチ方法はいくつもあるの。改めてコード書き直してみて、いくつかの小さい発見があったのは収穫だった。(というか、当時のコードにかなり問題があったw)
定期的に自分が書いたコードを見直すのも大切だね。
3dsMaxのパスコンストレインコントローラーは、適用後他のコントローラーに変換すると場所が吹っ飛ぶという痛い仕様。
さらに問題なのは、参照パスが何かにペアレントされると、そのパスを参照しているパスコンストレインを適用したオブジェクトの位置が変わってしまうという謎仕様。
ということで、パスコンストレインコントローラーをPostion_XYZコントローラーに、完全に位置/回転をキープしたままコンバートできるスクリプトを作った。
おまけで、変換前のパスコンストレインの情報をオブジェクトに書き込み、Postion_XYZコントローラーに変換後でも、いつでもパスコンストレインコントローラーに戻すことができるようにもしてみた。
つうか、位置が吹っ飛ぶ問題の対処は標準でなんとかしてほしいけどなw
朝から、プロジェクトで起きた問題の検証。
複数人で検証したところ、原因はmaxの精度に関する部分であることが判明。
う~ん、こりゃ気づかないわ...
以前から時々同じような現象に遭遇したことはあったけど、ちゃんと深いところまで検証したことはなかった。
そう考えると、いい機会だったのかもしれない。
午後からは問題を解決する為の小物スクリプトを数点制作。
同じことを手動でやると、ウンザリするほど面倒な手順を踏まないといけない。
結局そうやって、問題分かっていても素通りすることは過去多くあったので、ツール作って簡単に対応できるようにした。
長いスパンのプロジェクトでは、こうしたボトムアップ精神が不可欠なのだ。