原文:https://www.sidefx.com/tutorials/flowmaps-houdini-for-games/
Houdiniの新しいフローマップツールを使用してフローマップを作成する方法を学びます。 地形のジオメトリ、カーブを使用してフローマップの速度を制御する方法と、より具体的な制御を望む場合は手動で組み合わせる方法がわかります。 その後、メッシュジオメトリをエクスポートし、フローマップをベイクして、Unreal Engineで川床を組み立てます。
シーンデータはSidefxの下記サイトからダウンロード可能です。
https://www.sidefx.com/tutorials/flowmaps-houdini-for-games/
上記リンクからファイルをダウンロードし、解凍します。
Finle>Import>Filmbox FBXを選択し、ダウンロードフォルダ内にあるRiver02.FBXをロードします。
川床のジオメトリがImportできます。
UniformScaleを0.01に設定します。
あたらしいGeoノードを作成し、名前をRevierSurfaceに変更します。
RiverSurfaceノード内のFileノードは削除します。
次にトップビューからカーブを作成します。Spaceキーと2を同時におすとTopViewに切り替わります。
Curveノードを作成し、スムースカーブにするためにPrimitive TypwをNURBSに設定します。
Show Handleマニピュレータを選択し、Point Snappingをオンにします。
ジオメトリ上にマウスのカーソルを置くと下にある川床ジオメトリのポイントが表示されスナップすることがわかります。
下記のような感じで少し曲がったカーブをジオメトリ上に作成します。
カーブが完成したらEnterキーで確定します。
Spaceキー+1でPerspビューに戻ります。
このカーブに沿ってSweepメッシュを作成するので、一度カーブを再サンプリングします。
Resampleノードを追加します。オプションはデフォルトのままで大丈夫です。ポイントが十分に追加され、完全にジオメトリに沿わせることが可能になります。
カーブを川床ジオメトリに潜っていると完全に投影することができません。
Transformノードを追加し、上に持ち上げます。
Transformの下にRayノードを追加します。
Rayノードは投影するノードとさらにその投影先のオブジェクトが必要です。
投影先を作るために、Object Mergeノードを作成し、川床ジオメトリを選択します。
Mergeした川床ジオメトリを表示すると、大本の大きさ(今の100倍)になるため、ObjectMergeのTransformをInto This Objectに変更します。
これで表示されている川床ジオメトリと同じサイズになったので、rayに接続します。
Rayオペレーターは、最初の入力ジオメトリの各点からのレイを法線方向に投影し、次にその点を2番目の入力からレイがヒットする任意のジオメトリに移動します。
カーブの一部がジオメトリから飛び出てしまい正しく投影されていません
これはカーブが投影されたカーブのノーマルが向いている方行にオフセットされてしまっているからです。
これはTransformノードを使用して修正可能です。
rayノードを表示したまま、1つ上のTransformノードを選択し、TransformXの数値をドラッグします。カーブが
カーブノードでポイントを調整し、カーブが良い感じにジオメトリに投影されるようになるまで調整します。
投影先のジオメトリ形状の岩同士が非常に密接している事とかその岩がアップダウンしていることで、カーブが少し複雑な形状になってしまいます。
Smoothを追加し、Strengthを5000にすることで滑らかな形状にすることができます。完全ではありませがこれで先に進めます。
水に深さを持たせるためにTransformノードを追加して、Yに0.5移動します。
このTransformノードの名前をWaterDepthにします。
Sweepのチュートリアルメッシュを見たことがある方はご存知だと思いますが、UVのちょっとしたトリックをご紹介し明日。後で使用するUVのために、カーブに対してUVを適用しています。
UV Textureノードを追加し、UVを追加します。
Texture TypeをRow&Columnsに設定し、Attribute ClassをPointに設定します。
更にOffsetをー1に設定委s、Angleを90にすると下記のようにUVが配置されます。
次に川幅を定義するLineノードを追加し、DirecionをXにします。
Lengthが川幅を定義するようになるので、このLineのOrigin X(カーブの開始点)が川幅のちょうど中心に来るように設定します
LengthをOrigin Xまでドラッグして、離すと下記のようなActionが表示されるのでRelative Channel Referenceを選択します。
これにより下記のようなエクスプレッションが入力され、Origin Xは常にLengthの値を参照することになります。
上記ではLengthの値が1になっているため、OriginXも1になります。
つまり開始点が川幅の半分かつマイナス値になるとちょうど中心が原点にくるようになります。
これでどんなに川幅変更しても常にカーブの中心が原点になります。
さらにLengthを10に設定します。
UVのための2つ目のトリックして、Lineノードの下にポイント番号を格納するためにAttribute Createを作成します。これは後でSweep作成時のUV Coordinateに使用します。
Value Xに$PTと入力し、Enterを押します。これでポイント番号が作成したアトリビュートに格納されます。
さらにResampeをクリックし、Maximum Segment Lengthをオフ、Maximum Segmentsをオン、Segmentsを50に設定します。
これでSweepの準備ができました。
Lineから作成したものをCloss Sectionに最初に作成したものをBackboneに設定します。
デフォルトだと下記のようにBackboneカーブにそってLineが複製されて配置されているような状態です。
そこでSweepノードのSkin OutputをSkin Unclosedにします。
これで下記のようにカーブに沿ったプレーンが作成されます。
次にオリジナルカーブに沿ってそれぞれのポイントで横幅を制御するためにRampを使用します。
Rampを割り当てるにはUVが必要です。そこで先ほど設定したアトリビュートを利用していきます。
Sweepの下にAttribute Wrangleを追加します。
そして、下記のように入力します。
このattribute1はLine作成時にCreateAttributeで作成したアトリビュートです。
この状態で、UV Viewを確認すると下記のようにグリッド上に展開されたUVとなります。
これで下準備ができました。
Game Development Toolsetのシェルフから、Create Flowmapアイコンを見つけてください。ない方は、Game Development Toolsetを更新する必要があります。
アイコンがあったら、ドラッグして作成します。
attributeWrangleとFlowmap作成ノードをつなげます。
次にCreate FlowmapのVisualize Flowをオンにすると下記のように現在の流れる方向が表示されます。
デフォルトはポイント上にまっすく上に向いています。これでは全く役に立ちません。
そこで、Guide Flowmapノードを追加します。
次にCurveノードを作成し、Show HandleとPointスナップを有効にして、作成したRiverSurfaceの真ん中をクリックしてカーブを描いていきます。これが川が進む方向になります。
そして、作成したCurveをGuide Flowmapに接続してください。
ビューを確認すると、Velocityが正しい方向を指していることを確認できます。
Guide_FlowmapのStrength(強さ)、Width(幅)、Falloff(エッジ周りの減衰)を調整しReiverSurface全体に欲しい方向を向いているように調整します。
過去にフローマップを操作していた場合、実際にはフローマップ上に表示されるような視覚化ツールには使用できませんでした。でもこのツールでは実際に実行可能でとてもシンプルです。
Flowmap to Colorノードを作成し、接続します。
これで頂点カラーとして使用した色を表示することができます。
Create Flowmapで有効にしていたVisualize Flowをオフにして確認します。
良い感じになってきましたが、このままでは川の中にある岩などの障害物が川の流れに影響していないことがわかります。
そこで、Flowmmap Guideの後ろにFlowmap Obstacleを追加します。
そして、もう一つのInputに川底オブジェクトを読み込んでいる、Object Mergeノードを接続します。
その後、下記のようにFlowmap Obstacleノードを更新します。
ビューポートで確認すると以下のような結果を得ることが可能です。
岩の周りに正しく迂回するような流れが生成できていません。
Flowmap Obstacleを右クリックし、Allow Editing of Contentsを選択し、HDAの中に入ります。
ここでObject MergeでInputしたデータをIsooffsetでFogに変換していることがわかります。
そこで精度をあげるために、VDBFromPolygonを作成し、isooffsetの代わりにScatterにVolumeを渡すようにします。
vdbfrlomPolygonのオプションをFOG VDBに変更します。
これで岩の周りに正しい流れが生成されます。
ポリゴン板の解像度をあげるためにSubdivideを追加します。
ここまでで正しい結果を得ることができるようになりましたが、場合によってはComb(櫛)でVelocityを調整したい場合もあるかもしれません。
そこで、Flowmap ObstacleとFlowmap to Colorの間にCombを追加します。
このノードはNormalをコーム(櫛でなでるように方向を変更)することができるので便利です。
CombオプションでOverrider Normalを有効にして、vに設定します。
これでVelocityに対してコームすることになります。
Show Handleツールを有効にすると、Combノードによるブラシツールが表示されます。
CombノードのBrushタブでRadius(半径)とOpacity(強さ)を調整します。
これで壁の周りのエッジに部分の流れや渦の状態などを素早くペイントで変更することができます。
次にこれをテクスチャにベイクしていく必要があります。
現在はPoint Attributeとなっているので、これをVertexアトリビュートにする必要があります。そのためにAttribute Promoteノードを使用します。このノードはあるジオメトリ・レベルから別のジオメトリ・レベルにアトリビュートを変換します。
Flowmap to Colorノードの下にAttribute Promoteノードを追加します。
オプションで、New ClassをVertexに設定し、Color(Cd)とTexture(uv)を指定します。
Bakerに情報を渡すために、Nullを追加します。
そして名前をOUT_Bakerに設定します。
ここからゲームエンジンに渡すデータを作成します。
Normalを追加し、Add Normal toはPointに設定します。
Attribute Deleteを追加し、Vertex AttributeでColor(Cd)を設定します。
Remeshを追加し、Target Edge Lengthを1に変更します。
更にPolyReduceを追加し、40%位までポリゴンを削減します。
Nullを追加し、これをゲームエンジンへ出力するメッシュとします。
FBXで出力してください
次にベイクを行います。
OUTコンテキストに移動し、GameDevelopmentToolシェルフからドラッグでGamesBakerを作成します。
GamesBakerのオプションを開きます。
解像度ですが、フローマップは通常、実際にはそれほど大きくする必要はありません。
Target MeshをOUT_BAKER
Resolutionを512
マップ名をflowmap
出力チャンネルをVertex Color
に設定し、Renderボタンをクリックします。
Bakeが終了すると下記のようなマップが生成されます。
UnrealEngineを起動し、Rever02.fbx、ゲーム用に出力したrivermesh、そしてFlowmapをImportします。
RiverMeshをロードする際にImport Uniform Scaleを100に設定します。
Rever02とRivermeshの位置合わせを行います。
コンテンツで右クリックし、新しいマテリアルを作成、マテリアルをRiverMaterialに変更します。
RiverMaterialをダブルクリックし、マテリアルブラウザを開いたら、ImportしたFlowmapをドラッグで読み込みます。
FlowMap Simpleノードを追加します。
FlowMap Simpleは赤と緑チャンネルのみ使用します。
ComponentMaskを追加し、RとGのみ有効にします。
次にFlowmapの値をオフセットします。現在は0から1の値なので、これを-1から-へとオフセットすると、左から右、上から下といった形に流すことが可能です。
Constant Bias Scaleを追加し、Scaleを2.0、Biasを-1.0にします。
その結果をFlowMap SimpleのFlow Vector Mapに接続します。
ダウンロードしたデータからT_Water_NをUnrealEngineにインポートし、Texture Objectノードを作成しそこにロードします。
これはノーマルマップをNormal Mapに接続します。
この結果をRiverMaterialのノーマルに接続します。
これでFlowMapをUnrealEngineで確認することができました。