以下は、Houdini上でWrangleを使ってメンガーのスポンジ(Menger Sponge)を生成する一例です。
この例では、DetailWrangleノード内で再帰的に各立方体の中心位置とサイズ(pscale)を計算し、後段のCopy to PointsノードでCube(Box)をインスタンスする方法を示します。
手順
-
新規ジオメトリノードを作成
HoudiniのNetwork Viewで新しいジオメトリ(Geometry)ノードを作成し、中に入ります。 -
Detail Wrangleノードの配置
中に「Attribute Wrangle」ノードを作成し、Run Over を「Detail (only once)」に設定します。
このWrangleで、再帰的なメンガーのスポンジの点群(各立方体の中心位置とサイズ)を生成します。 -
パラメータの追加
Wrangleノードのパラメータペインで、以下のパラメータを作成してください。-
iterations
(Integer):再帰回数(例:3~4程度) -
size
(Float):初期の立方体のサイド長(例:1.0)
-
-
以下のVEXコードをDetail Wrangleに貼り付け
// パラメータ取得 int iterations = chi("iterations"); // 再帰回数 float init_size = chf("size"); // 初期立方体のサイド長 vector start_pos = {0, 0, 0}; // 初期位置(原点) // 配列を用意:positions と scales vector positions[]; // 各立方体の中心位置 float scales[]; // 各立方体のサイド長 // 初期状態:1個の立方体(原点、サイズ = init_size) append(positions, start_pos); append(scales, init_size); // 各反復で、各立方体を3x3x3に分割し、メンガーのスポンジとして不要な部分を除去する for (int iter = 0; iter < iterations; iter++) { vector new_positions[]; // 次段での立方体中心位置 float new_scales[]; // 次段での立方体サイズ int n = len(positions); for (int j = 0; j < n; j++) { vector pos = positions[j]; // 子立方体のサイズは親のサイズの1/3 float s = scales[j] / 3.0; // 3x3x3のグリッド(ix, iy, iz = 0,1,2) for (int ix = 0; ix < 3; ix++) { for (int iy = 0; iy < 3; iy++) { for (int iz = 0; iz < 3; iz++) { // 3軸それぞれで、中央(値が1)の数をカウント int cnt = 0; if (ix == 1) cnt++; if (iy == 1) cnt++; if (iz == 1) cnt++; // メンガーのスポンジのルール:中央および面中央は除去(カウントが2以上なら除外) if (cnt < 2) { // 子立方体の中心位置は、親の中心から (ix-1, iy-1, iz-1) * s だけずらす vector newpos = pos + set((ix - 1) * s, (iy - 1) * s, (iz - 1) * s); append(new_positions, newpos); append(new_scales, s); } } } } } // 次の反復用に更新 positions = new_positions; scales = new_scales; } // 最終的に生成された各立方体の中心にポイントを作成し、"pscale" 属性にサイズを設定 int npts = len(positions); for (int i = 0; i < npts; i++) { int pt = addpoint(0, positions[i]); // Copy to Pointsノードでインスタンスする際、pscale属性でサイズが決まる setpointattrib(0, "pscale", pt, scales[i], "set"); }
-
Copy to Pointsノードの配置
- Detail Wrangleノードの出力に接続して、「Copy to Points」ノードを配置します。
- 2番目の入力(右側)に、インスタンスとして用いるBox(Cube)ノードを接続してください。
※Boxのサイズは1単位としておき、pscale属性により各立方体のサイズが適用されます。
-
表示と調整
- 作成したCopy to Pointsノードを表示すると、指定した反復回数に応じたメンガーのスポンジが得られます。
- Wrangle内の
iterations
やsize
の値を変えて、生成のレベルや大きさを調整してください。
以上の手順とコードで、SOPとWrangleを組み合わせたメンガーのスポンジの生成が可能です。
この基本手法をもとに、さらに色付けや変形、アニメーションなどを加えることで、より複雑な表現にも発展させることができます。
グラデーション例
// バウンディングボックスの最小/最大値を取得
vector bbmin, bbmax;
getbbox(0, bbmin, bbmax);
// ジオメトリ中心を算出
vector center = (bbmin + bbmax) * 0.5;
// バウンディングボックスの半径(中心から最も遠い距離のおおよその値)
float max_radius = length(bbmax - bbmin) * 0.5;
// 各ポイントの中心からの距離を計算
float d = length(@P - center);
// 0~max_radius を0~1に正規化
float t = fit(d, 0, max_radius, 0, 1);
// Rampパラメータ "color_ramp" に基づいてグラデーションカラーを設定
@Cd = relbbox(0, @P)*chramp("color_ramp", t);
メンガーのスポンジについては
すでに数年前に堀川さんがYoutubeにもあげられています
https://www.youtube.com/watch?v=-bass6YzWEA