LoginSignup
20
10

More than 5 years have passed since last update.

Wire SolverでなくFor-Eachを利用したワイヤー表現

Last updated at Posted at 2016-12-04

この記事はHoudini Advent Calendar 2016の四日目の記事です。

この記事では
・Stroke SOP
・Ray SOP
・For-Each SOP
・PolyFrame SOP
について記述しています。

*バグが含まれていたので追記しました。新しいhipファイルを一番下に置いています。
forwire2.PNG

DOPで作成する場合

DOPでワイヤーを表現する場合、WireSolverを利用すれば紐の動作を行うことができます。

WireSolverの話は…と書こうと思ったらすでに書かれていますね。
外部リンク:http://nomoreretake.net/2016/09/17/houdinicapture-deform/

確かにDOPを利用すれば正しい動作は期待できます。しかし、solverの欠点は1フレーム目から計算を行わなければ結果が見れないというところにあります。
個人的には何か動作したら、すぐに結果が見たいというもの。じゃあSOPで完結すればいいじゃないか!

SOPでどうすべきか

strokeとrayを利用します!
結果はこんな感じになります。
tube1.png

まずは、ワイヤーの元となるpolylineを作りましょう。

Stroke SOPでワイヤー形状を

strokeでは筆圧など様々な情報が格納されており、いろんな用途に使えそうです。
(ただ今回は筆圧でワイヤーの太さを変える動作はさせないので、いらないattributeは削除しておきます。)
事前にstrokeでpolylineを作成します。traceSOPでもlineを取得できるのですが、strokeで嬉しいのは、1ストローク1primitiveであるということです。つまりforeachで1ストロークごとに処理を行うことができます!
stroke1.png

Ray SOP

rayはpointの法線方向にある物体に向かって瞬時に張り付きます。(ProjectRayがデフォルトで@Nのため)
この機能を利用して疑似的にワイヤーがからまるような表現を行います。

▼raySOP
ray.png

法線方向についてはProjectRayで相手のオブジェクトに対して法線を方向手動で入れてもいいですし、Minimum Distanceを利用して最短距離を求めるのもいいと思います。
sphereなどについては、下のWrangle(Run Over:Points)のように書いて重心をターゲットにするのもいいかもしれません。

vector min, max;
getbbox(1,min, max);
vector target = (min+max)/2; 
@N=normalize(target-@P);

・getbbox(min, max);でなくgetbbox(1,min, max);と書くことで2番目のinputのバウンディングボックスを取得することができます。

ひとまず法線の方向に何らかのオブジェクトを配置します。(でなければpointは微動だにしません)

ForEachでループ処理

forの話は…と書こうと思ったらすでに書かれていますね。
外部リンク:http://nomoreretake.net/2016/01/08/houdini_for-loopsop/

ForEachの全体

Houdini15からforノードができてbegin-endのblock内で処理ができるようになりました。
これで毎回subnet内に入る必要がなくなります。(ただネットワークがでかくなる…)
target.png

ダブルBlock-begin

今回工夫している点はpieceとfeedbackを複合させ、次のループの下準備を前のループで行っている点です。
2つのeachはそれぞれの役割を持ちます。左側のpieceは名前の通りワイヤーを一本ずつ運んできます。右のfeedbackにはrayに衝突させるためのオブジェクトが入ります。途中PolyWireを入れています。これは次のループの衝突用オブジェクトです。このループで出力されるのは、変形したpolywireだけでなく衝突用オブジェクトも含まれます。衝突用オブジェクトは、ガイド用のため最終的に出力したいワイヤーの太さの2倍にしておきます。そうすることで干渉が起きにくくなります。
guide.png

なぜこんな工夫が必要なのか?

通常のfeedback処理は、処理を行うオブジェクトのみループします。しかし今回のように衝突用オブジェクト(sphere)をfeedback前にmergeしたら、foreachの結果にも残ってしまうので、最終的に衝突用オブジェクトが11回重複してしまいます。しかし、rayを当てるオブジェクトの更新は行いたい。ということで、一時的に衝突用のオブジェクトは消さずfor脱出後に削除を行います。衝突用オブジェクトを削除するために先にgroupを指定しておき、最後に削除します。
foreach.png

▼衝突用オブジェクトのガイド削除後
out.png

ダブルeach(old)

旧foreachサブネットにおいても同様の事が可能です。
デフォルトで入っているeachに加えてeachをもう一つ新規で作成し、feedbackにチェックをいれ、自分自身をFor pathに入れます。これで同様の動作が可能です。
double.png

PolyFrameのtangentとpeakを利用した延長線

PolyFrameの接線の話は…と書こうと思ったらすでに書かれていますね。
外部リンク:http://nomoreretake.net/2015/09/07/houdini_curve_tangent/

Houdiniではcarveを利用してpolylineを簡単に削ることはできますが、伸ばす場合には少々工夫が必要です。
peak.png

1:PolyFrameのtangentをNにセットする

▼まずはすべてのポイントを接線の方向に向かせます。
tan.png

2:Wrangleで法線を整える

各primitiveの0と最後のポイントのみ法線を残し、ほかの法線は一時的に{0,0,0}をセットします。
Wrangle(Run Over:Points)

if(@ptnum==0){@N=-@N;}
else if(@ptnum!=npoints(0)-1){@N=set(0,0,0);}

3:primitive分foreachで回す

▼foeachからの出力
normal.png

4:peakで伸ばす

peakは各pointからの法線方向に向かって自身のpoint座標を移動させます。
先ほど先端以外は法線を除去しておいたので、先端以外が動くことはありません。
normal2.png

5:法線を元に戻す

このままではこのあとのsweepに支障が出るので元に戻します。

Sweepでpolylineからワイヤーに

polylineのprimitive attributeにCdがある場合はpoint attributeにattribute promoteを行います。primitive attributeはSweepが行われる際に破棄されます。(ただ、後ほどmaterialでCdを利用する場合はprimitive attributeである必要があるので、Sweep後に戻します。)
tube2.png

まとめ

foreachはHoudiniの中でもかなり利用頻度の高いSOPのため、できるだけ早い段階で習得をオススメします。
▼全体のネットワーク
11.png

以上
*nomoreretake様、勝手にいっぱいリンク張って申し訳ありません。

hipファイル(old)
https://drive.google.com/open?id=0B8-SILG4S2_fcWU2T1ZGVkVPdlk

追記 2018/05/18

なんか重いなと思ってたら、致命的なバグが含まれていました。
feedbackの最初にgroup化を忘れており、最終結果にガイドで利用した過去のワイヤーが含まれておりました。
大変申し訳ありません。正しくはこちら feedback beginブロックの次にgroupを追加しています。

正しくはこうでした.PNG

feedbackは全て削除する必要があったので、sphereのグループに含む必要がありました。
軽くなったので、大量にワイヤーを配置できます。

色とスケールのコントロールがしやすいように手を加えています。
Edit parameter Interfaceでfolderを利用することでパラメータの増減ができるようにすると、拡張性があって便利です。
maincontrol.PNG
Folder TypeをMultiple Parm(list)にすることで+ -できるパラメータ群を作れます。NameとLabel内の#には増やした分の固有のID(1から割り振られる)が適用されます。
mult.PNG
増減するパラメータは、この変数で対応します。
一例ですが、floatとvectorで指定するサンプルを入れています。

set_wire_scale_color
int wireTypeLen=chi("../Main_control/wire_scale_variety_folder");
int wireType= floor(rand(@primnum)*(wireTypeLen))+1;
f@wirescale=chf("../Main_control/wire_scale_variety"+itoa(wireType));
float wcR=chf("../Main_control/wire_color_variety"+itoa(wireType)+"r");
float wcG=chf("../Main_control/wire_color_variety"+itoa(wireType)+"g");
float wcB=chf("../Main_control/wire_color_variety"+itoa(wireType)+"b");
v@wirecolor=set(wcR,wcG,wcB);

新しいhipncファイルです。
hipファイル(new)
https://drive.google.com/open?id=1UM06A0Df2mfv_lILu17A61syafP-kHF8

いろんな形状を入れたりrayのパラメータを変化させていろんなワイヤー表現が可能です
test1.PNG

20
10
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
10