トランジスタスタジオ・秋元純一氏によるHoudini連載「Houdini Cook Book」がリニューアル! Houdiniをより基礎の部分から解説し、最後にはふり返りとして課題も用意しています。第3回はSweep SOPを活用したフレキシブルなモデリングのアプローチについて解説します。


秋元純一 / Junichi Akimoto
株式会社トランジスタ・スタジオ/取締役副社長
2006年に株式会社トランジスタ・スタジオ入社。日本でも指折りのHoudiniアーティスト。手がけてきた作品は数々の賞を受賞している
Sweep SOPとVDBを活用したアプローチ
今回は、Sweepを使ったモデリングの例を紹介します。
Houdiniでは、Sweep SOPと言う、Curveなどを用いてフレキシブルにメッシュを生成する機能があります。
単純にCurveに沿って押し出すだけではなく、自動的にUVを生成したり、形状をコントロールしやすいパラメータなどもあらかじめ用意されていたりなど、非常に使い勝手が良いノードのひとつで、筆者自身もHoudiniのはじめの一歩としての参考に、よくサンプルに使用するノードでもあります。
今回は単純にそれを使用するだけではなく、他のアプローチと絡めて、より複雑な形状を作成する方法を探っていきたいと思います。
本編には、VDBなどの要素も登場します。これは、形状を直接つくるためというよりは、補助的な役割で使用しています。Houidniでは、本来の使用方法とはずらして、その機能を余さず発揮するためのアプローチが多く存在します。
今回のようなシチュエーションでは、Sweep SOPでのモデリングのために、あらゆる面でトリッキーなアプローチを使ってみました。セミオートマティックなフローになっていますが、完全なプロシージャルモデリングよりもコントロールがしやすく、筆者が好むアプローチのひとつです。
01 Projection Geometry Flow / ベースとなるジオメトリの下準備

STEP 01
まず、ベースとなるジオメトリを用意します【A】【1】。
STEP 02
そのジオメトリにVDB from Polygon SOP【B】を使って、SDFのVolumeへコンバートします【2】。このSDFをVDB Reshape SDF SOP【C】のDilateで外側に太らせ【3】、さらにVDB Smooth SDF SOP【D】で滑らかにします【4】。このSDFをConvert VDB SOP【E】でPolygonへ変換します【5】。


STEP 03
このPolygonにVOP【F】を使って、元々のジオメトリにフィットするしくみを作成します。VOP内でXYZ Distance VOP【G】を使い、元々のジオメトリと自身のPositionから近似するPositionのPrimitiveとそのUVを取得します。
Primitive Attribute VOP【H】を使って、そのPrimitiveとそのUVの値を基に、元々のジオメトリのPositionを取得し、それを自身のPositionへ代入します。これにより、近似するPositionへフィットさせることができます【6】。



STEP 04
次に、Line SOP【I】でベースとなるジオメトリのY軸方向への長さを基にラインを作成し、分割したい数のPointを設定します。このPointを基に、Voronoi Split SOP【J】で輪切り状に分割します【7】。
次に、Convex Decomposition SOP【K】を用いて、輪切りにしたパーツごとにジオメトリをConvexで変換します。これにより、大きな凹みのないジオメトリを作成することができます【8】。

STEP 05
このConvexジオメトリを上記の手順と同様にVDBを使って整理し【L】、最後にRemesh SOP【M】で綺麗なメッシュを作成して完了です【9】。これで、元のジオメトリを包み込むようなプロジェクション用のジオメトリを作成することができました。
今回のアプローチでは、有刺鉄線を巻くためのジオメトリを作成するところから始めています。そのためには、ある程度ガイドとなるジオメトリだけではなく、プロシージャルモデリングを見据えた下準備をしておくと、手作業でもオートでもある程度対応しやすいジオメトリとして使用できます。
何も準備がないと、フローが重くなったり、エラーが回避できなかったりします。Houidniのアプローチにおいては、後のフローを予測した下準備は欠かせません。
02 Base Curve Flow / ベースとなるカーブの下準備
次に、先ほど作成したジオメトリに巻き付けるカーブの準備をします。

STEP 01
プロジェクション用のジオメトリを使って、それにStroke SOP【A】で自由にカーブを描いていきます【1】。
今回はセミオートマチックなアプローチにしたので、Stroke SOPのようなマニュアルなオペレーションをしていますが、例えばここをCurve SOPのような編集可能なオペレーションに変更しても良いと思います。しくみとしてのながれが問題なければ、組み換えも可能です。
STEP 02
Stroke SOPで描いたラインは、今回のような螺旋状のものだと、どうしても途切れ途切れで描く必要があるため、Join SOP【B】でラインをつなげていきます。Resample SOPで綺麗に分割し、Attribute Noise SOPでPに対してNoiseをかけて歪ませます【C】【2】。
STEP 03
次に、プロジェクション用のジオメトリをPeak SOP【D】で調整し、前項で行なったような、ジオメトリにフィットさせるアプローチを行います【E】。ここでは、Positionだけではなく、Normalも取得しておきます【F】。


STEP 04
Smooth SOP【G】で”N”を滑らかにして、VOP【H】を使って”N”方向へNoise【I】の値で膨らませます【J】。このとき、Noiseに負の値が入らないように、Clamp VOP【K】で0以下はクランプします【3】。



STEP 05
これらを、Convert SOPでNURBSにして滑らかにし、Resample SOPでPointを均一にします【L】。さらにPoly Frame SOP【M】を使って、Tangent方向へ”N”を作成し、Bitangent方向へ"up"を作成します【4】【5】。
これでベースとなるカーブの作成が完了しました。



03 Sweep Flow / 最終的なSweepのながれ

STEP 01
ベースカーブにSweep SOP【A】を用いて、NURBSのメッシュを生成します【1】。
このとき、RotationにはTwistの設定をします。制御しやすい回転の仕方で良いですが、今回はPer Edgeでの回転角で制御しています【2】。NURBS【B】にする理由は、次のCarve SOP【C】でラインを抜き出すためです【3】。
Extractを使用して、ねじれているカーブを抽出します。このとき、Carve SOPを2つ用いてずらして抽出します。これに対して、Convert SOPやResample SOPでラインを綺麗に整理し【D】、最終的なメッシュをSweep SOP【E】で作成します【4】。
STEP 02
次に、有刺鉄線の棘のパーツを作成します。Spiral SOP【F】を使って、コイル状のカーブを用意します【5】。
これに対して、Poly Frame SOP【G】で”N”と"up"を作成します。その後、Group Expression SOP【H】で、コイルのスタートとエンドのPointをGroup化します【6】。
このPointをそれぞれPeak SOP【I】で法線方向へ引き伸ばします【7】。
このカーブに対してSweep SOP【J】でメッシュを作成し、スタートとエンドのPoint位置にBoxを配置します【K】【8】。このBoxを使ってBoolean SOP【L】で端をカットします【9】。これで棘のパーツが作成できました。
次に、ベースカーブから棘を配置するPointを、Group Range SOP【M】で、数個飛ばしのPointを選択します【10】。
また、Copyを行う前に、Attribute Noise SOP【N】で"up"に対してNoiseを追加して、ランダムな回転が入るようにします。Copy to Points SOP【O】で棘を配置すれば、有刺鉄線の完成です【11】【12】【13】。


04 Hints / 制作に役立つヒント
Open VDB

今回、プロジェクション用のジオメトリを作成する際に登場したVDBですが、これはOpenVDBというオープンソースのVoxel制御のためのツール群を総称してVDBと呼んでいます。
まずは通常のVolumeを作成するためのVoxelと何が異なるかを理解しましょう。
HoudiniネイティブのVolumeは、Uniformな状態で、直方体状のバウンディングボックス内に立方体がきっちりと整列しているものです。例えば、データが格納されていない状態のVoxelも存在しないといけません。
それに対してVDBは、データが格納されていない状態の場合、そのVoxelは生成されず、歯抜けで隙間が空いた状態でVoxelを作成できるため、非常に軽い状態でVolumeを扱うことが可能になります。また、VectorのVoxelは、3つのScalarのVolumeとしてだけではなく、Vector Volumeとして扱うことができるため、さらに無駄にデータを保持せずに済みます。
何はともあれ、VDBはこの数年で非常に浸透しており、膨大で大量のVoxelを扱う上では欠かせないものとなっています。
次に、FogとSDFのちがいを学びましょう。
Fogは密度を格納するVoxelで構成されています。主にDensityというVoxelを用いて、そのジオメトリの密度から、様々なアプローチに用いることができます。例えば、密度の濃い場所にPointを配置したり、エフェクトであれば、例えば密度をソースとして用いたりすることが可能です。
SDFはSigned Distance Functionの略で、ジオメトリのサーフェス表面からの距離を保持します。例えば、表面を0とした場合、内側か外側かで符号を付加し、その距離を測ることができます。そのため、衝突判定などに用いると便利です。
今回のアプローチでは、SDFを用いてジオメトリの形状自体を調整し、判定モデルの作成に役立てましたが、モデリング的に用いると非常に便利な場面が多く存在します。
VDBはその軽さから、非常に細かなVoxelをもつことができるので、モデリングのディテールを保持しながら編集可能になり、使い勝手が非常に良いです。直接的にジオメトリを作成するのに用いたり、今回のように間接的に使用するために用いたりと、その方法は多岐に渡ります。
ぜひ、これを機会にVDBへの理解を深めましょう。
05 Issues / 今回の課題
Issue 01:チェーンのモデリング / Modeling ★☆☆☆☆
チェーンをつくってみましょう。

Issue 02:DNAのモデリング / Modeling ★★☆☆☆
DNAの形状をつくってみましょう。

Issue 03:ランダムなスプライン / Modeling ★★★☆☆
ランダムで大量のカーブを自由に作成し、コントロールしてみましょう。

こちらの制作例は、今回のプロジェクトデータ内に用意しています。ひととおり制作できたら、ぜひ確認してみてください。
今回のプロジェクトデータはこちらから>>TEXT_秋元純一 / Junichi Akimoto
EDIT_小村仁美 / Hitomi Komura(CGWORLD)