Softimage ブラウザで表示できる画像(アルファチャンネルも確認可能)を書き出す。

Softimageからブラウザで使える画像を書きだすということをやったのでご紹介。
今回の要点は

  1. モデルに貼られているテクスチャ(連番含む)を抽出・書き出す。
  2. SIではTGA/PSD/PICなどなど色々な形式がサポートされているが、ブラウザで必ずしも表示できる形式とは限らない。むしろ出来ない物の方が多いので、形式を統一する。
  3. ブラウザでもアルファチャンネルでどうテクスチャが透過されているのか知りたい!

以上、3点ですね。d(≧▽≦*)

まずは、1ですが今回対象となるのはテクスチャとしてはり込まれた画像のみです。
Picturesフォルダにはあるけど、モデルには貼られていないものなんかがあった場合はなにかしら対処が必要だと思いますが、今回は触れません。
あとは、似た方法でレンダリングした画像にも同じこととかできるかもしれませんね。(試してませんが)

で、肝心のテクスチャのファイルを抽出・書き出しですが、オブジェクト内のマテリアルから繋がっているノードを辿って…という方法も考えられますが、
ぶっちゃけメンドクサイので標準装備のdotXSI書き出し機能を使用します!!
実はdotXSI書き出し機能には、テクスチャの書き出しと書きだした画像形式のフォーマット変更まで付いています。
これで1と2の用件を同時に満たせるわけです。
といいますか、画像の形式を変更するなんて自分の知識ではできんのですよ…。 A=´、`=)ゞアセアセ...

実際のスクリプトは簡単なので、特に書きません。
ただ書き出し前にはちょっと面倒なdotXSIの設定をしないといけないので、その関数を載せときますね。

//dotXSIOptionの設定を行う
function Setup_dotXSIOption(in_TextureSize,in_TextureFormat){

	//dotXSIの書き出しオプションを取得
	var dXEOp = Dictionary.GetObject("dotXSIExportOptions");

	dXEOp.output_file_format.value = 1;	//出力形式アスキー
	dXEOp.output_file_format_version.value = 360;	//バージョン

	//////ジオメトリグループ//////
	dXEOp.sceneroot.value = 0;	//選択がない場合にシーンルートを書き出す
	dXEOp.polymesh.value = 1;	//ポリゴンメッシュ
	dXEOp.nrbssrf.value = 0;	//NURBSサーフェイス
	dXEOp.user_normals.value = 0;	//ユーザ法線
	dXEOp.nrbscrv.value = 0;	//NURBSカーブ
	dXEOp.tesselation.value = 0;	//ポリゴンタイプ

	//////アニメーショングループ//////
	dXEOp.animall.value = 0;	//すべて
	dXEOp.animgeom.value = 0;	//ジオメトリ
	dXEOp.animcam.value = 0;	//カメラ
	dXEOp.animlight.value = 0;	//ライト
	dXEOp.animmat.value = 0;	//マテリアル
	dXEOp.animenv.value = 0;	//アンビエンス
	dXEOp.animaction.value = 0;	//アクション

	//////アニメーションフィルタリンググループ//////
	//プロット
	dXEOp.animplot.value = 0;
	//プロットしない場合は以下のチェックボックスは無効のため設定しない。

	//////関係グループ//////
	dXEOp.constraint.value = 0;//コンストレイント
	dXEOp.envelope.value = 0;//エンベロープ
	dXEOp.ik.value = 0;//IK

	dXEOp.custompset.value = 0;	//カスタムパラメータセット
	dXEOp.keep_shared_mat.value = 0;	//共通マテリアルの保持

	///////テクスチャグループ///////
	dXEOp.textures.value = 1;//テクスチャ
	dXEOp.txtabsolute.value = 0;	//絶対パス
	dXEOp.txtsequences.value = 0;	//シーケンス
	dXEOp.txtfiles.value = 1;	//ファイルのコピー
	dXEOp.txtformat.value = in_TextureFormat;	//ファイル形式
	dXEOp.txtresizeX.value = in_TextureSize;	//Xサイズ
	dXEOp.txtresizeY.value = in_TextureSize;	//Yサイズ

}

今回はテクスチャを書き出すことだけが目的ですから、不必要なものは書き出さないようにしています。書き出し時間が延びるだけですしね。
ポイントとしてはポリゴンメッシュは書き出すこと。
これを書き出さないとテクスチャも道ずれで書き出してくれません。
あとは、テクスチャグループのシーケンスを有効にすること。
テクスチャアニメーションなどが設定されている場合、これで一括して書き出してくれます。
dotXSI書き出し前に以下のような感じで使って下さい。

Setup_dotXSIOption(1,4);

引数としては

in_TextureFormat 1:オリジナル
2:PIC
3:BMP
4:PPM
5:TGA
6:JPEG
7:TIM2
in_TextureSize 1:オリジナル
2:自動
3:2pixel
4:4pixel
5:8pixel
6:16pixel
7:32pixel
8:64pixel
9:128pixel
10:256pixel
11:512pixel

となっています。
テクスチャのサイズは縦横比を維持したい場合は、XかYを自動にしておくとよいでしょう。
dotXSI書きだし設定から選択できる画像形式の中でブラウザで表示できる形式はJPEGくらいですね。
単純にブラウザで表示するのであればここまででOK!!しかし、今回は3の要件もあるので、JPEGでは役者不足。
アルファチャンネルが消えてしまいます。
そこでひとまず書き出しの際に選択できる形式の中で、アルファチャンネルが保持できてなおかつメジャーな画像形式ということでBMPを選択。
ここからさらにブラウザで表示でき、なおかつ透過できるPNG形式にしようという魂胆であります。(゚ー゚)ニヤリ

まず試みたのはPHPに内包されているGDライブラリという画像処理用のライブラリ(?)
しかし、問題が幾つか。一つ目は、BMPとWBMPがなんとか…詳しくは良く分からんですが、どうやらBMP形式がサポートされてないらしい。
しかし、インターネットの海は広いですから誰かそれらしいの公開してるだろうということで探してみたら

というものを発見。早速PHPに組み込んで試してみたところ、見事BMPPNGに変換成功!!
やったーーーーーーーーー!!
と喜んだのもつかの間、出来あがったPNGは透過データが吹っ飛んでました。��q|゚Д゚|p
拾ってきたものの中身を変更するスキルなんて当然ないので、PHPでの画像形式変換はきっぱりと諦め、作戦変更。別の手を探すことにしました。

次に考えたのがフリーソフト
コマンドラインから使える画像形式変換ツールがあれば、Softimageからバッチファイルを生成してdotXSI書き出し後に、一括変換、ウマーーーー。という流れ。
探したらピッタリなのがありました。

コマンドプロンプトを立ち上げて

(ソフトが置いてあるパス)\BMP2PNG.EXE -A (処理対象のフォルダ)/*.bmp

という感じに使います。これで透過済みのPNGファイルの出来あがり!!
ブラウザにファイルを放り込めば透過された画像が表示されてるのが確認できるはず。
Softimageから使うときは以下のようなものになります。
(手持ちに関数なかったのでババっと書いたので、エラー出るかも…)

//コマンドライン版 BMP ←→ PNG コンバータを使用してフォルダ以下のBMPファイルを一括でPNGに変換する
//in_Dir:処理対象フォルダパス
function BMP2PNG(in_Dir)
{
	//コマンドライン版 BMP ←→ PNG コンバータのパス
	var BMP2PNG_EXE = "パスを設定";
	//バッチファイルパス
	var BatPath = Application.InstallationPath( siUserPath )+ "\\Application\\Plugins\\BMP2PNG.bat";

	//バッチファイル内に記述する文字列
	var BatString = BMP2PNG_EXE + " -A" + in_Dir + "\\*.bmp";

	//バッチファイルを作成
	var oFso = new ActiveXObject("Scripting.FileSystemObject");
	var ScriptFile = BatPath;
	var file = oFso.OpenTextFile(ScriptFile, 2 , true);
	file.WriteLine(BatString)
	file.Close();
			
	//バッチファイルを実行
	var WshShell = new ActiveXObject("WScript.Shell");
	WshShell.Run( BatPath , 4, true );
	
	//バッチファイルの削除
	oFso.DeleteFile(BatPath,1);
	
	return
}

Jscriptから直接コマンドラインの操作は出来ない(と思う)ので、バッチファイルを作成。
それを実行することでコマンドラインから使用するソフトを操作します。
バッチファイルの実行が終わるまで、処理を次に回さないようにしています。
これをやらないと、外部ソフトの動作が終わってないのに次の処理に進んでしまい処理が上手く行かなくてエラーがでるかもです。
後は、この関数内には元のBMPファイルを削除する処理は書いてないので、場合によっては追加が必要ですね。
ちなみに、今回使用したフリーソフトのような実行ファイルのみで動くようなソフトは、インストールしてもらう手間が無く、サーバーにポンっと置いておけば使うことが出来るのが利点ですね。

長々となりましたが、まとめると

  1. dotXSIでBMPを一括書き出し。(シーケンスのチェックを入れることで連番テクスチャにも対応)
  2. コマンドライン用ソフトをSoftimageから使う為にバッチファイルを作成
  3. バッチを実行、コマンドラインBMP ←→ PNG コンバータを使用してフォルダ以下のBMPファイルを一括でPNGに変換
  4. ブラウザで表示可能な画像ファイルの完成!!
  5. 必要であれば元のBMPファイルを削除

こんなところでしょうか。
なにか間違い等あれば教えて下さい。m(。-_-。)m