強火で進め

このブログではプログラム関連の記事を中心に書いてます。

「Blender to WebGL exporter」にテクスチャ情報の出力を追加出来たら良いなぁ

以前のエントリーで「Blender to WebGL exporter」を使って出力したデータをWebGLで表示する話を書きました。

Blenderで出力したデータを使ってWebGLで簡単に3Dモデルを表示する(その2) - 強火で進め
http://d.hatena.ne.jp/nakamura001/20101115/1289836776

この時はテクスチャ用の画像ファイル名を別途、メインのプログラムのファイル名の部分を書き換えて対応しました。

これを見たhack_webglグループのメンバーのtmasdaさんがこの様にプロパティにテクスチャ名を設定されてるのを見て

//var BlenderExport = {};
BlenderExport.spikey = {};
BlenderExport.spikey.texName = "spikey.jpg"; // Add Texture Name

「この一手間減らせれるのは良いなぁ。Exportプログラム(Blender to WebGL exporter)をいじってこの機能追加出来ないかなぁ?」と思いちょっとプログラムをのぞいてみました。
基本的にBlenderに搭載されているPythonの仕様は理解してないので他のExportプログラムを参考に作業を開始。

今回は xsi_export.py を参考にしました。

プログラムファイル内を texture などそれっぽい文字列で検索した後に順番にたどって行ったところ以下の手順でテクスチャ情報が取得出来ると判明しました。

	for mat in MAT:
	    mtex = mat.getTextures()
	    print mtex
	    for mt in mtex:
			if mt:
				tex = mt.tex
				if tex.type == Blender.Texture.Types.IMAGE:
					img = tex.getImage()
					print tex.name
					print img.getFilename()

順番にやってる事を解説します。プロパティ名からの予想ですが多分合ってるでしょう。

ここでまず、マテリアル情報一覧を取得。

MAT = Blender.Material.Get()

マテリアル情報を1つづつ取り出してループ。

  for mat in MAT:

マテリアル情報の中からテクスチャ一覧を取得。

    mtex = mat.getTextures()

テクスチャ情報を1つづつ取り出してループ。

    for mt in mtex:

有効なテクスチャ情報が存在する時のみ以降の処理を行う。

      if mt:

マテリアル情報からテクスチャ情報を取得。

				tex = mt.tex

画像を使っているテクスチャの時のみ以降の処理を行う。

				if tex.type == Blender.Texture.Types.IMAGE:

テクスチャとして設定しているファイルの情報を取得。

					img = tex.getImage()

Blender内部でのテクスチャ名とテクスチャとして設定している画像ファイルのパスをコンソールへ出力。

					print tex.name
					print img.getFilename()

次はこの処理を「Blender to WebGL exporter」へと組み込みます。

取り敢えず、「Native WebGL」で出力出来れば良いのでその処理を行っているところ探します。

関数名と記述されている文字列 var BlenderExport = {}; などから export_native が該当の関数だと特定。

def export_native(class_name, mesh, ob):
	s = "var BlenderExport = {};\n"
	s += "BlenderExport.%s = {};\n" % (class_name)

試しにここの先頭に以下のにプログラムを追加して出力してみました。

def export_native(class_name, mesh, ob):
	s = "var BlenderExport = {};\n"
	s += "BlenderExport.%s = {};\n" % (class_name)
	
	MAT = Blender.Material.Get()
	for mat in MAT:
	    mtex = mat.getTextures()
	    print mtex
	    for mt in mtex:
			if mt:
				tex = mt.tex
				if tex.type == Blender.Texture.Types.IMAGE:
					img = tex.getImage()
					s += "tex_name2 %s %s;\n" % (tex.name,img.getFilename())

ちなみに .py ファイルの記述にバグが有った場合は以下の様に「コンソールをチェックして下さい」と表示されます。

エラー情報は コンソール.app アプリを使うか、

/アプリケーション/ユーティリティ/コンソール.app

もしくはBlenderをターミナルから実行ファイルを直接実行するとこの様なエラー情報がコンソールに情報が出力されます。

実行ファイルは .app の中の /Contents/MacOS/ の下に有るみたいです。
自分の環境だと以下のパスに実行ファイルが有りました。

/Applications/blender-2.49b-OSX-10.5-py2.5-intel/blender.app/Contents/MacOS/blender

なお、コンソールから実行すると自分の環境だとウィンドウの閉じるボタンなどがメニューの裏側に行ってしまって触れない状態になってしまいました。まぁ、メニューから「Window」-「Zoom」を選択する事ですぐに修正出来ましたが…

今回、bal;fa] と意味のない文字をプログラムに差し込んで意図的にエラー発生させた場合、 コンソール.app には以下に表示されます。

赤枠の所を確認すると「109行目でシンタックスエラーだな」と確認できます。

ちょっと脇道にそれましたが先ほどのプログラムを追加したものでExportした結果はこちら

var BlenderExport = {};
BlenderExport.spikey = {};
tex_name2 I.metalscratches.whit /home/icu/Ubuntu One/workshop/supertux3d/enemies/1.ice.world/spikey/metal2.diff.jpg;
tex_name2 I.metalscratches. /home/icu/Ubuntu One/workshop/supertux3d/enemies/1.ice.world/spikey/metal2.spec.jpg;
tex_name2 I.metalscratches..001 /home/icu/Ubuntu One/workshop/supertux3d/enemies/1.ice.world/spikey/metal2.nor.jpg;
tex_name2 spikey.tex /home/icu/Ubuntu One/workshop/supertux3d/enemies/1.ice.world/spikey.TEX.jpg;
BlenderExport.spikey.vertices = [0.503120,-0.569621,0.181385,0.491068,-0.426495,0.296873,0.419011,-0.119035,0.428811,0.4
(以下略)

ちなみにこれは以前のこちらのエントリーでも使わせて頂いた、 snowspike.blend をExportしました。

Blenderで出力したデータを使ってWebGLで簡単に3Dモデルを表示する(その2) - 強火で進め
http://d.hatena.ne.jp/nakamura001/20101115/1289836776

最初のテクスチャ情報を見るとBlender内部で使っているテクスチャ名、

I.metalscratches.whit

そして、テクスチャに使っている画像ファイルのパスがちゃんと出力されているのが分かります。
※この snowspike.blend を作られた方のマシンのパスかな?

/home/icu/Ubuntu One/workshop/supertux3d/enemies/1.ice.world/spikey/metal2.diff.jpg;

この様にテクスチャ情報を出力した結果、改めて「Blender to WebGL exporter」はマテリアル情報を全然出力していない事を再認識。この辺りの含めてこのExporterをちょっと拡張してみたいですね。

そのためには出力結果確認の為にWebGLでのマテリアル設定を反映するプログラムの作成やBlender側にどんなマテリアル情報を持っているのかなどを調べたりなど結構やらないといけない事が多そうなので取り敢えずココで一区切り。時間が有る時に順番に攻めて行こうと思います。