stamp を使わないでCopyする


今回はstamp を使わないでCopyする方法を紹介します。

 

今回のサンプルファイルです。
Copy.zip

 

Copy Stamp はHoudini の初級チュートリアル等にもよく使われており、stamp() 関数を使ったバリエーションの変化などはHoudiniをある程度触られた方なら経験された方も多いと思います。 しかし、Copy Stampを使うとシーンが複雑になった時に、処理が極端に遅くなる現象を経験したことはないでしょうか。

例として200*200の計40,000個ポイントを持つGridにBoxをCopy Stampしてみました。

左下のステータスバーの経過時間を見ての通り、ここでは、Copy Stampにディスプレイフラグを立ててから、処理が完了するまでに7秒かかっていることがわかります。ちなみにこちらでは、1000*1000の計1,000,000個のポイントの例も試したのですが、処理が完了するまで5分近くかかってしまいました。

この処理時間の遅さは、実はCopy Stampが原因であり、Copy Stampを他の手法に置き換えるだけで改善することがあります。

 

色、Transform等はポイントアトリビュートに

例えば色やトランスフォームを利用したい場合はCopy to Pointノードが利用できます。これは必要な情報をstampのvariableではなく、アトリビュートとしてGird側のポイントに格納する方法です。

Copyで使うことの出来るアトリビュートの一覧は、SideFX公式サイトのヘルプに記載されています。今回はランダムなアトリビュートを付けたいのでAttribute Ramdomize SOPを用いてpscale,orient,Cdのアトリビュートを作成しています。

 

先ほどと同じ結果が出るものを、Copy to Pointを用いて作成すると、このように処理が一瞬で終わることが確認できるかと思います。

 

ジオメトリにバリエーションを付ける場合は For Each ループで

また、For Each ループでひとつひとつのポイントに対して加工をしてからコピーをするという手法もあります。しかし、この手法は注意する必要があり、コピーするポイントの数や処理内容によってはstamp() 関数を使うよりも低速になってしまうことがあります。

 

そこで、以前に紹介した、コンパイルブロックを利用します。コンパイルブロックについては、「H16新機能 コンパイルブロック 8」 「H16新機能 コンパイルブロック 9 Spare Input」 を参照してください。

図のように For Eachをコンパイルブロックで囲んでしまえば、処理はかなり高速になります。これはコンパイルブロックで囲われた部分は並列化処理されるように設定されるからであり、このFor Eachは並列処理ができるからです。裏を返せば、並列化されないような処理であればコンパイルブロックの効果はありません。

Houdini 15までと異なり、Copy系のノードは機能に応じて複数のノードに分かれてわかりづらくなってしまいましたが、その代わりとして、それぞれのCopyがコンパイル対応になりました。過去の記事でも記述しましたが、コンパイルブロックを使う場合は、ジオメトリのバリエーション作成に使えるノードはコンパイル対応のSOPしか使えなくなってしまうので注意が必要です。ちなみにstamp()関数が並列処理できないため、Copy Stampノードはコンパイルブロックには対応しておりません。

 

まとめとしますと、Copy Stampはひとつで色々なことができる便利なノードですが、処理が遅くなりがちで、多数のオブジェクトのコピーの際には不向きです。そのような用途の場合はCopy to PointやFor Each+コンパイルブロックなどのアプローチを用いることでコピーにかかる処置時間を大幅に短縮することが可能です。