2010年02月

2010年02月26日

パーティクルシステムのお勉強 その53 3ds max 2010

フィギュアスケートフリーを前に何でこんなに自分が緊張してるんだかw
ソワソワして落ち着かないなw

さて、今回はキャッシュオペレータについて調べてみたい。

まず下のようなシーンを作ってみた。

fig01

このシーンのパーティクルビューは以下の通りだ。

fig02


見ての通りいろいろなオペレータが入り組んでるし、パーティクルの挙動は発生した時点から逐次計算していかなければならないので、タイムスライダを動かしてみてもビューポートが更新されて表示されるまでに時間がかかる。反応が悪くなれば、当然作業性も悪くなる。下のGIFアニメは0フレームから100フレームに移動したりタイムスライダを動かしてみた時のビューポートの反応。とっても反応が鈍いのがわかる。

fig03

そんな時に役に立つのがキャッシュオペレータだ。キャッシュオペレータはパーティクルの状態をメモリに記録することで計算処理を置き換える機能がある。

例えば上のパーティクルビューのPFSourceのグローバルイベントのところにキャッシュオペレータを挿入して、タイムスライダを100フレームまで移動すると、

fig05


シーンの開始(今回は0フレーム)から100フレーム目までの全てのパーティクルの状態を記録する。当然ながらこの処理には今まで同様、時間がかかる。しかし、これで100フレームまでのパーティクルの状態が全て記録されたので、タイムスライダを0〜100の間でスクラブすると、ビューポートはサクサク更新されて追従するようになる。

下のGIFアニメはその結果。キャッシュオペレータを入れてから最初に100フレームにタイムスライダを移動した時の1回だけは反応時間が変わらないけど、キャッシュが済めばサクサク反応しているのがわかる。

fig04

ただ、キャッシュの内容とシーンの内容が変わってしまった場合は、キャッシュを更新しなくちゃならないので、その場合はやっぱり計算に時間がかかる。例えばパーティクルの数を変えたり、スピードを変えたりしたら、そうなるよね。

大抵の場合、修正する必要があるパラメータは複数ある事が多いけど、1つ直すたびにシーンは更新処理が始まるから、タイムスライダがシーンの後ろの方にあればあるほど、そこに至るまでのパーティクルの計算に膨大な計算が必要になる。だからそういう場合はパーティクルのビューポートで表示する数を減らしたり、タイムスライダを0にもってくるなりするわけだ。

fig06キャッシュオペレータはキャッシュ内容を更新するタイミングを変えられて、「更新」を「常時」から「手動」に切り替えてやれば、「更新」のボタンが押されるまでキャッシュされた部分の変更がシーンに反映されなくなる。だからパラメータを全部調整してから「更新」ボタンを押して、一挙にキャッシュとシーンを更新させる事が出来る。

上記の例ではグローバルイベントにキャッシュオペレータを挿入したけど、ローカルイベントにキャッシュを挿入すれば、そのイベント内だけキャッシュする事も出来る。

例えば、今回のシーンの場合、パーティクルが赤い円柱にぶつかって、飛沫が飛ぶようになっていて、飛沫のパーティクルはEvent03で処理されている。そこでEvent01とEvent02にキャッシュオペレータを仕込んでおけば、Event03の中のオペレータをいじっても、Event01とEvent02の部分はキャッシュとして更新されず、Event03の変更箇所の計算だけがなされるようになるので、とても軽く作業が出来るようになる。ちなみにキャッシュオペレータのイベント内での順番は特に気にする必要は無いらしいよ。

fig07

今日はとにかくソワソワしてmaxいじってる場合じゃないのでw続きはまた来週。シーンファイルはアップしておいたので、キャッシュを入れて試してみるといいよ。

maxまとめページ 



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2010年02月25日

LuaスクリプトからIupLuaを使ってみた modo 401 SP3

前回も書いた通り、LuaはC言語で書いたプログラムと組み合わせて使う事がとっても簡単に出来るものらしい。だからうまく使えばCで書いたプログラムをLuaスクリプト経由で使えるようになるんじゃないかなと思ったわけだ。

そこで、IUPというC、Lua、LEDで使えるGUIのツールキットをLuaから使ってみた。

IUPのサイトはここ

Luaのサイトはここ

まずはmodoなしでやってみようという事で、Luaのサイトからlua5_1_4_Win32_bin.zipを落としてきて解凍した。次にIUPのサイトからiup3_0_Win32_dll9_lib.zipを落としてきてこれも解凍し、その中からiup.dllとiuplua51.dllをlua5_1_4_Win32_bin.zipを解凍して出来たディレクトリにコピーした。

そしてlua5.1.exeをダブルクリックして実行した。

そして次のコードを直接入力して実行してみた。

reauire("iuplua")
iup.Message('YourApp','Finished Successfully!')

fig01

2行目を入力してEnterを押したら下のようなダイアログが出た。

fig02

と言っても、このダイアログは積極的に前に出てこないので、他の窓の後ろに隠れてて、窓をどけてようやく発見したw

ちなみにコピーして持って来たDLLの名前はiup.dllとiuplua51.dllで、iuplua.dllは無い。しかしDLLを検索するパスであるpackage.cpathを

print(package.cpath)

とやって表示してみると、「.¥?.dll;.¥?51.dll;・・・」となっていて、カレントディレクトリ( .)の中の「〜51.dll」も検索するようになっている。だから「iuplua」だけ与えてやれば、「iuplua51.dll」も検索対象に入るわけだ。

何はともあれiupのパッケージが簡単に使える事がわかったので、今度はmodoのluaから呼んで見ようと思ったわけだ。

そこでとりあえず今実行しているLuaはCTRL+Cを押して終了した。

次にtest.luaという名前でmodoのScriptsフォルダに次の内容のファイルを作った。

-- lua
lxout(package.cpath)

そして「システム」メニューから「実行」を選んで、「@test.lua」と入力して実行した。

fig03

そして「システム」メニューから「高度な設定」→「イベントログ」を選んでイベントログを表示して、スクリプトからの結果を見ると、こうなった。

fig04

で、この「.」はどこを指してるんだろう?よくわからなかったので、とりあえずCドライブのルートにパスを通してそこから読み込ませる事にして、このようなコードを作ってみた。

-- lua
package.cpath='.¥?.dll;.¥?51.dll;c:¥¥?51.dll'
require("iuplua")

で、実行してみたらこんなメッセージが・・・

fig05

「dynamic libraries not enabled; check your Lua installation」

どうやらDLLの読み込みを許可して無いと・・・orz

幸いな事にLuaのプラグインはmodoのSDKにソースが付いているので、この際そっちに組み込んじゃえばいいかなと思いついた。

そこでさっきダウンロードして来たiup3_0_Win32_dll9_lib.zipの替わりに今度はスタティックにリンクするバージョンのiup3_0_Win32_vc9_lib.zipをダウンロードしてきて使うことにした。

先に書いておくけど残念ながらこのアーカイブをリンクする事は出来なかった。リンク時に

 1>iup.lib(iupwindows_main.obj) : error LNK2019: 未解決の外部シンボル ___argc が関数_WinMain@16で参照されました。

などと出てくる。マイクロソフトの解説ページを見ると、ランタイムライブラリが違ってる時とかにこういうエラーが出るらしいんだけど、ExpressEditionなので選択肢としてはデバッグ用とリリース用の2通りしか選べなくて、どちらでやっても問題は解決しなかった。どうもMFCのランタイム使ってるっぽい(あくまで予想だけど)。

で、試しにもう少しバージョンを下げてiup2_7_1_Win32_vc9_lib.zipをダウンロードして来て、入れ替えたらうまく出来た。

手順としてはVisual C++ 2008 Express Editionを立ち上げて、SDKを解凍したディレクトリ内のsamples¥VisualC¥BuildSDKSamplesにあるBuildSDKSamples2008.slnを開いて、ソリューションエクスプローラのscript_luaのところを展開して、intrlua.cppを開く。

intrlua.cppの冒頭の部分#include "lxlua.h"の下に

#include <iup.h>
#include <iuplua.h>

を追加した。

fig06


さらにCLuaInterpreter::Run の定義のところで、luaL_openlibs(L);の行の下にiuplua_open(L);を追加した。

fig07

ソースの変更はこれだけ。

出来たらソリューションエクスプローラのscript_luaを右クリックしてプロパティを選択してscript_luaプロパティページを開く。

そして構成プロパティのC/C++の全般を選んで追加のインクルードディレクトリとしてiup2_7_1_Win32_vc9_lib.zipを展開したディレクトリの中のincludeディレクトリを追加する。項目を選ぶと右側にファイル選択のためのボタンが出てくるので、それをクリックして、

fig08

こういうパネルが出たら上に並んでいるボタンの中から追加ディレクトリのためのボタンを押して、1行増えたらまたそこの後ろのファイル選択のボタンをクリックして、iup2_7_1_Win32_vc9_lib.zipを展開して出来たiup2_7_1_Win32_vc9_lib¥includeを選択する。


fig09

同様に、リンカの全般で追加のライブラリディレクトリにiup2_7_1_Win32_vc9_lib.zipを展開して出来iup2_7_1_Win32_vc9_libディレクトリを追加する。

fig10

そしてリンカの入力の追加の依存ファイルで、以下のライブラリを追加する。

ole32.lib comctl32.lib liblua.lib iuplua51.lib  iup.lib

さらに特定のライブラリの無視で、以下のライブラリを無視させる。

LIBCMT LIBCMTD

fig11

これでビルドしたらなんとかscript_lua.lxが生成された。

解説のページを読むとさらにリソースも入れろって書いてあって、追加でiup2_7_1_Win32_vc9_lib.zipを解凍して出来たディレクトリ内のetcの中のiup.rcがあるからそれをプロジェクトに追加して、

fig13


プロパティページのリソースの項目で、このリソースファイルがコンパイルされて出来たiup.resがリンクされるように設定する。

fig12

でもこのままじゃ使われないような気がする・・・。

で、modoは最初からluaのプラグインがextraフォルダにintrlua.lxという名前で入っていて、コンフィグファイルにも登録されている。とりあえずMODO401.CFGファイルのバックアップをとってからそれが登録されている場所を見つけ出して削除し、

    <hash type="Server" key="D612FFCE-4B94-4823-A0A7-CC7CA2DDC3D6:lua">
      <atom type="Module">intrlua.lx</atom>
      <hash type="Tag" key="server.username">Lua Scripts</hash>
      <hash type="Tag" key="loader.dosPattern">*.lua</hash>
    </hash>

modoを立ち上げて先にビルドしたscript_lua.lxをファイル→プラグインの追加でmodoに追加した。

そして、test.luaを下のように書き換えた。

-- lua
iup.Message('YourApp','Finished Successfully!')

そしてスクリプトを実行した結果が以下だ。

fig14


ちゃんとダイアログが出た。とりあえずバイナリだけアップしておくね。使用はあくまで自己責任でね。

それではまた次回。

modoカテゴリー別ページ   



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)modo | CG

2010年02月24日

パーティクルシステムのお勉強 その52 3ds max 2010

Lock/Bondもずいぶんやったので、今回は下のようなアニメーションを作ってみたい。

fig01


まずは球(作った奴を確認したら半径36くらいだった)を1つとPF SOURCE(サイズ20×20)を1つ、汎用オムニフレクタと平面オムニフレクタ、重力のフォースをシーンに追加する。

fig02

PF Sourceは球の真上に配置しモディファイヤパネルでエミッションロールアウトのマルチブライヤ量で「ビューポート%」を100に、平面オムニフレクタは球の中心付近に配置して、球体より大きめのサイズにする。汎用オムニフレクタと重力の位置と大きさは適当で構わない。球にはチェックのマテリアルを貼ってあるけど、これはお好みで。

重力と平面オムニフレクタはデフォルトのまま、汎用オムニフレクタはオブジェクトとしてシーン内に配置した球を選択し、反射のカオスを100%にする。

パーティクルビューはこのように設定する(クリックすると大きくなるよ)。

fig03


テストの枝がイベントの右側から出てるものは、CTRLを押しながらテストオペレータの左から出ている小さい四角形をイベントの右側にドラッグすることで移動できるよ。新しいイベントはオペレータを下のコンテナから空いているところにドラッグ&ドロップすれば勝手に出来る。

さて、オペレータの設定をひとつずつやっていく。

fig04Render 01はタイプを「なし」にしてレンダリングされないようにする。今回はパーティクルを直接使わないで、最後にブロブメッシュにまとめる。

fig05Display 01は毎度の事ながらタイプを「ジオメトリ」にして、シェイプがビューポートに表示されるようにする。

fig06Force 01には重力を追加する。ForceはPF Source 01に入れてあるので、全てのイベントに重力が影響するようになる。

fig07Birth 01は1〜100フレームで1000個のパーティクルが発生されるようにした。この辺の量は最終的な仕上がりを見ながら調整すればいい。

fig08Shapeは3Dで球(20面)にして、サイズを12にした。この形状は直接レンダリングしないけど、ブロブメッシュでこのシェイプを包むような形状を生成するので、このシェイプのサイズによってブロブメッシュのつながり具合が変わってくる。小さくしすぎると、ブロブメッシュは1つ1つのシェイプを包むだけになってしまい、隣どうしが繋がっていかないので、様子露見ながら調節する。このシェイプの大きさを小さくして、かつブロブメッシュを繋げたいなら、パーティクルの数を増やすか、ブロブメッシュのテンションを下げるかする事になる。

fig09Collision 01には汎用オムニフレクタを追加し、「次イベントへのパーティクル条件」に「衝突する場合」を選び、速度は「バウンス」にして、パーティクルが衝突した時の挙動を汎用オムニフレクタの設定で決めるようにした。

fig10Collision 02は、なぜか汎用オムニクレクタをすり抜けてしまうパーティクルが出てしまったので、これを平面オムニフレクタでキャッチしてDeleteが入っているEvent 03に送って削除するためのものだ。ディフレクタとして平面オムニフレクタを追加する。

Event02はパーティクルが球体(汎用オムニフレクタ)に衝突したパーティクルが送られてくる。

fig11Split Amount 01はこのイベントに送り込まれて来たパーティクルの一部分を他のイベントに送り込むためのもので、ここで分けられたパーティクルがそれおぞれ球表面を流れるパーティクルと飛沫のパーティクルになる。今回は50%にしたけど、この比率をいじると飛沫の量とかが変化するよ。

fig12Send Outはイベント内のパーティクルを全て他のイベントに送るか、それとも保持するかを手動で切り替えるオペレータだ。これを使ってEvent04に送らなかった残りのパーティクルをEvent05に全て送った。こうする替わりにEvent05と同じものをSend Outのところに配置してもいいけど、調整箇所が多くなるので今回はこの方式をとった。

Event 04は球体表面を流れ落ちるパーティクルのための設定だ。

fig13「オブジェクトをロック」の下の「追加」ボタンを押してシーン内の球体を選択して追加し、「サーフェスにロック」を選び、「サーフェスに制限」をONにして、「実行する%」を0にする。これでパーティクルは球体表面に沿って自由に動くようになる。このパーティクルにも重力のForceがかかっているので、結局パーティクルは球体に沿って下方向に流れ落ちていく。
そこでダンピングを摩擦と空気/流動体抵抗の両方設定して、摩擦を287、抵抗を392、スピード単位を23にして、ねばっこくバーティクルが流れるようにした。このへんの数値を変えると流れるスピードとかが変わるよ。

fig14Age Test 02(途中でAgeTestを1つ削除したので番号が02になっちゃってる)は球体表面を流れて来たパーティクルをイベント内で経過した特定の時間で引き剥がしてEvent 05へ送る。
テスト値38、変動17で、パーティクルがこのイベントに入ってから21〜55フレームでEvent05へ送られる。

Event 05は球体から離れたパーティクル(飛沫と球体表面を流れて落ちたもの)が送られて来るところ。

fig15Scale 01は「タイプ」を「連続した相対値」に、「スケール係数」を93%にして、毎フレームごとに7%ずつパーティクルに割り当てられたShapeのサイズが小さくなっていくようにした。

fig16Age Test 03は飛沫がいつまでも残らないようにEvent 05にパーティクルが来て14フレーム経ったらEvent 03に送って、そこで削除するようにした。

fig17Event 03に送られてきたパーティクルはDelete01で全て削除される。

ここまでの設定の結果、このようなアニメーションになる。

fig18

fig19次に「作成パネル」の「ジオメトリ」のプルダウンから「合成オブジェクト」を選んで、出てきた「オブジェクトタイプ」ロールアウトから「ブロブメッシュ」をクリックして、ビューポートの空いている所をドラッグして適当にブロッブメッシュを作成する。

タイムスライダを少し進めてパーティクルが見えるようにしておいて、

fig23

fig20ブロブメッシュを選択したままモディファイヤパネルで、下の方にあるブロッブオブジェクトで「選択ボタン」を押して、ビューポートでパーティクルをクリックして選択する(PF Sourceのアイコンを選択したりリストを使って選択してもいい)。

そして左のようにパラメータを設定する。ブロブメッシュはパラメータの変更に伴って変化するけど、設定によってはとんでもないデータ量になったりするので設定の前にシーンを保存しておいた方がトラブルは防げるよ。「相対的な粗さの設定」はONにしない方がいいよ。それとビューポートの数値も小さくするとデータが莫大に増えるから気をつけてね。

これでパーティクルを覆う液体表面のメッシュが出来たので、これにマテリアルを設定する。不透明度をちょっと下げて半透明にしてある。


fig21

設定したマテリアルはブロブメッシュにドラッグ&ドロップして設定する。

fig22

以上でこのシーンの組み立てはおしまい。マテリアルは透明にしてあるけど、Renderオペレータでパーティクルがレンダリングされないように設定しておいたので、ブロブメッシュの中にパーティクルが見える事はない。

fig01


今回のシーンはデータとしてアップしておいたよ。

それではまた次回。

maxまとめページ 



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2010年02月23日

Pythonスクリプトのsys.exit()について modo 401 SP3

SDKを眺めていて思い出したんだけど、スクリプトのSDKが公開されてるんだよね。サンプルにLuaのインタプリタが添付されてる。中を見ればいろいろ面白い事がわかってきそうな感じだ。で、ついでにLuaってどんなものなんだろうとちょっと調べてみたら、なかなか面白そうな言語だな。どうやらC言語のプラグラムからLuaのプログラムを呼び出したり、LuaからCを呼び出したりといった事が簡単に出来るらしい。最近は資料も増えてきているみたいだし、ちょっと勉強してみようかなと思い始めたとこ。

話は変わって、スクリプトとコマンドのマニュアルを眺めていたら、こんな記述が見つかった。

PythonスクリプトはPython標準の sys.exit() を呼び出すことにより終了させることが可能です。引数なしでsys.exit() を呼び出すと、エラーを出力することなくスクリプトは終了します。
  sys.exit()
"code:message" というフォーマットで文字列引数を渡すことにより、呼び出しが失敗した際のレポートも可能です。このフォーマットでは、コードもしくはメッセージのどちらかは省略可能です。

今までスクリプトの途中で終了するためにexitをしようとすると、例外のエラーダイアログが表示されてしまって、使ってる人に変な誤解を与えかねないし、鬱陶しいのでスクリプトの中でexitが発生させる例外をトラップして処理していたんだけど、どうやら401ではそんな事をしなくても済むようになったらしい。

な〜んだ、もっと早く気付いてればなぁ。マニュアルは読まないとダメだなぁ・・・。

嬉しさ半分、悲しさ半分で、さっそく試してみた。

#python
import sys
sys.exit()

実行してみたら・・・

fig01

(つд⊂)ゴシゴシ

( ゚д゚)ポカーン

Windows版の自分の環境では元のままですが・・・。

ちなみにログはこうなってる。

fig02

SystemExitの例外が3行目で発生してるのは確かなので、modo側でこれを無視してくれたらいいだけなんだけどなぁ。

やはり当分の間は例外をトラップする事になりそうだなぁ。こんな感じで。

#python
import sys
import lx
try:

                           :

    sys.exit("ログに出す終了メッセージ")

                           :

except SystemExit:
    lx.out(sys.exc_info()[1])

マニュアルにはエラーコードによってメッセージダイアログを出せたりするって書いてあるので、使えるようになると面倒が減るね。

ちなみにsys.versionをとってみると、

2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)]

だった。

それではまた次回。

modoカテゴリー別ページ   



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)modo | CG

2010年02月22日

パーティクルシステムのお勉強 その51 3ds max 2010

今回も前回に引き続きLock/Bondオペレータだ。

fig02

fig01「超過時に分裂」オプションはパーティクルが特定のしきい値を超えた時にパーティクルを他のイベントに送るものだ。他のイベントに送られたパーティクルはLock/Bondの制御から離れて自由に動けるようになる。

例えば半径1:100、半径2:0、高さ20、高さセグメント10の円錐を作って、

fig03

100フレームまで徐々に回転速度があがるようにして、その後は一定速度で回転するようにしてみた。

fig05

そしてパーティクルビューはこのようにしてみた。

fig06

BirthTextureで円錐のメッシュに沿って規則正しくパーティクルを配置する事にした。そのためにまず拡散反射光を白くしたマテリアルを1つ作って、

fig10


これを円錐に割り当てた。

fig11

次にパーティクルビューでBirth Textureを選んでオプションで発生開始と発生終了を0にして、「パラメータを初期化」ボタンを押してモディファイヤパネルに切り替えて、

fig07

モディファイヤパネルのエミッタオブジェクトに円錐を追加し、

fig08

「頂点/エッジ」を選択して「パーティクルエミッションを初期化」を押して、

fig09

円錐のテクスチャの状態からパーティクルを発生させる。これで円錐の頂点にパーティクルが発生する。

fig12


次にLock/Bondで貼り付けるオブジェクトとして円錐を指定して、「サーフェスにロック」に切り替えて「サーフェスにスナップ」をONにする。何故かよくわからないが、「サーフェスにスナップ」をONにしておかないと、円錐のてっぺんにあるパーティクルがなぜか飛び出してくる。また「サーフェスに制限」をONにすると、毎フレームごとにパーティクルの位置と角度の計算をするために、パーティクルが思わぬ回転をしたり、チラチラ動いたりするのでOFFにしておく。そして、「超過時に分裂」をONにして、「速度」を選んで数値を200にし、「変動%」を20にする。

fig13

これでパーティクルが160〜240を超えた時にパーティクルがイベント02に送られてLock/Bondから離れる。

fig14そのイベント02にセットされたspinオペレータはこのような設定にしてある。

これがその結果。回転の状況がわかり辛いからちょっと色を付けてみた。

fig04

同じ回転数ならパーティクルの速度は円錐の外周に行くほど大きくなるので、パーティクルは外側から順にオブジェクトから外れて飛び出している。さらに「変動」を20%入れているので、外れて行くパーティクルに多少のばらつきがついている。

分裂に加速度のしきい値を使う例としてマニュアルには、静止によってパーティクルが外れる場合なんかが紹介されているけど、自分が試した限りではうまく機能しない感じだ。さらに「外側へのみ分裂」はオブジェクトサーフェスの法線方向と速度や加速度などのしきい値に使ってる要素の方向とを比較して、法線方向に近いもののみを分離の対象にするオプションとなっているけど、これもどうもうまく機能させられなかった。本来このオプションが機能すれば、分離したパーティクルはオブジェクトを貫通する事は無いはずなんだけど、いろいろ設定を変えてみてもうまく行かない。時間がなくなったので今回はこの項目については諦めた。

それではまた次回。

maxまとめページ 



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG
Archives