【Houdini】みんな大好き「らせん十字モデル」を自由自在かつ秒速で生成する【2/3】
こんにちは! 今回もらせん関連です!
もうこのブログめっちゃグルグルが好きな人のブログみたいになっちゃってるよ...
とりあえず前回は、らせんのカーブに沿ってMeshをはる方法を紹介させていただきました!
急に今回の記事にたどり着いてしまった方は、ぜひ前回の記事から読んでみてね!!
さて、面を張ったらせんモデルですが、こういうのってだいたい先端が尖っていたり、INとOUTでフェードアウトができると良い感じ、ってことがほとんどですよね。
そこらへんを自由にカスタマイズできるようにしていきます。
まずは形状。 Sweepノードの「Sweep」タブの「Transform Using Attributes」のチェックをはずします。
このチェックを外すと、下の3つのパラメータを編集してSweepの結果を加工することができるようになります。
注目したいのは「Scale」のアトリビュートです!
この「Scale」、全体の太さとか細さをスケーリングしてくれる値なんですが、このスケール値、「カーブの中間は今のままで、先端だけ細くして~」とかワガママを聞いてくれたらいいな~、なんて考えちゃうわけです。
まずは、「このへんはこんな感じで!」と操作をする必要があるので、パラメータを増やしましょう。
今回は「処理結果と似たような見ためになる」ので、floatのrampパラメータを使います。
もともと存在していないパラメータを増やすには、右上の歯車アイコンからでしたね。
「Edit Parameter Interface」から小さいウィンドウを呼び出して...
「By type」タブからRamp(float)を選んで、右のツリーに追加します。 パラメータの名前も分かりやすいものをつけておくと◎
Rampパラメータが追加されるので、パラメータの名前を右クリックして「Copy Parameter」をえらびます。
さきほど編集できるようになった、「Scale」パラメータの値を消して、右クリックして「Paste Relative References」でエクスプレッションを貼り付けます。
「Paste Relative References」で貼られる「ch(“〇〇”)」というエクスプレッションは、そのパラメータの値を1つしか返してくれません。
今回は「それぞれの位置に対応するRampパラメータの値」が欲しいので、 これを書き換えます。
chramp("SpiralShape",$PT/($NPT-1),0) これでHoudini先生に対して、「"SpiralShape"っていうRampパラメータの、$PT/($NPT-1)の値ちょうだい!float値(浮動小数)で。」って言っていることになります。
まず、「chramp」は、2番目の引数で指定したポイントのRampの値を返してくれる関数です。
日本語にだと分かりづらいと思うので、画像で説明します。。。
今書いている関数は、2つめの引数(上記の画像のオレンジの部分)に定数ではなく、さらに「$PT/($NPT-1)」というエクスプレッションを書いています。
Rampを反映させるには、「ここのポイントの場合は、Rampのここ!」っていうの(2つめの引数)を、各ポイント番号ごとに求めなきゃいけないわけです。
しかも、chrampのヘルプページによると、「2番目の引数は0~1で指定してね!」って書いてあります。
http://www.sidefx.com/docs/houdini/expressions/chramp.html
つまりどうにかして、このポイントたちの位置を0~1の数値で表してあげる必要があります。
マジかよ難しそうだよできるかな...。
とりあえず、いきなり関数が書けなさそうなときは、 具体的な数字でやってみるのがセオリーです。
「10コのポイントがあるなかの、3つめのポイントの位置」を、0~1の範囲で求めてみましょう!
実は、図解してしまえば小学校の「さんすう」レベルの知能の人ならできる問題だったよ!
ポイントが10コのときの3番は、「0~9番まであるうちの3番」なので、 「3/9」 になります。
(なんで割り算なのかピンとこない人は、「3/9」を分数として読んでみてね)
ではもうちょっと数字をあいまいに。
ポイントがn個のときの3は、「0~(n-1)まであるうちの3」なので、 「3/(n-1)」になります。
(ポイント番号は0から始まるので、総数より1つ少ない)
ここまで来れれば、もう簡単ですね!!
ポイント番号は「$PT」です。 ポイントの総数は「$NPT」です。
ポイントが$NPT個のときの$PTは、「0~($NPT-1)まであるうちの$PT」なので 「$PT/($NPT-1)」になります!
もともと入っている式になりました!
ちなみに「現在のフレーム数」とか、「このモデルのポイント番号をそれぞれ」みたいな、「数字の代わりに使える、$とか@とかつくようなヤツらの名前」は、「エクスプレッション変数」って呼ぶみたいです。
Houdiniの公式ヘルプを見たり、Google先生に「Houdini expression variables」とかで聞くといろいろ出てきます!
あと、XからYまでの範囲を0~1までの範囲にあてはめなおす(リマップする)ことは、「正規化(ノーマライズ)」って言うそうです。
明日から「あぁそのパラメータ、0~1の範囲にじゃないと正しい結果にならないよ。正規化してあげないと(ドヤァ」って言えば、なんかデキる人っぽい雰囲気を醸し出せる...かもしれません。(誰も得をしない)
長くなってしまったので、まとめとして「chramp("SpiralShape",$PT/($NPT-1),0)」をムリヤリ日本語に直すと、
「各ポイントごとに、それに対応するRampの値」
ってことになります。
これで、「先が尖っている」どころか、Rampで自由自在に変形させることができるようになりました!!
もう、どんなリテイクも怖くない...!!!!!
※さすがにこんなにモデルはめったに使わないけど※
形状の調整はこれで事足りそうなので、 次は「先端でフェードアウトさせたい(モデルに頂点カラーを設定したい)」って部分ですね!
これも、モデルがどんな形状になっても引き継ぎ&修正が簡単にできるようにしたいので、UV座標をもとにして、モデル全体にグラデーションをかけてみようと思います。
処理が複雑なので、VOPでやっていきましょう!
Sweepから、「attributeVOP」を繋ぎます。
VOPの中に入って、まずはUVの座標を使いたいのでbindノードを作って、名前を「uv」にします。(小文字だよ!)
また、bindノードはデフォルトではfloat値(浮動小数1つ)を呼んでくれる設定になっていますが、今回は「UV座標」なので、UとかVとかが1セットにまとめられた数値です。
UVだから2つセット...と思いきや、GeometrySpreadsheetで見てみると、実は3つで1セットのようです。
(本当はUVW座標だったんだね...!Wいつも0だけど...!)
と、いうことでTypeは「3float(vector)」に変えてあげましょう。
U座標とV座標をそれぞれ別に加工したいので、 「UV座標」としてセットになっている数値を個別にバラします。
「3つセットをそれぞれバラバラ」は、もうおなじみですね!
「Vector to Float」です!
グラデーションをかけたいので、Rampパラメータを用意しましょう。 U用とV用で2個作ってあげてください。
ちなみに、このパラメータ自体はfloatの計算ですが、RampのタイプはRGBのままにしておきます。
UIがグラデーションの方がイメージし易いので!
UとV、それぞれの結果を掛け算します。
あと、これは無くても上手くいくときは上手くいくんですが、念のため。 数値のケタの丸め込みをしちゃいます。
実はHoudini、長~い少数(小数点第3位以下から先)がいっぱいある計算が、あまり得意じゃないんです。
なので、最終的な計算結果はズレちゃうかもしれないけど、小数点第三位以下の違いなんて人間の目ではジャッジできない誤差なので、切り捨てちゃいます!
まず、最終的に、計算結果はFloat型の「Alpha」に渡すことになるので、Rampの掛け算の結果のRチャンネルだけを貰ってきましょう。
さらに、その数値を100倍します。定数は「constant」ノードで入れられます!
100倍した結果を、Round to Integerノードに渡します。
(Round to Integerは、少数点以下をぶった切って整数にしてくれるノードだよ!)
最後に「÷100(×0.01)」をしてあげれば、すべては計画通り!
「クッソ長い少数?知らないよ?そんなのあった?」って訳です。
(計算結果が0.000141421356....とかだと、fbxエクスポートしたときにバグっちゃうんですよねぇ...)
「bind export」ノードのnameを「Alpha」にして、結果を渡してあげましょう。
頂点カラーアルファは、最初が大文字なので注意してくださいね!
あ、あとこれもFBXにエクスポートするときのためのおまじないなんですが、「Cd」にConstant(Vector)で1を渡しておきます。
(Cdが存在していないと、頂点カラーが無視されてしまうので...)
これで仕組みは完成です! キーボードのUキーでSOPネットワークに戻り、Rampパラメータの挙動を確認してみましょう~。
※VのRampを触ってみたらほとんどのAlphaがゼロになっちゃった!という方は、Sweepの第一入力の大元のLineノードの分割数をすこし増やしてみてください^^
うまく動けば、ネットワーク自体は完成です!!おつかれさまでした!!!
次回は、FBXに書き出すためのおまじないと、HDA化です!
あっ・・・Meshのエクスポートだけは、有料ライセンス(indie以上)じゃないとできないです><
(最後にノードを1つ繋ぐだけなので、Apprenticeで勉強中の方もゴール「は」できます...![書き出せないけど])
本日も最後まで読んでいただきまして、ありがとうございました!!