« 「c4d csc スクリプト」で検索された? | トップページ | MoGraphのCOFFEEエフェクタって? »

CINEMA 4D フォーラムの「衝突判定」を少し考えてみた。

以前に「衝突判定」をこのブログでも取り上げたと思うけど…
ハチャメチャだったような…

CINEMA 4D フォーラムでの、「衝突判定」の回数のカウント…
https://www.tmsmedia.co.jp/phpbb/viewtopic.php?f=4&t=58&p=185#p185

CINEMA 4D フォーラム
https://www.tmsmedia.co.jp/phpbb/index.php?sid=f5d23813d2f30f3d7cc1472691fa770b

では、XPressoの「衝突判定」の回数のカウントを少し考えてみよう。

XPressoの「衝突判定」…
静止画ではなく、アニメーションだよね。
ま、断定は可能性の幅を狭めるから良くないけどね。
もしかしたら、静止画だってXPressoの「衝突判定」使うかもしれないしね… あるかなぁ…

標準ノードでのXPressoは、既にCINEMA 4D フォーラムで公開されているので、このブログではC.O.F.F.E.E.ノードを使います。
一応、C.O.F.F.E.E.ノードもPythonノードも標準ノードだけどね。

さてと…

アニメーションだから、アニメーションの先頭フレームで初期化。
フレーム間で値を維持するには、グローバル変数。

「衝突判定」ノードはポリゴンオブジェクト限定の衝突判定だね。

XPressoはこんなイメージなるだろう…か?

Collisioncounter_01

C.O.F.F.E.E.ノードの入力InputBoolは、ブール。
出力のcountは整数です。

今回は、「衝突判定」のカウント。と、言うよりも…
どちらかと言うとboolの変化のカウントをC.O.F.F.E.E.ノードで作成する。と言った方が良いだろうか?

Collisioncounter_02

横軸が時間(フレーム)、青の折れ線が入力されたbool値の変化だとしよう…
そうすると、offからonの立ち上がりの赤い部分をカウントすると言う事です。
ま、on/offと書きましたが、正確には TRUE/FALSE ですね。

C.O.F.F.E.E.ノード
/*
off->on counter
2011.2.24
*/


//グローバル変数
var pre_bool; //前フレームのbool値
var c; //カウンター

main()
{

}

まずは、こんな感じ。
グローバル変数で、前のフレームのbool値(pre_bool)と、FALSEからTRUEに変化したカウント値(c)を保持します。
グローバル変数は、main()関数の外で定義します。

次はmain()関数内です。

0フレーム時、もしくはグローバル変数に値が設定されていない時は初期化します。

C.O.F.F.E.E.
var doc = GetActiveDocument();
var tm = doc->GetTime();
var fm = tm->GetFrame(doc->GetFps());

if(fm == 0 || c == nil){
    pre_bool = FALSE;
    c = 0;
}

アクティブなBaseDocumentの取得
現在のフレーム数を取得するためBaseDocumentからBaseTimeを取得します。
BaseTimeから、BaseDocumentからFPSを取得したものをパラメータにして、現在のフレーム数を取得します。

フレーム数が0の時か、グローバル変数に値が設定されていない時、pre_boolをFALSE、cを0にリセットします。
グローバル変数に値を設定しないで宣言したときは、初期化に注意しよう。
nilの状態で比較やインクリ/デクリ、計算等に使用するとエラーが起こります。
今回は、グローバル変数cがnilの場合は、pre_boolもnilなので、cのみの比較にしました。

この、C.O.F.F.E.E.ノードには、入力:InputBool、があります。
InputBoolは現在のbool値で、pre_boolが前のフレームのbool値です。
pre_boolがFALSE、InputBoolがTRUEの時、カウンタ:cを1つ加算します。

C.O.F.F.E.E.
if(pre_bool == FALSE && InputBool == TRUE)c++;

最後に…
次のフレームの処理のため、pre_boolにInputBoolの値を代入します。
C.O.F.F.E.E.ノードの出力:countにカウンタ:cを代入します。

C.O.F.F.E.E.
pre_bool = InputBool;
count = c;

全体は…

C.O.F.F.E.E.
/*
off->on counter
2011.2.24
*/


//グローバル変数
var pre_bool; //前フレームのbool値
var c; //カウンター

main()
{
    //フレームの取得
    var doc = GetActiveDocument();
    var tm = doc->GetTime();
    var fm = tm->GetFrame(doc->GetFps());

    //0フレームでリセット
    if(fm == 0 || c == nil){
        pre_bool = FALSE;
       c = 0;
    }

    //FALSE->TRUEをカウント
    if(pre_bool == FALSE && InputBool == TRUE)c++;

    //最後の処理
    pre_bool = InputBool;
    count = c;
}

これで完成だと思いますが…

「CollisionCounter_01.ZIP」をダウンロード

ビュー上でのアニメーション再生は問題ないのですが、レンダリングをすると問題が発生します。

原因は、C.O.F.F.E.E.ノード内での現在のフレームの取得に問題があります。

アクティブなBaseDocumentを取得し、そこから現在のフレームを取得すると言うことは…
タイムラインルーラーのタイムスライダの位置を取得すると言うことです。

Script_install_04

ビュー上のアニメーション再生では、タイムスライダーが移動しますので、フレーム数が変化します。
レンダリング中は、タイムスライダが動いているわけではありませんので、値は変化しないようです。

問題の解決策は、C.O.F.F.E.E.内で現在のフレーム数を取得しないで、外部からもらう。

ただし、時間(BaseTime)を入力して、C.O.F.F.E.E.ノード内でフレームを取得するには、FPS値を取得しなければならなく…
GetActiveDocument()でアクティブなBaseDocumentをわざわざ取得しなければならない。
その為だけに、アクティブなBaseDocument取得したくないので、入力はフレームにしました。

Collisioncounter_03

C.O.F.F.E.E.ノードの追加した入力fmは、整数。

そうすると、時間の取得の部分が、まるまま削除できます。

C.O.F.F.E.E.
/*
off->on counter
2011.2.24
*/


//グローバル変数
var pre_bool; //前フレームのbool値
var c; //カウンター

main()
{
    //0フレームでリセット
    if(fm == 0 || c == nil){
        pre_bool = FALSE;
       c = 0;
    }

    //FALSE->TRUEをカウント
    if(pre_bool == FALSE && InputBool == TRUE)c++;

    //最後の処理
    pre_bool = InputBool;
    count = c;
}

「CollisionCounter_02.ZIP」をダウンロード

でも、使い勝手(使いまわし)の事を考えると、フレーム(時間)を入力するよりも、リセットするか否かのboolを入力した方が良いのではないだろうか?
その方が、アニメーションの途中でリセットが必要になったときに自由にリセットができるわけで…

Collisioncounter_04_2

C.O.F.F.E.E.ノードの入力resetはブールです。

0フレームとアニメーション途中で、別に用意したオブジェクトに衝突したら、C.O.F.F.E.E.ノード入力resetがTRUEになり、グローバル変数がリセットされます。

C.O.F.F.E.E.
/*
off->on counter
2011.2.24
*/


//グローバル変数
var pre_bool; //前フレームのbool値
var c; //カウンター

main()
{
    //0フレームでリセット
    if(reset || c == nil){
        pre_bool = FALSE;
       c = 0;
    }

    //FALSE->TRUEをカウント
    if(pre_bool == FALSE && InputBool == TRUE)c++;

    //最後の処理
    pre_bool = InputBool;
    count = c;
}

「CollisionCounter_03.ZIP」をダウンロード

これで、「off -> on カウンタ」の完成です。

公開したファイルはC4D R9.6で作りました。
R12でも動作します。

C4D Pythonノードでも同じようになると思うけど…

C4D R9.5以前のユーザは乗り換え版が有効なのか…
いくらだろう…
Studioは無理だなぁ…Primeかなぁ…

|

« 「c4d csc スクリプト」で検索された? | トップページ | MoGraphのCOFFEEエフェクタって? »

コメント

コメントを書く



(ウェブ上には掲載しません)




« 「c4d csc スクリプト」で検索された? | トップページ | MoGraphのCOFFEEエフェクタって? »