50
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

HoudiniAdvent Calendar 2017

Day 1

Step Up Houdini!階段をつくろう

Last updated at Posted at 2017-11-30

この記事はHoudiniアドベントカレンダー2017 1日目の記事です。

Houdiniには多くの機能があり、目的に対して様々なアプローチがあります。
(そこが面白いところでもあり、難しい所なのですが。)

今回は僕がHoudiniを最初に使いだした頃に取り組んでいた「階段」をテーマに
いろんな方法で階段を作っていきます。

*hipファイル:https://drive.google.com/open?id=1cGAutLmJvjvVo4fKyvKneLq3ARVIUdiq

#「普通の階段」
利用SOP:Copy Stamp,Duplicate
normal.PNG

階段を1段ずつ複製します。
複製はCopy StampとDuplicateどちらでも可能です。
copyanddupulicate.PNG

この2つの違いはほとんどありません。duplicateのほうが
copyよりも単純なため少し早い程度の違いです。

#「らせん階段」
利用SOP:Resample,PolyFrame,Copy Stamp
spiral.PNG
lineやcurveを利用して、階段を作成します
polyframeを利用すると、簡単に法線、接線、従接線を取得できます。
polyff.PNG

法線が正しく設定されていれば、copySOPが正しい向きに階段を配置してくれます。
spiral2.PNG

#「ぐにゃぐにゃ階段」
利用SOP:Divide,Foreach
階段が常に直線とは限りません。特殊な形状の階段を作るにはどうすればいいでしょうか。
上の段になるほど、横幅を縮めるstampやscaleを利用する方法もありますが、ここではdivideを利用してみます。

まず、階段にしたい形状を用意します。
gunya1.PNG
Wrangleにはupvectorとpscaleのばらつきを設定します。

points
@up={0,1,0};
@pscale=chf("stairwidth")+rand(@ptnum);

sweepを行います。
gunya2.PNG

そのあとはdivideで一度内側のエッジを全て削除します。
removesharededge.png
その直後にもう一度divide(BrickerPolygon)を行います。xとzは仮の数値として1000という大きい数値が入っています。
divide(BrickerPolygon)はバウンディングボックスの端を0として計算しているので、大きすぎる数値が入ると分割がされません。これを逆手にとってy方向のみ段差の高さで分割します。
xz1000s.png

段差別に分割されたので、段差ごとに平らにしていきます。段差1段につき1primitiveとなっているので、Foreach内でprimitiveのscaleをY座標:0にして平坦化させます。

pettan0.png

#「岩の階段」
利用SOP:VoronoiFracture,VDB
iwa.PNG

ぐにゃぐにゃ階段の応用として、VDBを使って岩の階段を再現します。

岩は人工物ではないので、切れ目がランダムです。しかし、完全なランダムではありません。
なぜならば、人が歩きやすい階段にするために、あるルールをもって配置するからです。
では、この場合の配置ルールを想定してみます。

①1段の高さは等しい
②1段を2つに分割する必要はない
③切れ目は縦に切れている

以上のルールを実現するために、ボロノイを利用します。
ただボロノイをかけると、ボロノイっぽくなってしまうので、段差ごとにForeachをかけてseedの違うscatterを発生させます。
voronoi6s.png

scatterの偏りを生じさせるために、scatter前後にZ方向の縮小をかけます。
右に行くほどscatterを行った際にZ方向の縮小が強くなっています。前段階のtransformでZ:0.5とした場合、元に戻すために後ろのtransformで1/0.5として、元の大きさに戻します。
voronoi5.png

ボロノイで縦にしすぎると岩らしさが無くなってしまうので、ちょうどいい塩梅を見つけます。

ボロノイの注意点として、gridのように高さのない面の場合はそのまま切れるのですが
高さのある面の場合は、backfaceにサーフェスができることがあります。

ですので、一度上を向いているサーフェスだけ抽出します。
抽出するためには法線が上に向いているかを確かめればよいので、法線と{0,1,0}の内積をとります。
上を向いている場合は-1、下を向いている場合は1になっています。

primitives
if(dot(@N,{0,1,0})<-0.5){
 removeprim(0,@primnum,1);
}

下向きのbackfaceは一度削除します。

次に岩の角を丸める処理を追加します。今回は、resampleを利用した後にrelaxをかけて丸みを追加します。
そして、polyextrudeを行った後、groupを利用して70度以上のedgeを取得します。そのgroupにpolybevelを
加えます。(なんとなく岩っぽく変形した?)駄目押しで、一度ポリゴンからVDBの変換を行います。
voronoi7.PNG

これらの一連の処理を岩1個ずつforeachで回します。本当は重くなるので、やりたくないのですが、
VDBの解像度をかなり上げないと岩同士がくっついてしまいます。
*VDBSmoothで丸みをつけることや、VDBcombineのSDF~で岩の傷をランダムに与えることも可能です。

問題ないレベルになったら、converVDBでポリゴンに戻します。
最後はポリゴン数を抑えて、autoUVを適用します。

#「エスカレーター」
利用SOP:Wrangle(UVアニメーション)
es0.gif

エスカレーターは足場をループをさせる必要があります。
今回は法線の向きに気を付けて、頂点をUVに沿って移動させる手法を取ります。

##UVをNURBS Curveから取得する
UVとNURBS Curveの相性は抜群です。なぜならば、NURBSの始点がUVの0、終点が1になるからです。UVTextureのTextureTypeはUniformSplineを選択します。
UVNURBS.PNG

UVが取得できたので、一見このまま進めばいいように思えます。しかし、ここで落とし穴があります。
エスカレーターのようにUVがループ状になった場合、頂点とUVでずれが生じます。始点(0)と終点(11)は別のPositionにいるにも関わらず同じUVの値を持っています(0=1)。
例:UV0の頂点位置からUV1の頂点位置に移動すると一周したように思うが実際は頂点0の前の頂点11にいる
UVNURBS3.png
この状態を解消するにはNURBS CurveのArc TypeをClosedからOpen Arcに変更するか、Carve(Curveじゃないですよ)を利用する必要があります。Carveの方がポリゴンをNURBSにコンバートした後の始点移動調整が簡単なので便利です。
UVNURBS4.png

落とし穴はもう一つあります。
ループさせるために始点と終点をfuseで繋げようとするとどうなるでしょう。
UVNURBS6.png

fuseするとattributeが補完されてしまうので(1+0)/2となり0.5となってしまいます。
解決策としては。Wrangleで

points
if(@ptnum==0){
@uv.x=0
}

を直接代入するか、fuseを利用せず始点か終点のどちらかの頂点を削除した後addSOPで結合させます。

##addSOPでポイント番号順にVertexを繋げる
addSOPを利用してClosedな状態に変換します。addSOPはこのエスカレーター作成の肝となります。
なぜaddSOPか。それはpolyLineやpolyを簡単に作ることができるからです。
Add3.png

UVNURBS7.png
これを、ポイント番号が整列された4つのpolylineに適用すると、エスカレーターの形ができます。
Add6.png

##primUVで頂点をぐるぐるする
全ての下準備が完了しました。最後はprimuvを利用して回転を行います。

points
float uvp=@Time*ch("../control/speed");
float puv=(uvp+@uv.x)%1;
@P=primuv(1,"P",0,set(puv,0));

esloop.gif

ポイントはpuv=(uvp+@uv.x)%1の「剰余(%)」です。UVは0から1の範囲で値があるので、単純にオフセットしていくと1を超えてしまいます。そこで余剰を行います。すると0~0.999はそのままに、1.0 が 0.0 、 1.2 が 0.2に変換されて取得できます。結果としてUV内でループが発生します。
そしてprimuvでポイントを@Timeや@Frameなどを利用してオフセット分ずらします。

法線の方向は人が乗っている間は平衡にする必要があります。
そこでバウンディングボックス内に存在するpointのY座標の法線を0にしてnormalizeします。
esloopN.gif

法線が正しく設定されたのでcopystampで台をコピーすればいい感じの方向に向いてくれそうですね。
最後に、手すりなどいろいろくっつけて、エスカレーターの完成です!

#まとめ

以上5つの階段でした。このように同じテーマだけど違うやつに取り組むと
自分の知らない機能についての知見も増えると思います。

様々な方法を知れば知るほどHoudini力はステップアップしますよ。

次は satoruhigaさんの「HoudiniをOSCタイムラインとして使う」です!

50
23
0

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
50
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?