Houdini:CopytoPointでのMeshの配置をMayaで再現してVRayでレンダリングしてみる


概要

HoudiniでCopy to PointでのMeshの配置を、MayaのBifrostGraphで再現してVRayでのレンダリングまでをやってみました。

動機

いま仕事で行ってる会社ではHoudiniからnCacheを出すツールがあり、それにAttributeを持たせてnParticleとして使用してます。で、そのnParticleにInstancerを適用してMeshをばらまいています。

しかし動作がやたら不安定なため使い所がむずかしく、他に方法ないのかなーと探してたとき、こちらのTutorialでHoudiniのデータをBifrostGraphを使ってArnoldでレンダリングできることを知りました。

Houdini data imported into Bifrost, and then used Maya Arnold rendering
(HoudiniからAlembicで書き出したpointやcurve、またparticleに配置した豚さんをMayaのArnoldでレンダリングするという内容)

会社で使用してるのは主にVRayなので、VRayでもレンダリング可能ならnParticleの代替になりそうです。

BifrostGraph(Bifrost)ってなに?

Mayaの割と最近のversionから付いたノードベースのVisiual Programing環境。以前は流体エフェクトのみの拡張機能で単にBifrostという名前だった。

どちらかというとそのイメージのほうがいまだに強く、BifrostGraphを業務でバリバリ使っているという人はあまり聞かない。自分自身、業務でもテストでも使ったことはほぼないです。

検証環境

  • Maya 2020.4
  • Bifrost 2.2.01(古いverだと中身が違いすぎてダメそう)
  • VRay 5 PLE
  • Houdini indie 18.5.408

注意事項

  • BifrostGraphを使う上で以下の懸念点があります
    • 現状、全体的に開発途中感が半端ない
    • 今回pointの読み込みで使うfile_cacheノードは、将来変更される可能性がある実験的なノードと公式が言っている

手順

Houdiniでの作業

ネットワークの全体図



このようなHoudiniのシーンをMayaに持っていくことにします。回転はNとupで制御しています。

toBifrostGraph内のノードの説明


Mayaに持っていくために処理しているのは、青で囲ったtoBifrostGraph内のノードたちです。
主にここの説明をしていきます。

N_up_toOrient(Wrangle):NとupをQuaternionに変換

BifrostGraphでの回転にはQuaternionを使うため、今回のように
回転をNとupで制御している場合は、Quaternionにする変換する必要があります。

ネットワーク右側のN_up_toOrient(Wrangle)に変換用のコードを書きます。

matrix3 m = maketransform(@N,@up); 
@orient = quaternion(m);

コードはこちらを参考に、というかそのまま使わせていただきました。
cgwiki : Convert N and Up to Orient with maketransform

variant_round(Wrangle):intのvariantを最も近い値のfloatにする

copy to pointのinstance Idとして使っているvariantを、最も近い値のfloat値を持つpoint_instance_idというfloat型Attributeにしています。

f@point_instance_id = rint(@variant);

なんでfloatに変換するのか
BifrostGraphでInstanceのIdとして使わるのはlong型というあまり聞き慣れないものでした。
その正体はint-64bitとのことで、Houdiniでint-64bit型を出してみたんですがそれでも読み込んでくれませんでした。というかそもそも普通のintを読んでくれない。

そのためHoudiniからintを書き出すときは、同じ値のfloat型のAttributeを用意して書き出しています。
この仕様は将来のBifrostGraphのアップデートで変わる可能性があります。というか変わってくれ~。

point_instance_idという名称にしてる理由は?
point_instance_idはBifrostGraphにおけるInstance Idのデフォルトプロパティ名。ただしfloat型にしてるため互換性はないです。
ここでpoint_instance_idとしてるのは、BifrostGraphで使うAttributeですよ、とわかりやすくしておくため。

Attribute Rename:BifrostGraphで使う名前に変更


Attribute名をBifrostGraphがデフォルトで使う名称に変更しています。
これによりBifrostGraphでAttribute名を変えなくてもそのまま使えるようにしています。

変更するAttributeは以下の2つ

  • pscale -> point_size
  • orient -> point_orientation

Attribute Delete:不要なAttributeを削除


variant, N ,upなど、BifrostGraphでは使わない不要なAttributeを削除しておきます。
最後に、ROP AlembicでAlembic形式を書き出したら、Houdiniでの作業は終了です。

Mayaでの作業

Bifrost Graphを開く
Window → Bifrost Graph Editor → Create Graph

ノードを繋ぐ
set_instance_geometryノードがほぼcopy to pointのようなものなので、基本はそこにAlembicのmeshとpointを繋いでいくだけです。ポイントは、

  • HoudiniでいうAttributeはBifrostGraphだとPropertyと呼ばれていること
    • そのためここからAttributeのことをPropertyと記述します
  • point_instance_idをto_longでlong型に変換すること
  • bake_instanced_geometryでVRayなどでもレンダリング可能にしてること

ここからは各部分の説明です

file_cache:Alembicのpointを読み込む


まずAlembicのpointを読み込むのはfile_cacheノードになります。
BifrostGraphには他にread_Alembicというまさしくそれなノードがあるのですが、なぜかそちらで読み込むとAttribute(Property)が来なかったため、今回はfile_cacheノードを使用しています。

ただし、file_cacheノードは将来変更される可能性がある実験的なノードと公式に書かれているため、業務で使う場合は注意が必要です。

知っておくと便利な小技
いまどんなPropertyを持っているか確認したいとき

  • ノードを繋ぐラインを右クリック → Add Watchpoint

get_geo_propertyとto_long:float型のpoint_instance_idをlong型に変換

pointを読み込んだら、そのpointにget_geo_propertyノードを繋いで、point_instance_idと入力しPropertyを取り出します。その後出力のdataからto_longノードを繋いでlong型に変換します。

ここで注意しなければいけないのは、Propertyの型を指定しないとエラーになることです。

指定の仕方
typeという入力を右クリック → Value Types → Propertyの型(この場合float)

set_instance_geometry:pointとmeshを接続してinstance化

pointにmeshを配置してます。手順は以下の通り。

  • set_instance_geomeryノードにpointとmeshを繋ぎます。
    • meshはAttributeいらないのでread_Alembicで読み込んでいます
  • 入力にあるSelectionをクリックして開き、instance_id_valueに先程long型に変換したpoint_instance_idを繋ぎます
  • パラメータでOverwrite Instance Idにチェックを入れます。
    • これはpointが持っているInstance Id Propertyではなく、instance_id_valuesに繋いだ値を使うという設定です。


Instanceができたら、それをbake_instanced_geomertyに繋いで最後にOutputに繋げばノードの作業は終了です。

なんか黒豚になってるけど気にしないことにします。

BifrotsMeshをMayaのMeshに変換する

BifrostGraphでの作業は終わりましたが、この状態ではまだレンダリングできません。
標準のNode Editorを使ってMayaのメッシュに変換する必要があります。

polySurfaceShapeはtabキーを押してmeshと入力したら出てくるやつを使えばいいと思います。

これで普通にレンダリングできるようになりました。

Historyを消去しなければ、BifrostGraphの変更は反映されます。

MaterialがMeshごとに適用できない大問題発覚

さっき”普通にレンダリングできるようになりました”と言ってしまいましたが、すみませんウソです。
察しの良い方ならお分かりの通り、これだと複数のMeshを結合して1つのMeshになっているため、このままではMaterialが個別に適用できません。
ArnoldであればBifrostGraph上でMaterialをアサインできるようですが、VRayだといまのところムリそうでした。

現状の解決策:BifrostGraphをInstanceのMeshの数だけ作る

ということで考えた苦肉の策がこちらです。

BifrostGraphを2つ作ってMeshも2つ用意します。

同時に表示したら解決!わーい!

1つのBifrostGraphに1つのMaterialしか適用できないなら、BifrostGraphを2つ作ればいいじゃない。
さんざんノードベースでやってきて、最後にこれかよというがっかり感はあるけれど、調べた限りでは他の解決方法は見つからなかったです。「もっと良い方法があるよ」という方がいらっしゃれば、私めに思し召しください。

一応コツとかある
こんな脳筋手法でも気をつけないといけない点はあります。
それは、set_instance_geometryから外したmeshの場所にconstruct_pointsを繋げること

pigのBifrostGraphではtoyを読み込んでいたread_Alembicの代わりにconstruct_pointsにしています。
こうすることで、instance Idを無視して全pointに配置されるのを防いでいます。

toyのBifrostGraphはpigのread_Alembicが繋がっていた0番目にconstruct_pointsを繋げています。
これで狙ったpointのidにmeshを配置することができます。

construct_pointsノードとは
公式によると、「なにもPropertyを持っていない最小のpointsを作成する」とのことです。
なので一番処理が軽そうでmeshの代わりになるものということで選びました。
Mayaヘルプ : construct_points

最終結果

感想

Maya標準の機能でHoudiniのpointがAttribute付きで持ってこられるのはうれしい。
あとはVRayなど他レンダラーとの親和性が高まっていけば、HoudiniとMayaの連携はかなり楽になりそう。

ただBifrostGraphはUI含めて開発中感が半端ないので、業務で使うのはまだ早い気がする。
後になってシーンの再現ができないとかはすごくでてきそう。

結論:VRay for Houdiniに期待したい