2009年03月18日

テクスチャプラグインを作ってみる

今回はこちらのページを参考にして、テクスチャプラグインを作ってみたいと思います。

一応、Blenderの公式ユーザーマニュアルの中のページなのですが、一番上の部分を見ると「Blender Version 2.31」となっていて、内容がBlenderの最新バージョンに対応していないようです。このページ以外にBlenderプラグインリポジトリなどにもBlenderのテクスチャプラグインのサンプルコードが掲載されていますが、いずれも現在のBlenderに付属するプラグイン作成用のヘッダファイルとバージョンが違っていて、そのままではコンパイルしてもきちんと動作しないようです。

そのため、今回はBlender2.48aの「plugins」フォルダに入っているサンプルファイル「clouds2.c」のソースファイルを元にして、オリジナルのプラグインを作るにはどこを修正すればいいのか、という形で話を進めたいと思います。ただし、上記の参考ページの解説内容については、ほとんどの部分が現在も有効です。今回は最低限の内容に話を絞っていますので、もしこの内容に興味を持たれた場合は、そちらのページの方をご参照ください。
pic090318_01.jpg

まず、「clouds2.c」を複製して「test.c」と名前を変更してください。そして、以下の手順でこのファイルの内容を作り替えていきます。
一応、サンプルデータsample_data090318.zipにソースファイルとWindows(32bit)、Linux(32/64bit)のバイナリファイルを用意してあります。私は現在のところ、Windows64bit、Mac OSなどのバイナリファイルを作ることができません(将来的にもできなさそうです)。ご了承ください。

○コメント
サンプルファイルには冒頭にライセンスについての記述があります。
本来は、きちんとライセンスの内容を確認した上でコードの管理者などを明記する必要があると思いますが、今回はとりあえず冒頭のファイル名の部分を変更してあります。
/**
 * $Id: test.c $
 *

○インクルードファイル
#include "plugin.h"

テクスチャプラグインを作成するには、必ずこの「plugin.h」をインクルードする必要があります。サンプルファイルではこの他に「math.h」をインクルードしていますが、今回は使用しませんので削除してあります。

○プラグイン名の設定
char name[24]= "Test";

とりあえずダブルクォートで囲まれた部分(" ")を変更しています。
参考のページでは、「Texture Buttons Windowでtexture's titleとして表示される」と書かれていますが、現在のバージョンではプラグインファイルのパスが表示されていて、ここで設定した名前は表示されていないようです。

○サブタイプの設定
#define NR_TYPES    1
char stnames[NR_TYPES][16]= {"Default"};

サブタイプというのは、プラグインの使われ方を切り替えるスイッチのようなものです。今回は簡単にするために一つだけに修正しています。「cluds2.c」では、「強度」「カラー」「バンプ」の3種類の使い方ができるようになっていて、「NR_TYPES」が「3」に、「stnames」が「{"Intens","Col","Bump"}」となっています。
pic090318_02.jpg pic090318_03.jpg

○VarStruct構造体 ボタンの設定
VarStruct varstr[]= {
{    NUM|FLO,    "value",    0.0,    -1.0,    1.0,    "test value"},
};

「plugin」パネルに表示するボタン類をここで定義します。ここでは「value」という数値を変更できる数値ボタンを、デフォルト値「0.0」、最小値「-1.0」、最大値「1.0」として設定しています。
VarStructという構造体には「type」「name」「def」「min」「max」「tip」を指定します。
  1. type ここで数値設定用のボタン(数値ボタン、数値スライダ、トグルボタン)、テキストラベルなどのタイプを指定します。数値ボタンの場合数値のフォーマット(INT,FLO)とボタンタイプ(NUM,NUMSLI,TOG)を「|(OR)」で組み合わせて指定します。
  2. name ボタンに表示される名前です。15文字までです。
  3. 数値の範囲 デフォルト、最小、最大の値を指定します。トグルボタンでは「min」が押された状態、「max」が押されていない状態に対応します。
  4. tip ボタン上にマウスポインタを置いたときに表示されるテキストです。80文字までです。

pic090318_04.jpg pic090318_05.jpg

○Cast構造体 ボタンで設定する変数の本体
typedef struct Cast {
    float val;
} Cast;

VarStructでは、ボタンの表示に関する設定だけを行っていて、実際に描画のための処理を行う関数(plugin_tex_doit)で使用するための変数については何も書かれていません。Cast構造体には、VarStructで指定した順番通りに、それぞれのボタンに対応する変数を記述します。今回はボタンが一つだけなので、それに合わせてfloat型の「val」という名前の変数を一つだけ記述してあります。

○変更の必要ない部分
以下、実際のソースコードではplugin_tex_doit()関数まで、基本的には内容を変更する必要のないコードが書かれています。変更していないのでブログの記事上では内容を省略しますが、コンパイルするために必要なコードが書かれていますので、実際のソースコードでは省略しないでください。

○プラグインの描画処理
int plugin_tex_doit(int stype, Cast *cast, float *texvec, float *dxt, float *dyt, float *result)
{
    if (texvec[0] <= cast->val) {
        result[0] = 0;
    } else {
        result[0] = 1;
    }
   
    return 0;
}

この部分がレンダリングの際に、各ピクセルに対して毎回Blenderから呼ばれるプラグインの本体となる部分です。参考のページのもの、pluginsフォルダのサンプル、どちらもそれなりに複雑な計算をする処理が書かれているので、ちょっと見ただけでは内容がわかりにくいように思いました。そこで、このサンプルでは思いっきり簡単にしてみました。

plugin_tex_doit()関数に渡される引数

  1. stype どのサブタイプが有効になっているかが渡されます。今回はサブタイプが一つなので関係ありませんが、 2つ以上設定している場合はこの値に応じて(強度、カラー、バンプなど)処理を分けることになります。
  2. *cast ボタンに応じた変数を格納したCast構造体のポインタです。
  3. *texvec レンダリングされているピクセルで使用されているテクスチャ座標を「float」型の3つの数値で渡しています。texvec[0]がX座標、texvec[1]がY座標、texvec[2]がZ座標となります。
  4.  *dxt,*dyt OSAがオンで、アンチエイリアスが正しく計算されているとき(それ以外はNULLとなりますので確認が必要です)3つのfloat値の配列のポインタが渡されます。アンチエイリアスの計算で使用されるようなのですが、正直なところ私にはまだよく理解できていません。
  5. *result この配列を使って計算結果をBlenderに返します。つまり、このresult[]をなんらかの値に設定することが、この plugin_tex_doit()関数の目的になります。result配列は、float型のresult[0]からresult[7]までの8つの値が渡されます。その中に入れる内容はあらかじめ決まっていて、result[0]は強度、result[1]からresult[4]まではRGBA値、 result[5]からresult[7]までがnormalのXYZ値となります。result[0]の強度は必ず返す必要があります。それ以外はオプションとなります。RGBA、normalの値を返す場合は、plugin_tex_doit()関数の戻り値でそれぞれ「1(RGB)」「2(Normal)」「3(全て)」を返すように設定する必要があります。強度のみの場合は「0」です。
プラグインの描画処理の内容についてです。
このプラグインでは「plugin」パネルで数値ボタン「value」の値を変えることができ、テクスチャ座標のX座標がそれより小さければテクスチャ強度「0」、大きければテクスチャ強度「1」になります。

テクスチャプラグインの描画処理は、基本的に「texvec」からテクスチャ座標(X,Y,Z)を取り出して、その場所でのテクスチャの強度を計算し、結果を「result[0]」に格納する、という感じになります。このサンプルでは「texvec[0]」でテクスチャ座標のX座標についてだけ調べています。

プラグインのパネルに設定したボタンからは、Cast構造体の変数を通して値を受け取ることができます。このサンプルでは「cast->val」の部分で、プラグインパネルの数値ボタンの現在の設定値を調べています。

if文の条件式の部分は、(texvec[0] <= cast->val)となっています。「val」変数にはデフォルト値で「0.0」を指定してあり、テクスチャ座標は、「-1.0」から「1.0」の範囲の値が渡されるようです。
例として、あるピクセルが描画される際、plugin_tex_doit()関数に渡されるテクスチャ座標Xの値が「-0.5」であったとします。このとき「val」の値がデフォルトのままであればif文の条件判定は「-0.5 <= 0.0」でTRUEとなりますから、result[0] = 0がレンダラに渡されます。結果として、そのピクセルはテクスチャ強度「0」となり、テクスチャプレビュー表示では黒になります。
実際にこのプラグインをロードした状態(「Val」が0.0になっている)でテクスチャの「Preview」パネルを見ると、左半分が黒で右半分が白になっています。
pic090318_06.jpg

プラグインパネルの「Value」の値を変更すると、それに応じてプレビューの表示の白い部分と黒い部分の境目が左右に動くのが確認できると思います。
pic090318_08.jpg pic090318_09.jpg

最後の部分で、plugin_tex_doit()関数の戻り値は、result[0]以外を使用していないので「return 0;」としています。
はっきりいって、実用性ゼロのプラグインができてしまいましたが、他のサンプルと比べてかなり内容が分かりやすくなったと思いますが...どうでしょうか。

このブログ、ソースコードのインデントが表示できないことに、今頃気づきました。プログラミングの記事を書くのには向いてなかったようです...。
※追記
スタイルシートとかを変えれば表示できそうなので、少し調べてみたいと思います。 ->スタイルシートは変更できなかったのですが、記事の本文を書く際に「リッチテキストエディタを使用する」というのを選択したら、とりあえずインデントが反映されるようになりました。
posted by mato at 22:50| Comment(0) | Blender | このブログの読者になる | 更新情報をチェックする

2009年03月15日

テクスチャプラグインをWindowsでコンパイルする

前回は付属のサンプルコードをコンパイルするだけで終わってしまったので、今回はオリジナルのプラグインを作ってみよう...と思ったのですが、前回できなかったWindowsでのコンパイルがようやくできるようになったので、その方法を書いておこうと思います。

まず、今回参考にしたインターネットのページです。
BlenderArtists.orgのフォーラムで検索してこちらのスレッドにたどり着きました。
そして、その中で紹介されていたのが、こちらのサイトです。

以下に、簡単に手順を説明します。基本的に上のサイトの手順そのままです。
ちなみに使用するコンパイラはMicrosoftのVisual C++ 2008 Express Editionのものです。

1.コマンドプロンプトを立ち上げます。Windowsのスタートメニューの「アクセサリ」とかにあります。
pic090314_01.jpg

2.Visual C++の機能をコマンドプロンプトから使えるようにします。具体的には、Visual C++に付属する「vcvars32.bat」というバッチファイルを実行します。

"\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"

インストールの仕方によってファイルの場所は、違っていたりするかもしれません。
pic090314_03.jpg pic090314_04.jpg

3.「cd」コマンドで、Blenderのインストールフォルダにある「Plugins」ディレクトリに移動します。
あらかじめ「Plugins」フォルダだけを、どこかわかりやすい場所にコピーしておいた方がいいかもしれません。

cd \blender\plugins

今回は「C:\」直下に「blender」というフォルダを作って、そこに「Plugins」フォルダをコピーしてあります。
pic090314_05.jpg pic090314_06.jpg

4.コンパイルに必要な「lib」ファイルを作成します。
詳しいことは上記のサイトで説明されていますが、プラグインのソースファイルでBlenderの用意している関数を使うために必要なようです。サンプルの「tiles.c」と「clouds2.c」では、「plugins」-「include」フォルダの「plugin.h」に記述されているhnoise()関数が使われています。
そのためのコマンドは以下のようなものになります。

link /lib /nologo /MACHINE:X86 /DEF:include\plugin.def /NAME:blender.exe

これで、「plugin.lib」「plugin.exp」という2つのファイルが作成されます。
pic090314_07.jpg pic090314_08.jpg

5.プラグインをコンパイルします。

cl /nologo -Iinclude /LD texture/tiles.c plugin.lib /link /EXPORT:plugin_getinfo /EXPORT:plugin_tex_getversion

2行に分かれて表示されていますが、実際には1行にまとめて入力します。
上の例では、「texture」フォルダに入っている「tiles.c」を指定しました。
このコマンドを実行すると、コマンドプロンプトにずらっとメッセージが表示され、「tiles.obj」「tiles.dll」「tiles.lib」「tiles.exp」の4つのファイルが作成されます。このうち、「tiles.dll」がプラグイン本体となります。
pic090314_09.jpg pic090314_10.jpg

pic090314_11.jpg

Blenderの「plugin」パネルの「Load Plugins」ボタンで、今作ったプラグインファイルを開いてみます。
pic090314_12.jpg pic090314_13.jpg

無事、プラグインとして使用できました。


実は、今回参考にさせていただいた上記のサイト以外に、LCC、MinGWを使ってWindowsでテクスチャプラグインをコンパイルする方法が書かれているサイトがあって、最初はそちらを参考にしてコンパイルを試していたのですが、私の環境ではなぜかうまくいきませんでした。
そちらでは、今回の「4.」の「lib」ファイルを作成する部分に相当する手順が省かれているようですので、そのあたりを工夫すればLCCやMinGWでもコンパイルできるのかもしれません。
posted by mato at 00:21| Comment(0) | Blender | このブログの読者になる | 更新情報をチェックする

2009年03月13日

テクスチャプラグインのサンプルをコンパイルしてみる

「vectexを改良しよう!」と目標は定めてみたものの、予備知識がないことにはどうにもならないので、まずは基本から始めてみたいと思います。
とりあえず簡単なテクスチャプラグインを自作するところから始めてみます。プラグインファイルを作る際に参考になりそうなページがBlender.orgのWikiにあります。

こちらを読んでみるとBlenderのインストールディレクトリの「plugins」フォルダにプラグイン開発に必要なファイルが全部そろっていて、サンプルもいくつかあるということです。このフォルダは3Dマウス「SpaceNavigator」を使う際にプラグインファイルを置く場所だったので知っていましたが、テクスチャプラグインの開発用のファイルが置いてある場所でもあったんですね。
pic090313_01.jpg

この「plugins」-「texture」フォルダを見てみると「clouds2.c」「tiles.c」という2つのサンプルファイルがありました。「plugins」-「include」フォルダの方にはプラグインの〜.cファイルを書く際に使われるC言語のヘッダファイルがあります。
pic090313_02.jpg pic090313_03.jpg

プラグインを実際にコンパイルするには「plugins」フォルダにあるMakefileを使えばいいようです。テクスチャプラグインの開発に必要なファイルは「plugins」フォルダの中にあるものだけで、Blenderのインストールディレクトリにあるその他のファイルは関係ないようです。実際にプラグインをコンパイルする場合、「plugins」フォルダごと別の場所にコピーしておいて、そちらで開発するという感じでもいいようです。

Linuxの環境でサンプルファイルをコンパイルしてみます。
コンソールウィンドウで「plugins」フォルダに移動して、

$ make

とするだけです。
コンソールにとくにエラーらしきものが表示されなければ、「texture」フォルダの中に「cloud2.so」「tiles.so」というファイルができているはずです。(エラーが表示されてもファイルができてしまうこともあるのですが、そういう場合はBlenderでプラグインをロードするときに失敗したりします)
pic090313_04.jpg pic090313_05.jpg

ちなみに「plugins」フォルダのMakefileはこんな感じになっています。

all: textures sequences

textures:
$(MAKE) -C texture

sequences:
$(MAKE) -C sequence

clean:
$(MAKE) -C texture clean
$(MAKE) -C sequence clean

「texture」フォルダと「sequence」フォルダに入っているMakefileを実行するように記述されています。
そして、「texture」フォルダのMakefileは、こんな感じです。

all: plugins

plugins:
@/bin/sh -c 'for i in *.c; do ../bmake $$i; done;'

clean:
rm -rf *.o *.so

「〜.c」という名前のファイルがあったら全部コンパイルする、ということですね。
自分で新しく「test.c」というようなプラグインを書いたとしても、Makefile自体を修正する必要はなくて、makeコマンドを実行するだけでコンパイルしてくれるというのは助かります。

さて、できあがったプラグインはどんなものなのでしょうか?
どちらもソースコードの行数は178行で、書かれているコードはそれほど多くはありませんが、かといって最低限の簡単さというわけでもなく、普通に実用的なプラグインとして使えそうな感じです。
pic090313_06.jpg pic090313_07.jpg

長くなってしまったので、今回はここまでにします。次回以降でオリジナルのプラグインを作ってみたいと思います。
(ちなみに、Windowsでも試してみようと思ったのですが今のところまだうまくコンパイルできていません。もう少し調べてみたいと思いますが、Windowsの開発環境(VisualStudio、MinGW、Cygwin、LCCなどで試してみています)自体についてかなり勉強しないと難しそうな感じです。ちょっと無理っぽいような...。)
posted by mato at 01:32| Comment(0) | Blender | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。