Tag : lightwave

7 月 25 2008

Lightwaveでシェーディング済みテクスチャを作成する

Posted by tanjo at 4:16 PM

Lightwave 3D Layout でライティングし、そのシェーディング結果をテクスチャとして利用できるようにしてみます。
今回私は、レースゲームのシェーディング済みテクスチャを用意するためにこの方法を使います。ですので、精度よりも生産性を重視しています。キーワードは2つ。

  • Ambient Occlusion(アンビエントオクルージョン)
  • Surface Baking Camera(サーフェイスベイキングカメラ)

アンビエントオクルージョンで環境光を模倣

レースゲームのフィールドだから、「影」はくっきりとしたレイトレースのシャドウでも良いのだけれど、環境光を感じるようにするには、やっぱりやわらかい「陰」も必要でしょう。
環境光を再現する方法としてはラジオシティが正確ですが、とっても重い、と。そこでアンビエントオクルージョンを使います。ラジオシティは反射していく光を次々と追ってシミュレートするのに対し、アンビエントオクルージョンは周囲から光がどのくらい遮られるか、という陰係数をもとに計算するそうです。

ちなみに速度重視なら、Lightwaveでは、シャドウマップを使った疑似環境光が圧倒的に速いです。ですがフィールドモデルのスケール・場所に影響を受けやすく、今回は使いません。やり方は、以下のページ12灯スポットライトの項で分かりやすく解説されています。

レイトレーシングで環境光を模倣する具体例 ~ Lightwave 3D

まずはモデリングをして、UVマップを作成しておきます。

Lightwave v9ではサーフェイスはノード形式で制御できるようになっていて、アンビエントオクルージョンもノードを介して「サーフェイスに」設定してやります。レンダリングはレイトレースを使います。

標準でインストールされるアンビエントオクルージョン・ノードには Occlusion, Occlusion II の2つがありますが、どちらも精度がイマイチ。より細かく設定できるノードプラグイン SG_AmbOccNode を使いました。

サーフェイスのノード設定はこのようにしました。

モデルの大きさがどうなっても困らないよう、ライトはすべて Distant Light を使用します。場合によってはライトのプロパティで Ambient Intensity を高めに設定しちゃっていいかもしれません。
Render Globals のオプションで Ray Trace Shadows にチェックを入れ、レンダリングすると、環境光が再現されていることが分かります。

サーフェイスベイキングカメラでテクスチャ書き出し

ここからが本題ですね。レンダリングした状態のサーフェイスを、テクスチャとして保存します。
Lightwave v9 Layout では Surface Baking Camera というカメラが追加されていて、これは、メッシュとUVマップを指定すると、それに応じたUVテクスチャをレンダリングしてくれるというものです。書き出した画像をテクスチャとして設定すれば、簡単にシェーディング済みモデルの完成です。

やり方はとても簡単。
まずはModelerで、適用させたいポリゴンだけを選択してUVマップを作成し、それらのポリゴンを1つのレイヤーにまとめておきます。
Layoutに移ったら、カメラのプロパティから Surface Baking Camera を選択し、設定で Mesh に先ほどのオブジェクト、UV Map にさっきのUVを指定します。その他の項目を適当に設定し(出力画像のタテヨコ比に注意)、レンダリングすればUVマップ用の画像が取得できるはずです。

低解像度の場合は、UV Border の値を設定して、UVマップの輪郭よりレンダー画像が少しはみ出すようにしてやった方がいいかもしれませんね。詳しいチュートリアルは、公式のデモビデオで取り上げられています。

古いバージョンのLightwaveを使っている場合

アンビエントオクルージョンは、SG_AmbOcc プラグインが利用できます。
ベイキングは Surface Baker (LW_Baker) シェーダが利用できます。チュートリアルはこちら
でも、どちらも使ったことなくて詳しいことは分かりませんッ。

ゲームで使ってみました

さて、レンダリング済みモデルをCOLLADAに変換し、前回作ったゲームサンプルに読み込ませてみました。
まあ相当荒削りなサンプルですが、少しは空間内の建物として見えてきたでしょうか。

レースゲーム・サンプル画面

デモをプレイする (要:Flash Player 9.0.115.0以降)

7 月 13 2008

COLLADAオブジェクトをPapervision3Dで表示してみる

Posted by tanjo at 4:20 AM

Lightwaveでモデル作成 → BlenderでCOLLADA出力 → Papervision3Dでレンダリング、と練習してみます。
PV3Dやってみる(5) 【DAEデータを読み込み】 | [FlaTech+]WebDesign Rainyday を参考にさせていただきました。やりながら気づいたこと、つまずいた点とかを書いておきます。

モデルの作成

Lightwave Modelerで適当にモデルを作ります。

lw_pers

UV投影方式は Atlas にしました。
データインポート時にトラブルのもとになる(気がした)ので、UV名やサーフェス名は、半角英数のみ・記号なしの短いものにした方が無難です。ちなみにUVマップされていないサーフェスは、Papervision3Dで描画できないっぽいです。単純なモデルでもUVマッピングしましょう。
マップ画像の形式は、JPEG か PNG あたりにしておけば問題ないです。ちなみにPNGに透明色があると、その部分はPapervision3Dで描画したときに透明のテクスチャとして扱ってくれます。自動で。これは便利!

lw_uv

そして、そのままネイティブのLWOファイルとして保存。ファイル名も box.lwo とか無難なものに。
私は最新版のLightwave 9.3.1を使用していますが、このバージョンのLWOでも、Blenderはインポートしてくれました。

COLLADA形式での書き出し

あらかじめBlenderをセットアップしておきます。
Blender起動時に、すでに余計なモデルやライトが置いてある場合は、[A]キーを使って全選択 → [Delete] で削除できます。
File > Import > Lightwave (.lwo) から、先ほどのLWOをインポート。アニメーションモードに切り替え(下図)、ブラウザパネルで書き出すオブジェクトだけが選択されているか確認し、File > Export > COLLADA 1.4 (.dae) を選択します。

bl_mode

エクスポート設定はこのようにしました。

bl_export

ポリゴンを三角分割する/選択部分だけ書き出し/UVマップを使用する、の3つにチェックしています。「Disable Physics」もチェックしていいかもしれませんね。
この時点で三角分割しても、テクスチャマッピングがずれる…なんてことはありませんでした/今のところは。でも多角形の分割はあまり利口ではなかったので、複雑な形状は、モデリングの時点である程度分割しておくべきかも。まあ当然ですかね。
*綺麗な分割でないと、Papervision3Dでポリゴン欠けやテクスチャ歪みが起こりやすいです。

これで、COLLADA形式のモデルデータが出力されます。
COLLADAはXMLで記述されたテキストファイルで、Google Earthなんかでも利用されています。拡張子は「.dae」。

さて、このまま利用してもとりあえずPapervision3Dでは使えますが、私の場合ではテクスチャ画像の参照を絶対パスで行っていたので修正しておきました。
DAEファイルをテキストエディタで開き、該当箇所を相対パスに変えておきます。

<init_from>f:\works\flashdevelop\pv3d\3dmodel_01\model\t_box.jpg</init_from>  (修正前)
<init_from>t_box.jpg</init_from>  (修正後)

(追記)
どうやらBlenderのエクスポートオプションで、「Use Relative Paths」をチェックすれば相対パスになるようです。

Papervision3DでCOLLADA表示

Papervision3Dでは、COLLADAを使用するためのクラスとして、

  • org.papervision3d.objects.parsers.Collada;
  • org.papervision3d.objects.parsers.DAE;

の2つがあります。
両者の違いは、ロードするときの書式だとか、拡張されたCOLLADA形式への対応状況だとか、オブジェクトのデフォルトサイズとかいったところ。note.xさんの記事にちょくちょくヒントが出ています。
使い方は、まずSWFが書き出されるディレクトリを基準に、COLLADAファイルとテクスチャ画像を移動。そしてスクリプトはこのような感じに。Colladaだと、

//クラスをインポート
import org.papervision3d.objects.parsers.Collada;
//宣言
private var colladaObj:Collada;
//定義して読み込む
colladaObj = new Collada("XXX.dae");
//Scene へ addChild
scene.addChild(colladaObj);

DAEだと、

//クラスをインポート
import org.papervision3d.objects.parsers.DAE;
//宣言
private var colladaObj:DAE;
//定義して読み込む
colladaObj = new DAE();
colladaObj.load("XXX.dae");
//Scene へ addChild
scene.addChild(colladaObj);

基本的な操作は、スクリプトで生成したPlaneとかと同様です。
なお私のモデルでは、同じファイルを扱ってもDAEの方がかなり小さく表示されてしまいました。そこで .scale を 100 に指定してやるとだいたい同じくらいのスケールに。

さてさて、これらをもとにサンプルを作ってみました。
*ソースファイル Main.as の全文はこちらから参照できます。

collada01