この記事はHoudini Apprenticeアドベントカレンダー2019 25日目の記事です。
HoudiniのUV展開とリグについて、網羅的に機能を確認し、自力でUV展開&リグのセットアップができる状態を目指します。
しかし、この記事・・・大変申し訳ないことに、体調不良で100%の状態で完成しておりません。
現状は、だいたい8割ぐらいの内容となっています。できるだけ早く完成させるようにしますので、しばしお待ちください。
#UV展開
まずはUVです。
俺はキャラクターなんか作らないし、HoudiniでUV展開なんて一生しない!!と思っている方もいるかと思います。しかしHoudiniでのUV展開はプロシージャルなプロジェクトにおいて非常に重要な役割を果たします。
なぜかというと、UV展開したUV座標は必ず0~1に収まるからです。この0~1に格納された整合性のあるモデルはプロシージャルの上流において非常に柔軟な素材となります。
キャラクターを作らない方も、この機会にUV展開について勉強してみましょう。
#UVの種類
Geometry内でノードを呼び出す際にuvと検索すると、
けっこうな数あります。
それもそのはず、HoudiniでUV展開する手法は1つではありません。
手動で展開させる場合もあれば、プロシージャルで展開させる場合もあります。
まずは、どんな種類のUV展開があるのかを見ていきましょう。
※前回の復習となりますが、UV展開のビューを見るためには、space+5を押します。
##UV Quick Shade
名前にQuickとあるように、とにかく時間が無いとか、Gridにバシッと一枚絵を出す際に使用します。
UV Quick Shadeの中に入るとMaterialノードがあります。なので1ノード作るだけでshop_materialpathも付与してくれます。滅茶苦茶楽ですね。
デフォルトでは、$HFS/houdini/pic/uvgrid_grey.pic が適用されています。必要に応じて画像を変えて確認してみてください。
ただし、速度と引き換えに自由度はほぼありません。projection方向はX・Y・Zに限定されています。
なんだ、平面のGridぐらいにしか使えないのか・・・。と思われるかもしれませんが、このノードはちょっとした特徴があります。先ほどのQuickShadeのノード内をもう一度見てください。そこには何故かswitchノードがあります。
switchの条件は
if (!hasdetailattrib(opinputpath(".", 1), "currentlayer") || (detail(opinputpath(".", 1), "currentlayer", 0) == 1),
max(haspointattrib(opinputpath(".", 1), "uv"), hasvertexattrib(opinputpath(".", 1), "uv")),
max(haspointattrib(opinputpath(".", 1), "uv" + detail(opinputpath(".",1), "currentlayer", 0)),
hasvertexattrib(opinputpath(".", 1), "uv" + detail(opinputpath(".",1), "currentlayer", 0))))
です。つまり、入力にUVのAttributeが存在しない場合は、平面にUVを貼るけれども、UVを持っている(has***attrib)場合はそのまま利用すると書いてあります。よってこれから紹介するUV展開を行ったあとにQuickShadeを繋げることで簡単にuvgrid_grey.picマテリアルを適用したモデルを確認することができます。
さきほどのUV Quick Shadeは、平面しか使えませんでした。しかし、3Dソフトは普通は立体物を扱います。そこでUV Unwrapを利用します。簡単なUVであれば自動でUVを合理的に平坦化、重複なしのグループに分離してくれます。
ここで重要なのはPlanesです。
今回はBoxを展開させようとしたので、Planesを6としています。
これは、簡単に言えば 左・右・前・後・上・下 の6方向からPlane状にProjectionして、いい感じにUVをカットしてくれます。ただし、Planes=アイランド数ではありません。あくまで形状に応じて切り分けを行ってくれます。
LayoutはカットしたUVをUV座標上にどのように展開したいか
Spacingは各アイランド間のマージンです。
RotateはPlanesをあてがう軸を指定します。
UV Unwrapでは、立方体のような単純なジオメトリならきれいに出力されます。しかし、単純ではない。たとえば、球状のものを展開しようとした場合は、別のノードでUV展開をした方がよさそうです。
UV展開において、もっとも基本となるノードがUV Textureノードです。
平面はもちろん、球状や筒状のものをUV展開しようとした場合は、このノードを利用します。
各投影タイプの解説はこちらから引用
##UV Project
UV Textureは、あくまでTexture Typeを選択するだけでした。
歪んだ形状に展開したい場合は、状況に応じて選択した形状を回転させたくなることがあります。そうした場合は、UV Projectをお勧めします。
UV Projectでは何種類かのProjection手法が準備されているので、形状に応じて最適な手法を選択します。
##UV Flatten
UV Flattenは、このノードだけで正しく展開することはできません。
まずは下準備をした後、後処理が必要となります。
UV Flattenは名前の通り、UVを展開させます。しかし、展開するためにはエッジに切れ目を入れなければなりません。
UVをカットする手法は2種類存在します。エッジを直接指定するか、エッジグループで指定するかです。
###手動でUV展開
SideFXからUV展開のチュートリアルが出ているので、動画で見たい方はこちらから
UVのカットは、選択モードにおいて Cut UV Layout を使用します。
するとBoxが展開されました。
※後日追記
###UV Edit
そこで、UV Editを使用します。これはプロシージャルが破綻するので注意が必要です。
###UV Fuse
合わせて、UVの結合も必要に応じて行います。
が、、方向が斜めになってしまいました。
##UV Transform
これを調整するのが、UV Transformです。
###UV Overwrap
tubeの場合などは、重なってしまう場合があります。
ビューポートオプションから、どの部分が重なっているのか確認することができます。
##UV Pelt
UV Flattenに非常に似ていますが、こちらはストレッチがかかります。
正確に言えば、テクスチャ領域の端側に引っ張ることでUVを緩めます。
これ一つで望ましい形状にするのは難しいでしょう
以下ヘルプ参照
UVPeltは、革職人が皮はぎ(Pelt)を作る動作と非常に似ています。 サーフェスのトポロジーが円盤に近くなるようにジオメトリにカットを加えます。 このサーフェスの境界は、フレームに繋がって、伸ばされます。
閉じたフェースをPeltのフレームとして使うことができます。 フレームを指定しなかった場合は、円が使われます。 カットをした後にPeltするジオメトリの箇所を指定するには、ヒントポリゴンを使います。 ヒントポリゴンを含んだセクションの一番長い境界がフレームに繋げられるエッジになります。
##AutoUV
AutoUVは、非常に楽にUV展開を行ってくれます。
チュートリアル動画はこちら
もともと、AutoUVは、GameDevelopmentToolsetの機能としてリリースされていました。Houdini18では、SideFXLabに統合されています。
SideFXLabのインストールは、今年のアドベントカレンダーにも登場しましたね。
SideFX Labs Toolの新規のインストール方法、Package機能に関して検証してみる
とはいえ、基本的にやることは、これまでのGameDevelopmentToolset同様、アタリのコントローラーから最新版のAuto UVを呼び出すだけです。
このAutoUVは、初めて登場した際は「Shortest Path」と「cluster」の2種類のメソッドが用意されていました。現在のAutoUVは4種類のメソッドが用意されています。デフォルト手法もバージョンに応じて変わっています。
##RizomUV
Houdini18から、SideFXLabにサードパーティのUV展開で非常に高機能な RizomUV の機能を利用できるノードが提供されています。注意点として、2019/12現在、RizomUVはSideFXLabのプロダクションビルドには含まれていません。よって、このノードを取得するには、インストールプロセス中に「Production Build Only」のチェックを外す必要があります。
アップデートすると、ノードが現れます。
さて、このRizomUVですが、Houdiniインストール直後そのままで使用できるわけではありません。RizomUVも別途購入する必要があります(←重要!)
###RizomUVの購入とインストール
まずは、RizomUVソフトウェアが必要です。Rizom LabのWebサイトから30日間の評価版を購入するか、インディーライセンス、もしくはプロライセンスを購入します。インディーライセンスだと、1か月単位(14.9ユーロ:約1800円)、もしくは永久ライセンス(149ユーロ:約18000円)となります。僕はうかうかしていたら、評価期間が切れてしまっていたので、1か月のライセンスを購入します。
購入には、名前、住所、電話番号の入力が必要です。決算方法はクレジットカードの他paypalなども選択できます。
https://www.rizom-lab.com/my-account/licenses/
購入時、もしくはマイアカウント画面でHOST IDの入力を行います。HOST IDとは、rizom-labが発行するPC固有のIDです。
https://www.rizom-lab.com/rizomuv-vs/
このHOST IDはソフトの立ち上げ時、ライセンスアクティベーション画面に表示されています。
なので、このあたりでRizomUVの実行ファイルをダウンロードしてインストールしましょう。
この長いコードをマイアカウント画面でコピペして貼り付けます。
成功するとライセンスファイルをダウンロードできるようになります。
そして、ライセンスアクティベーション画面のFOLDERから、ライセンスファイルが置かれているディレクトリパスを指定します。
アクティベーションに成功すると、RUNのボタンが押せるようになります。
ソフトが立ち上がりましたね。準備完了です。
###RizomUVでUV展開
では、Houdiniの画面に戻ります。
一連のノードでUV展開をするチュートリアルは以下のサイトにあります。
https://www.sidefx.com/ja/tutorials/sidefx-labs-rizomuv-bridge/
動画と同じ豚だと、新鮮味がないので、今回はSideFXLabで突如として現れたtestgeometry_luizを利用します。
※unwrapする前にattributeを削除しておきます。
Rizomuv_unwrapを作成し、ディスプレイフラグを立てると、処理が開始されます。
※処理には多少の時間がかかります。よってAutoCookは切っておいたほうが無難です
※この時点でライセンスが上手くアクティベーションされていない場合は、アクティベーションがあるかどうかを聞かれます。
このUV展開に特化したソフトは、高いだけあって凄まじいクオリティです。
というか人のモデルって、ひとつのアイランドにできるんだ・・・
しかし、1つのアイランドでは、どこがシームなのかがわかりにくいです。
そこで、もうひとつのSideFXLabのノードが登場します。
それが「Lab UV Visualize」です。これはUV可視化専用のノードです。UV可視化のための機能をいくつも持ち細かい需要に答えてくれる、いわば「UV Quick Shade」の上位版です。
では、Visualize Seemsのチェックボックスをオンにしてみます。
すごい!んだけど、そこ切る!?って感じです。
修正が必要ですね。※そもそもアイランドがひとつというのが無理がある。
Rizomuv_unwrapノードに戻り、Advancedを開いてStretch Controlを有効にしたり、Bruchを有効にしたり、様々なパラメータで試行錯誤を行います。
良い感じにシームが切れたとしても、アイランド内のUVの偏りが生じることがあります。
そういった場合は、Rizomuv_optimeseを行うことで、UVあたりの面積を均一化させることができます。Rizomuv_optimeseは必要に応じてiterationを上げて調整します。
※時間がないので、今後追記予定
#Bake Texture
UV展開できたので、UVテクスチャ用のべイクを出力します。
基本的にはカメラを置いて、ROPネットワークのbakeROPを作成して Cd 要素を出力していきます。
※後日追記予定
#UVに関する参考リンク:サイトや動画など
Houdini初級編:UV & Texture
Introduction to Houdini 16: Simple Procedural UVs
Setting Up a Character UV Map for a Character in Houdini 16
Houdini UDIMワークフロー
Houdini sidefx official Lesson8 UVs and Materials
Houdini sidefx official Lesson8 UVs and Materials
#Bone
SOPに慣れ切った体のユーザにとってHoudiniのボーンは、なかなか手を出し辛い分野かと思います。
しかし、Houdiniの群衆はバージョンを追うごとに良い感じになっているし、ちょっと気にはなるんだよね・・・。という方もいるのではないでしょうか。
時間が無い場合は、どうしても新しい分野を開拓するのは難しくなります。しかし、いつまでもmixamoに逃げてしまうと、進歩することができません。よって今回はボーンについて正面から学んでいきます。
##ボーンチェーン
まずは、Boneの種類について確認します。Tabでboneと入力するとBoneとBones、Bones fromCurveなどあります。
BoneとBonesの違いは、その名の通り1つだけ作るか、連続してボーンを作るかの違いです。
まずはビューポート上でbonesを呼び出してみてください。
続けてクリックすることで、ボーンチェーンにボーンが追加されます。
必要分のボーンを追加したらEnterを押すか、右クリック→Finish Drawingで確定させます。
ボーンチェーンって何?という方はネットワークビューを見てみてください。名前の通りボーンがチェーン状態になっています!このひとかたまりをボーンチェーンと呼びます。
各ボーンチェーンは、チェーンのルートとボーンでできています。
ここで、初めてHoudiniでボーンを扱う人はギョッとなるかと思います。
Houdiniは、ジオメトリレベルではなく、オブジェクトレベルでボーンを扱います。
###補足
※ルートはただのnullノードです
※まず最初に1つのボーンだけ作成して、後からCtrl+左クリックでボーン分割も可能です。
※マウスホイールを回転させるとボーンのdivisionを変更できます。
##ジョイントベースでなくボーンベース
そして、Houdiniのボーンを学ぼうとする際にさらに混乱するのが、ジョイントの概念です。
他の3Dソフトでは、スケルトンの焦点を「ジョイント」とする**「ジョイントベース」ですが、Houdiniは「ジョイントベース」ではなく「ボーンベース」**です。
・参考リンク
ボーン vs ジョイント
リグの役立つ情報とガイドライン
###比較して理解するボーンベース
MAYAや3ds Maxなど、ほとんどの3Dソフトのボーンは、ジョイントベースです。しかしHoudiniはジョイントを基本としません。※疑似的に作ることは可能ですが非常にコストがかかります
いやいや、ジョイント無しでどうやってスケルトンの設定するの???と、最初から初学者の精神を折りに来てくれます。
ジョイントベースは、ボーンの制御をボーン自身ではなくジョイントが制御します。対して、ボーンベースはボーン自身が制御情報を持ちます。
ジョイント(下図では右側のnullノード)が持つ情報は、各ボーンの支点となる座標です。そのジョイントからボーンは次の子ボーンへの方向にLookAtして、nullノード間の距離まで進みます。
距離の算出方法は、
vlength(vtorigin("../null0","../null1"))
です。
※この例は、あくまでHoudini上でジョイントベースを再現した場合です。各ソフトによってジョイントの処理は異なります。
対して、ボーンノードは各ボーンが保持する「方向」と「長さ」の情報をそのまま使います。親ノードを基準として、そのノードが持つ方向と長さの終端を子のボーンの開始点として利用します。なかなか、独特ですね。
というか独特過ぎるよ!!
最初はそう思いましたが、比較してみると、確かに左のほうがシンプルに見えます。そしてHoudiniの設計思想上、以下の点を重視した結果、ボーンベースの方がジョイントベースよりも都合がよいと判断されたのではないでしょうか。
以下引用 ボーン vs ジョイント
ジョイントベースシステムには柔軟性とジョイントを自由に動かせられるコントロールがあります。しかし、不適切なジョイントオリエンテーションは、しばしば予期しない問題を起こし、後処理が必要になってきます。
一方で、ボーンには方向があります。ボーンが向かっている方向が-Z軸で、高さがある方向がY軸、平坦な横方向がX軸です。ボーン階層はボーンチェーン全体を解釈することができます。つまり、ボーンと一緒にリグを伸縮することが容易になります。
###補足 Invisible paramters
ジョイントベースの再現時の例ではLookAtにCHOPを使用しました。
が、一応CHOPを使わない方法もあります。
ひとつは、ほかのジョイントベースのソフトでFBX出力を行った後に、Houdiniにインポートすると、CHOPなしのジョイントベースが生成されます。
対して1からCHOPなしのジョイントベースを作るためには、少し工夫が必要です。なぜなら、普通に呼び出したboneノードは、「Look At」「Look At Up Vector」が無いからです。
※補足:Houdini16でのコンストレイントのCHOP移行により無くなりました。
右上のギアマークからEdit Paramter Interfaceでパラメータを見ても、対象の項目がありません。
なぜ無いかというと、項目が隠れているからです。
Show invisible paramtersを押すと、普段隠れているパラメータが姿を現します。
隠れているパラメータをクリックします。ここからvisible状態に持っていくためにはinvisibleのチェックを外す必要があります。そして確定すると、隠れていたパラメータを出現させることができます。
宝探しかよ!?
invisible状態のパラメータは、SideFXが余分だと判断したり、下位互換のために残したパラメータ、推奨しないパラメータなどです。理由は様々ですが、積極的に使うか?というと、少々疑問の残るところです。
豆知識として覚えておく程度でよいかと思います。
そして、隠れたパラメータはInvisible parameterだけではありません。
##Pre-Transform
Pre-Transformもまた、隠れたパラメータです。直訳すると「事前のトランスフォーム」ですが、その名の通り、Transformをする前にTransformします。
同じ行為するのに、事前にする意味あるの!?そもそもどこで使われているの!!??
⇒ ボーンチェーンで使われています。
※注意:boneノードだけでなくほかのnullノード、transformなどにも利用されます。
もちろんボーンチェーン以外にも活用されています。
###boneとbonesの違い
まず、boneとbonesの2つを作成します。この2つのボーンの違いはどこにあるでしょうか?
まず単体のボーンと、ボーンチェーン(nullノード:ルート)の存在があります。
なぜルートが必要かというと、ボーンチェーンを構成するためには「方向」「長さ」のほかに「ノードツリーの従属関係:親から継承されたTranslateの座標」が必要だからです。
###従属関係
ノードツリーの従属関係がある子供の原点は親の座標に追従します。例えば親のTranslateの位置が(2,2,0)だった場合、子供の原点は親の(2,2,0)となります。
※子のKeep Position When Parentingオプションによって挙動は異なります
従属関係がある状態で子供のボーンが自身のTranslateを使用してしまうと、親と子の接点が途切れてしまいます。
例:子のボーンがY方向にTranslateを使用してしまった場合
つまり、ボーンで従属関係のある状態でTranslateは絶対にしてはなりません。
※以上の理由から、しばしばTranslateの値はLockされています。
そして、トランスフォームが許されるのは、最上位の親。つまりルートのみです。
なるほど!ではルートのトランスフォームの値を見てみましょう。
あれ?
Translateが(0,0,0)なのに、なぜかビューポート上では(0.6,0,0)に点があるように見えます。
ノードのどのタブを見ても0.6という値はありません。
なぜかというと、この0.6という値はPre-Transformに格納されているからです。
このPre-transformを見る方法は2種類あります。まずはノードの中クリックを押して見る方法です。下図の中にPre-transformという項目がありますが、このトランスフォーム値を事前に適用した状態が(0,0,0)となります。
もう一つは、タブから「Extract Pre-Transform」を選択することで、現在のPre-TransformパラメータをTransformパラメータに移すことで値を見る方法です。この方法は、値を編集することもできます。
編集が完了し、もう一度Pre-transformに格納したい場合は、Clean Transformを選択して、Transformのtranslate、rotate値をすべて0、scaleを1にします。
従属関係やPre-transformについての詳しいステータスは、インディゾーンHoudini情報日本語ブログに記載されています。
ルートのnullノードと同じように、boneノードもPre-transformがRotateに仕込まれています。
###0が欲しい!
なぜ、このような回りくどい方法をとってtransformの値を0にするかというと、後からアニメーションを付けやすくするためです。例えば、体のTポーズに戻したい場合、いちいち腕のrotateを90度など入れるとなると、初期化の手続きが面倒になります。基本の位置、基本の回転は原則として(0,0,0)にする必要があります。
##IK
他のDCCツールを使ったことのある経験者であれば、次に
「なるほど。じゃあIK(インバースキネマティクス)はどうするの?」と思うでしょう。
ボーンのキネマティクス選択は、boneノードを呼び出した後メニュー上に現れます。
HoudiniのBoneは、デフォルトではNo Kinematicsとなっているため、キネマティクスがありません。
では、2つめのInverse Kinematicsを選択して、先ほどと同じようにボーンを追加してみます。
すると、謎のnullノードとCHOPノードが現れます!!なんとHoudiniのキネマティクス設定はCHOPで処理されます!!
###チェーンゴールとCHOPノード
チェーンゴールは、ただのnullノードです。このチェーンゴールを移動させることで、ボーンはこのゴールに追従します。※例としてgoalのnullノードのTransformにsin($F*10)のアニメーションを付与しています。
この追従を制御しているのがCHOPネットワーク内のInverseKinノードです。
InverseKinノード内で、Root Bone・End Bone・Goal Affectorを指定します。
これを1文で表すと、「Rootのbone5からEndのbone8までに対して、Goalの影響を与える」ということになります。
それぞれの動きを見た方がイメージが湧きやすいかもしれません。
※後日追記
Kinematics | ボーン形状 | 生成されるノード | 説明 |
---|---|---|---|
No Kinematics | ソルバなし。元々のパラメータ値を使います。 | ||
Inverse Kinematics | IKは・・・ | ||
IK With Twist Affector | Twist Affector で・・・ | ||
Forward Kinematics | FKは・・・ | ||
IK With Constraints | コンストレイント付きIKでは、拘束パラメータによってボーンの角度制限が考慮されます(例:X角度範囲、Y角度範囲、Z角度範囲など)。そのほかは通常のIKと同じです。 | ||
FK With Constraints | ボーンの角度制限が考慮されます。そのほかは通常のFKと同じです。 | ||
Follow Curve | カーブにボーンが追従します。 |
##命名規則
ボーン作成時に、prefixの単語を指定することが可能です。
デフォルトは「chain」となっているので、今後作成されるボーンの名前は、chain_bone1、chain_bone2…となります。
※後日追記
・・・・
ここで時間切れとなってしまいました。
もうしばらくお待ちください・