[Houdini] SDFを滑らかにくっつける

久々にHoudiniネタになりそうなことをやったのでメモまでに。
画像右側のやつみたいに滑らかにSDFをくっつけます。


VDBめっちゃ便利ですね。何が便利ってやはり軽さ。軽さが尋常じゃない。
かつてのVolumeでは考えられなかったほどの高解像度なボリュームデータが手軽に扱えます。
快適です、ほんとに。
Sparse Volume万歳!!!

更にHoudiniでは、というかVDB公式のツールなのかもしれませんが、VDBを手軽に扱うための様々なノードが用意されています。
そして大体のことはこれで事足りる。素晴らしい。素晴らしすぎる。

ただし、今回やったSDFのなめらかな結合に関しては特にノードが用意されているわけでもなく、自分でやらないといけません。
・・・あれ?ないですよね?そういうノード??(自信ない)
まぁひとまず無いということにします。なので自分で作りました。(他の方法知っている人は是非教えてください)

で、具体的な方法ですが、こんな難しそうなものは僕には方法が思い浮かばないので、先人の知恵をお借りすることにしました。

Levelsets in production: Spider-man 3
上記のリンクはACM Libraryのものですが、同名で検索すると普通にPDFがダウンロード出来るので、ACM会員じゃない&中身に興味のある方は是非どうぞ。

これは2007年のSiggraphで発表されたもので(10年前!?)、スパイダーマン3のサンドマンを作成する際のLevel set(SDFの事だと思ってもらって大丈夫です)の活用事例と言ったところでしょうか。
そんでここにはサンドマン誕生シーケンスで用いられたSDFのBlendingに関する情報が数式付きで書いてあります。
超最高。超、最高。

あとはこの数式をVolumeに当てはめるだけなんですが、Houdiniでこれをやろうともうと実はそのままではダメでした。
というのもスパイダーマン3で使用されたField ToolsはField 3Dの前身とも言えるツールセットだそうで、簡単に言ってしまうとVDBとは符号が逆です。

なのでほんのちょっとだけ計算に手を加えてあげる必要があって、結果的にはこうなります↓

// パラメータ
float a = 0.1; // ブレンド半径
float b = 2; // ブレンドのスムーズ具合 
float y = 0.5; // ブレンドの押し出し加減

// 各SDFの値
float A = volumesample(1, 0, v@P);
float B = volumesample(2, 0, v@P);

// SDFの値を元にしたブレンド値のベース
float m = (clamp(abs(a-A), 0, a) / a) * (clamp(abs(a-B), 0, a) / a);

// ブレンドしたSDFの値をsurfaceに設定
f@surface = min(A, B) - pow(m, b) * y;

変数名はPDFに似せてあります。
α=a, β=b, γ=yです。

いやー良い感じ。
ダニエルさんありがとう!!!

コメントを残す

メールアドレスが公開されることはありません。