« 光学ドライブが再認識… | トップページ | C4D ChannelShader…09 前回の記事を参考に「ChannelShader…06」で失敗したコードを修正してみる »

C4D ChannelShader…08再挑戦

今回は、C.O.F.F.E.E.SDKを見ながらでもプラグインが作れるユーザが対象です。
実は、自分もC.O.F.F.E.E.SDKを見ながら作ってます。

以前取り上げた、C4D マテリアルチャンネルシェーダプラグイン…

C4D ChannelShader
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelshad.html

C4D ChannelShader…02
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-1.html

C4D ChannelShader…03
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-2.html

C4D ChannelShader…04 最小限とは…
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-3.html

C4D ChannelShader…05 出力カラーにNoiseクラスを使用
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-4.html

C4D ChannelShader…06 ダイアログを取り付ける…
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-5.html

C4D ChannelShader…07 前回の問題は保留にして… チャンネル値
http://villager-and-c4d.cocolog-nifty.com/blog/2009/10/c4d-channelsh-6.html

初挑戦で知識不足の為、挫折…

と言う結果に終わりました。
再挑戦です。

まずい…C.O.F.F.E.E.を触ってないと、以前のコードをパッと見しても何をしてるのかわからない…

前回の記事を踏まえて、一から始める事にします。
前回の記事は読まなくても良いです。軽くスクロールして下さい。

前回は、何処まで成功して、何処で失敗したのか…

成功から…
CannelShaderPluginとしてC4Dの起動時に認識させ、組み込みに成功。
マテリアルエディタからチャンネルシェーダとして選択に成功。
マテリアルエディタからテクスチャボックスや2Dプレビューアイコンをクリックしダイアログを表示に成功。
このダイアログへの入力に成功…?

失敗は…
チャンネルシェーダ毎のダイアログ値を保持できず、シーン中のチャンネルシェーダのダイアログ値が全て同じ値になってしまう。

結局、チャンネルシェーダ毎の値を保持する方法を探り出せずに挫折したのでした。

今回は打開できるのか…

まずは、ChannelPluginフレームワークは、こんな具合ですね。

/*
ChannelShaderPlugin
testChannelPlugin
*/


var pluginID = 1000007;

//testChannelPlugin ===============================================================
class testChannelPlugin : ChannelPlugin
{
  public:
  testChannelPlugin();

  GetName();
  GetID();

  GetInfo(settings);

  InitSettings(settings);
  InitRender(settings);

  Message(settings , message);
  EditData(settings);

  Output(settings , render , p , n , d , t , texflag , vd);
};

// ローカル変数等を初期化
testChannelPlugin::testChannelPlugin(){super();}

// シェーダの名前を戻す。
testChannelPlugin::GetName(){return "testCHShader";}

// http://www.plugincafe.comから取得した、このプラグインの為のplugin idを戻す
//テストID:1000001-1000010

testChannelPlugin::GetID(){return pluginID;}

// CHANNEL_DIRECTBUMPとCHANNEL_RAYTRACINGのコンビネーションを戻す
testChannelPlugin::GetInfo(settings){return;}

// シェーダセッティングを初期化
testChannelPlugin::InitSettings(settings){return;}

// rdとしてOutput()機能に渡される何かを戻す
testChannelPlugin::InitRender(settings){return;}

//ハンドルC4Dメッセージ
testChannelPlugin::Message(type , data){return;}

// ユーザがシェーダをダブルクリックする時に呼ばれる
// ダイアログなどを表示する

testChannelPlugin::EditData(settings){return;}

//指定されたポイントで色を戻す
testChannelPlugin::Output(settings , rd , p , n , d , t , texflag , vd){return;}



//main ============================================================================
main(){
  //C4Dへシャーダーの登録
  Register(testChannelPlugin);
}

ChannelPluginクラスのメンバ関数の簡単な説明。

GetName()
  チャンネルシェーダ名をreturnで返します。

GetID()
  このプラグインの為にPluginCafeより取得したIDをreturnで返します。

GetInfo() ---- オプション
  バンプにベクトルを使う場合CHANNEL_DIRECTBUMPをreturnで返す。
  独自のレイを計算させる場合CHANNEL_RAYTRACINGをreturnで返す。

InitSettings() ---- オプション
  シェーダの作成/アップデートされる度に呼ばれる。
  渡されたsettingsの初期化。
  TRUEを返す。

InitRender() ---- オプション
  レンダリング直前に呼ばれる。
  Output()へ渡すRenderDataをreturnで返す。

Message() ---- オプション
  プラグインから、シェーダにメッセージを送る事が可能。
  メッセージIDは、message->GetID()で検索する事が可能。

EditData() ---- オプション
  2Dプレビュやマテリアルボックスがクリックされると呼ばれる。
  ダイアログを使ってシェーダ固有のデータを編集させる。
  TRUEを返すと、マテリアルプレビュー等が更新される。
  ダイアログでキャンセルが押されたならば、FALSEを返す。

Output()
  サーフェスの色をreturnで返します。

これが、正解しているかは自信がありません…

最小限のチャンネルシェーダです。

/*
ChannelShaderPlugin
testChannelPlugin
*/


var pluginID = 1000007;


//testChannelPlugin ===============================================================
class testChannelPlugin : ChannelPlugin
{
  public:
  testChannelPlugin();//コンストラクタ

  GetName();//チャンネルシェーダ名
  GetID();  //プラグインID

  //ポイントPの色
  Output(settings , render , p , n , d , t , texflag , vd);
};

testChannelPlugin::testChannelPlugin(){super();}

testChannelPlugin::GetName(){return "testCHShader";}

// http://www.plugincafe.comから取得した、このプラグインの為のplugin idを戻す
//テストID:1000001-1000010

testChannelPlugin::GetID(){return pluginID;}

testChannelPlugin::Output(settings , rd , p , n , d , t , texflag , vd){
  return vector(1.0 , 0.0 , 0.0);//赤を返す
}



//main ============================================================================
main(){
  Register(testChannelPlugin);
}

最小限にしたChannelPluginメンバ関数は、コンストラクタと名前を返すGetName()、IDを返すGetID()、サーフェスの色を返すOutput()です。
上のコードは、サーフェスを強制的に赤に着色します。

では、ダイアログを取り付けて、マテリアルエディタで追加されたチャンネルシェーダ毎にカラーを設定できるようにして見ます。

ダイアログの学習は以前の記事で取り上げましたので、この辺りで…
http://villager-and-c4d.cocolog-nifty.com/blog/2009/08/c4d-247b.html
http://villager-and-c4d.cocolog-nifty.com/blog/2009/08/c4d--02-7a26.html
http://villager-and-c4d.cocolog-nifty.com/blog/2009/08/c4d--03-e989.html
http://villager-and-c4d.cocolog-nifty.com/blog/2009/08/c4d--04-e3f3.html

今回は、カラーピッカーを使ってみようと思います。
ダイアログ部分のみです。

/*
ColorChooser ModalDialog
*/


enum{
  DIALOG_GROUP = 1000,
  COL_PICER
}

//cpic_dialog =========================================================================
class cpic_dialog : GeModalDialog
{
  public:
    var col;

    cpic_dialog();
    Init();
    CreateLayout();
    AskClose();
}

cpic_dialog::cpic_dialog()
{
  super();
  col = vector(0.5 , 1.0 , 0.5);
}

cpic_dialog::Init(){
  SetColorChooser(COL_PICER , col , 1.0 , 1.0 , 0.0);
}

cpic_dialog::CreateLayout(){
  SetTitle("チャンネルカラー");
  AddGroupBeginV(DIALOG_GROUP , BFH_SCALEFIT , 1 , "group-1" , 0);
    AddGroupBorder(BORDER_GROUP_IN);
    AddGroupBorderSpace(10 , 5 , 10 , 5);

    AddColorChooser(COL_PICER , BFH_SCALEFIT , 0 , 0 , NO_BRIGHTNESS);

  AddGroupEnd();

  AddDlgGroup(DR_DLGGROUP_OK | DR_DLGGROUP_CANCEL);
}

cpic_dialog::AskClose(){
  col = GetColor(COL_PICER);
}

この状態のままでは何も起こりませんが、定義されたダイアログはこの様なものです。

Channelshader_19

では、最低限のチャンネルシェーダにダイアログを組み込みます。

/*
ChannelShaderPlugin
testChannelPlugin
*/


var pluginID = 1000007;



enum{
  DIALOG_GROUP = 1000,
  COL_PICER
}



//cpic_dialog =========================================================================
class cpic_dialog : GeModalDialog
{
  public:
    var col;

    cpic_dialog();
    Init();
    CreateLayout();
    AskClose();
}

cpic_dialog::cpic_dialog(){super();}

cpic_dialog::Init(){
  SetColorChooser(COL_PICER , col , 1.0 , 1.0 , 0.0);
}

cpic_dialog::CreateLayout(){
  SetTitle("チャンネルカラー");
  AddGroupBeginV(DIALOG_GROUP , BFH_SCALEFIT , 1 , "group-1" , 0);
    AddGroupBorder(BORDER_GROUP_IN);
    AddGroupBorderSpace(10 , 5 , 10 , 5);

    AddColorChooser(COL_PICER , BFH_SCALEFIT , 0 , 0 , NO_BRIGHTNESS);

  AddGroupEnd();

  AddDlgGroup(DR_DLGGROUP_OK | DR_DLGGROUP_CANCEL);
}

cpic_dialog::AskClose(){
  col = GetColor(COL_PICER);
}



//R_data===============================================================
//testChannelPluginクラスのInitRender()が返すクラスです。
class R_data
{
  public:
    var col;
}



//testChannelPlugin ===============================================================
class testChannelPlugin : ChannelPlugin
{
  public:
  testChannelPlugin();//コンストラクタ

  GetName();//チャンネルシェーダ名
  GetID();  //プラグインID

  InitSettings(settings);//settingsの初期化
  EditData(settings);    //ダイアログ
  InitRender(settings);  //RenderDataの作成

  //ポイントPの色
  Output(settings , render , p , n , d , t , texflag , vd);
};

testChannelPlugin::testChannelPlugin(){super();}

testChannelPlugin::GetName(){return "testCHShader";}

// http://www.plugincafe.comから取得した、このプラグインの為のplugin idを戻す
//テストID:1000001-1000010

testChannelPlugin::GetID(){return pluginID;}

testChannelPlugin::InitSettings(settings){
  settings->SetData(0 , vector(0.5 , 1.0 , 0.5));//チャンネルシェーダの基本カラー
  return TRUE;
}

testChannelPlugin::EditData(settings){
  var dlg = new(cpic_dialog);      //ダイアログの割り当て
  dlg->col = settings->GetData(0); //
  dlg->Open(-1 , -1);         //ダイアログを開く
  if(!dlg->GetResult())return FALSE; //ダイアログでキャンセルするとFALSEを返す。
  settings->SetData(0 , dlg->col);  //settingsにダイアログで変更した値を代入
  return TRUE;                      //データを更新するのでTRUEを返す
}

testChannelPlugin::InitRender(settings){
  var ren_data = new(R_data);           //返すべきRenderDataを割り当てる
  if(!ren_data)return NULL;             //RenderDataの割り当てに失敗したらNULLを返す。
  ren_data->col = settings->GetData(0); //settingsから、RenderDataへ代入する。
  return ren_data;                      //RenderDataを返す。
}


testChannelPlugin::Output(settings , rd , p , n , d , t , texflag , vd){
  return rd->col;
}



//main ============================================================================
main(){
  Register(testChannelPlugin);
}

testChannelPluginクラスにも、InitSetings()/EditData()/InitRender()を追加しました。
InitRender()が返すRenderDataクラスを追加しました。

ダイアログのcpic_dialogクラスのコンストラクタ内でメンバ変数colを初期化していましたが、削除しました。

チャンネルシェーダのtestChannelPluginクラスの追加したメンバ関数の説明です。

InitSettings()メンバ関数
シェーダの作成/更新の度に呼ばれる。
ここで、渡されたBaseContainerクラスのsettingsのID:0へ初期チャンネルカラーを設定します。
returnでTRUEを返します。

EditData()メンバ関数
変数dlgへチャンネルカラーを設定するモーダルダイアログであるcpic_dialogクラスを割り当てます。
ダイアログのメンバ変数colへ渡されたsettingsコンテナのID:0の初期カラーを代入。
ダイアログを開き、キャンセルが押されたらFALSEを返して終了です。
カラーが変更されOKが押されれば、ダイアログのメンバ変数から変更されたcolをsettingsのID:0へ代入しTRUEを返します。

InitRender()メンバ関数
レンダリング直前に呼ばれる関数です。
このメンバ関数が返さなければいけないRenderDataを変数ren_dataへ割り当て、渡されたsettingsのID:0のカラーをren_dataのメンバ変数colへ代入し、最後にreturnでこれを返します。

これで、Output()メンバ関数内で、渡されたsettingsのID:0、もしくは、InitRender()で返されたRenderDataであるrd内のメンバ変数colから、ダイアログで設定されたカラーを取得します。
今回は、取得したカラーに手を加えずに、returnでそのまま返しています。

Channelshader_20

今回は、マテリアル毎にダイアログで設定の変更、値の保持が成功しています。
マテリアル毎だけではなく、チャンネル毎でも問題なく動作しています。
Channelshader_21

でも、なぜダイアログで設定した値が設定したシェーダ毎に保持できるのか不明…
シェーダの更新イベントが起こる度に、InitSettings()が呼ばれ、カラーが初期化されます。
InitRender()で返すRenderDataもInitRender()がレンダリングされる前に必ず呼ばれ、その度に、新規で割り当てられます。

そうすると、一体どこに変更したデータが保持されているのかがわかりません。

「testCHShader_ReTry.ZIP」

|

« 光学ドライブが再認識… | トップページ | C4D ChannelShader…09 前回の記事を参考に「ChannelShader…06」で失敗したコードを修正してみる »