見出し画像

3Dプリントシュミレーター

Houdiniゆるゆる会 006に参加するために、3Dプリントのできあがる様子を説明した動画を作ってみました。3Dプリントのできあがる様子とはいっても、正確なシミュレーションなどではなく、右側の渦巻状のフィラメントが移動して、左側のモデルの外周をなぞるように形状を映し出すというシンプルなものです。
テーマは【推しノード】ということで、この作例では特にAttribute Copyについて語っています。

断面のラインを渦巻状にして縦につなげる

プリントされて出来上がってきた側を作成します。この形はインプットした形の周辺を螺旋を描くようにポイントが打たれて、つながっている状態です。
まずは形状を等間隔にスライスします。

ボロノイで分割することで、安定してモデルをカットできる
Exploded View で確認するとモデルがカットされている

For Each Connected Pieces でカットされたパーツごとに処理します。断面の上向きのものだけを取り出し、それをライン化します。

Resample で分割ラインを一定の間隔にしておく
ライン化

ラインを帯状にします。上向きの面を取り出したので、ポイント番号は常に時計回りに回っています。attribwrangle_convert_spiral という名前でVEXを書き、ポイント番号分だけ高さ方向にオフセットして、更にこの処理が動くごとに処理一個分オフセットします。それによって一つの螺旋と全く同じ位置に次の螺旋が来るようになります。

説明の順番のために高さをオフセットするVEXから説明
// attribwrangle_convert_spiral

float a = ch("../line1/points");
int i = detail(-1,"iteration",0);
@P.y = @ptnum/float(@numpt-1);
@P.y += float(i);
わるくなさそう…!

ポイントの開始位置を調整する

一見問題なさそうですが、この処理ではポイントの開始位置が一位に定まっていないので螺旋同士で位置がずれてしまうことがあります。これを修正します。
attribwrangle_get_shift というVEXで一番右のポイント番号が総ポイント番号からどれくらい差があるのか、をだします。この値の分だけ、ポイント番号をずらせば常に一番右側に最初のポイントを持ってくることができます。

螺旋がつながらない
attribwrangle_get_shift と Sort を追加
// attribwrangle_get_shift 

vector max = getbbox_max(0);
float max_X = max.x;
if(@P.x==max_X){
setdetailattrib(0, "shift", @ptnum, "set");
}
きれいにつながった

ちなみに単純にBy Xでソートすればよいのでは?と思われるかもですが、そうした場合、せっかくの時計回りに番号が連続してるという特性が失われてしまいます…

 VEXをなくし、By X で Sortした場合

できあがる形状のグループを時間で増やす

できあがった形状は縦に伸びているので、Match Sizeで形を整えます。

GroupノードでTimeというグループを作り、そのグループはフレーム番号以下のものを含むようにします。時間がたつに従ってグループが増えます。

@index<$F
下のポイントがグループ化される

螺旋を作成する

別ストリームに螺旋を作成します。
このあと、螺旋のポイントを順番に豚の位置に移動したいので、螺旋のポイント数を豚のポイント数に一致する必要があるのですが、LabsのSpiralにはポイント数を直接指定する機能があるので、Spare Inputで豚を参照してnpoints(-1)でポイント数を一致させます。便利ですね。
こちらにも同じくEnumerateとGroupをつけて、同じようにindexとtimeグループを生成します。リファレンスコピーしておくと簡単&安心です。

リファレンスコピー は非常に便利

Attribute Copy

Attribute Copyを行い、Timeグループに属しているポイントを螺旋から豚に移動させます。
見た目をちょっと良くするためにTimeでちょうど切り替わるポイントの位置を豚よりも少し高い位置に固定してベベルをかけています。

Attribute Copyは名前の通り、一致するポイントやプリミティブのアトリビュートをコピーします。今回はPアトリビュートをコピーしているので、ポイントの座標が移動しています。『転写する』と考えると、感覚的に近くにある場所を基準に転写しそうな気がするのですが、このAttribute Copyはポイント番号さえ一致していれば、全く違う形状に移すことも可能です。Houdiniにおいては座標さえもアトリビュートの一つにすぎない、というのが非常に重要です。
さらに時間によって増大するグループのものだけをコピーしているので、徐々に移動するということができるわけです。

Pアトリビュートをコピーする
時間によって豚が整形されていく

余分なラインをなくす

ここからはこのネットワークの欠点を修正していきます。
豚のときには気が付きませんでしたが、人型を出力すると腕や足の間にラインが生成されて見苦しいです。これをなくしていきます。

このラインはAttribute Copyする前の生成物ではみられません。つまり、螺旋のラインが一本につながっているので、線がすべて繋がって腕や足の間にもラインが引かれているのです。

すべてのラインをなくしてしまうのではなく、もともとつながっている部分はつなげたままにしたいのですが、ここでまたAttribute Copyを使います。整形したラインを予め螺旋の形に整形しておけば、同じように切れているラインが出来上がるという寸法です。

移動前に成形物のラインのポイントを移動して螺旋状にしておく
よくみると螺旋が時々切れている…が今回はこれでよしとします
腕や足の間の線がなくなった

体型が変わってしまったのを治す

つぎに体型が変わってしまっているのを治します。
これは最初に断面をパーツごとに処理して、処理回数ごとにずらしているので、本来同じ高さであるはずの腰と腕を異なった位置にオフセットしてしまっているのです。

不思議な形でこれはこれで味わいがある…
腰と腕の断面、これを同じ高さになるように一度に処理したい

腕と腰を一度に処理したいので、For Each Connected Pieces で処理せずに、高さをアトリビュートに与えてそのアトリビュートごとに処理する仕組みに変えます。
まずはそれぞれのパーツごとに平均の高さを出します。

先に高さのアトリビュートindexをつくっておく
// attribwrangle_make_index

float p = floor(@P.y*100);
i@index = int(p);

断面のラインを渦巻状に処理する部分を変更します。
螺旋の始端を決める処理はパーツごとに行う必要があるので、多重ループになっています。オフセットする高さはループの回数ではなく、平均の高さのアトリビュートなので、高さがおかしくなることはなくなりました。

体型も変わらなくなった

この記事が気に入ったらサポートをしてみませんか?