AnastasiaのProcedural Mandala Pattern VEX tutorial : VEXコード


前回の記事でアルゴリズムの説明をしたので、今回は実際にVEXコードの説明をしていきたいと思います。

 

サンプルファイルは以下からダウンロードすることができます。
https://gum.co/CltRS

 

初期設定

まずは Grid SOP、Divide SOP で高解像度のグリッドを作ります。アルゴリズム編で説明したセルはここではポイントとして扱います。まず、Circle SOP で円を作り、Attribute Wrangle SOP でこれらのノードを繋ぎます。各SOPの設定は下図を参照してください。

 

そして Attribute Wrangle の中に下のコードを書きます。pcfind()関数はインプットから、指定したポイントに一番近いポイントの番号の数を配列で返します。今回はグリッドの各ポイントから半径 0.09 の中を検索し、もし Circle SOP で作ったポイントが見つかったら(最大で1つだけ)自分のポイント番号を返し、pcloud 配列に代入しています。そして if 文で、pcloud 配列の要素数をチェックし、0 以外(何かポイントが見つかった場合)は state を 1 。色を黒にしています。

int pcloud[] = pcfind(1, “P”, @P, 0.09, 1);

if (len(pcloud) != 0)
{
    f@state = 1;
    @Cd = {0,0,0};
}

 

 

すると、Circle SOP で作ったポイントの部分だけ色が黒くなりました。これが前回のアルゴリズムの部分で説明した、ステップ 1 の段階です。次に For ループにより繰り返し処理を加えていきます。

 

曼荼羅作成

Forループを作ります。Iteration Method や Gather Method は図のように変更してください。Iterations はとりあえず50にしてあります。そしてループの中に Attribute Wrangle SOPを追加し、この中で曼荼羅を作るコードを書いていきます。

 

以下が全VEXコードです。小分けにして説明していきます。

float lookup_dist = ch(‘lookup_distance’);
int max_neighs = chi(‘max_neighours’);
float div = ch(‘division’);

int neighs[] = pcfind(0, “P”, @P, lookup_dist, 100);
int found = 0;
foreach(int n; neighs)
{
    if (point(0, “state”, n) != 0 & n != @ptnum)
        found++;
}

if (found > 0 & found <= max_neighs)
{
    f@state += found / div;
}

@Cd = 1 – clamp(f@state, 0, 1);

 

 

まず最初の3行はパラメーター用です

  • Lookup Distance : 自分自身のポイントからどれだけ離れた場所までチェックするか(半径)。
  • Max neighbours : 自分自身のポイントの値(state)をアップデートするかどうかのスレッショルドで、 Lookup Distance 内にある、値が 0 より大きいポイントの数がこのスレッショルドよりも多い場合は自分自身の値を変更しません。
  • Division : Lookup Distance 内で見つかった値が0より大きいポイントの数の合計を割る値。
float lookup_dist = ch(‘lookup_distance’);
int max_neighs = chi(‘max_neighours’);
float div = ch(‘division’);

 

  • 次にpcfind()関数によって自分の周りのポイント(最大100個まで)をneighs[] 配列に代入します。
  • found 変数を宣言し、0 より大きい値のポイントのカウント用に使います。
  • foreach() で配列に入っているポイントに対してループ処理します。
  • ポイントの state アトリビュートが 0 でなく、ポイント番号が自分自身の番号でない場合に found を 1 増加させます。
int neighs[] = pcfind(0, “P”, @P, lookup_dist, 100);
int found = 0;
foreach(int n; neighs)
{
    if (point(0, “state”, n) != 0 & n != @ptnum)
        found++;
}

 

 

  • 次にIF文のチェックで、found が 0 より大きい(値を持っているポイントを見つけた場合) かつ、found が Max neighbours で指定した値以下である場合に、自分自身の値(state)に found を div で割った値を加算します。
  • そして最後に clamp() 関数 で state を 0 – 1 にクランプして、1 から引いています(白黒反転)。
if (found > 0 & found <= max_neighs)
{
    f@state += found / div;
}

@Cd = 1 – clamp(f@state, 0, 1);

 

 

コード入力が終わったら、Forループの end にディスプレイフラグを付けると、曼荼羅模様が出来るのが確認できます。

 

色を付ける

VEXでランプパラメーターを作ることで色をつけています。Division パラメーターを増加させると中間色が増えるので、ランプで色をつけやすくなります。

@Cd = chramp(“color”, @Cd.r);

 

 

その他

初期化のときに使ったCircle SOP で円を大きくしたり、ポイントの数を増やしたりすると、それに応じて模様も変わります。いろいろと試してみましょう!