XPressoで多数のデフォーマを一元管理

この記事では、ちょっと手の込んだXPressoの例を紹介してみようと思います。
木のモデルの10本ある枝をデフォーマでグニャグニャと動かしていますが、10個のデフォーマはXPressoで一元管理し、作業の効率化を図っています。

サンプルファイルはこちら:201709_xp_multi_deformer

完成したXPressoは以下のような構成になっています。これらの要素についてひとつずつ説明していきますが、XPressoやユーザデータの基本操作などについては説明しきれないので、そのへんまだご存じでない方は各自ヘルプ等で調べてみてください。


屈曲デフォーマで動かしてみる

まず10本ある枝のうちの1本に「屈曲デフォーマ」を設定して動かしてみます。

オフの状態。

オンの状態。曲がっていますね。

この木は全体が1つのオブジェクトなので、デフォーマの効果が1本の枝のみに限定されるよう「減衰」(黄色い枠)を「ボックス」に設定し、領域を枝に合わせてあります。
デフォーマで曲がる角度は「強度」で設定します。この例では「30°」曲がっていることになりますが、モードが「無制限」になっているため、デフォーマの「サイズ」(紫色の枠)からはみ出ている枝先の部分もそのまま同じ曲率で曲がっています。このへんの加減は実際の結果を見てみないと決められないので、ある程度試行錯誤しています。

この「屈曲デフォーマ」にグニャグニャ曲がるアニメーションをつけるため、デフォーマの「強度」の値を変化させます。また、すぐ下の「角度」の値では、基本の「屈曲」に対して横方向に「ねじれ」を加えることができます。この2つの値に「なんとなくいい感じ」でキーを打ってみます。

アニメーションさせるとこうなります。そこそこいい感じにグニャグニャ動いていますね。

これを枝の数だけ(あと9回)繰り返せばアニメーションの完成です!

……いやそれはダメです。

現実的には、

(1)アニメーションのトラック/キーフレームはなるべく少なくしたい
(2)枝ごとの個体差をつけたいが手動でやるのは避けたい
(3)全体的な動きの速さ/大きさはまとめて操作したい

といった要求があります。要は省力化ですね。というか、同じようなものが10個あるのに10個それぞれ手作業で管理していたのではコンピュータに計算させてる甲斐がないのではないでしょうか。

自動化だ自動化!

キーフレームなしで揺らす

まず、「屈曲デフォーマ」に手作業でキーを打って作っていた「揺らぎ」のアニメーションをXPressoで自動化してみます。

XPressoには「ノイズ」というノードがあり、これを使って不規則かつ連続的に変化する値を得ることができます。いわゆる「乱数」は計算するごとにバラバラの値を返してきますが、「ノイズ関数」の出す値は連続性があるので「不規則に移り変わる値」としてアニメーションで便利に使うことができます。MoGraphのランダムエフェクタなんかでもお馴染みですね。

「ノイズ」のパラメータのうち、「周波数」が値の変化するスピードで、値を大きくすると変化が速くなります。「振幅」は出力される値のマルチプライヤで、基本となる「-1から1まで」の幅に乗算されます。たとえばこれを「2」に変更すると、出力される値の範囲は「-2から2まで」になります。

では、XPressoタグを作成し(とりあえずデフォーマ自体につけておきます)、1つずつノードをつなげていきましょう。

まず「屈曲」の「強度」に、基本の曲がり具合となる「30°」を入力します。これには「一般」グループの「定数」ノードを使います。モードは「実数」、値は「30」とします。

結果がこちら。

なんかメッチャ曲がってる! (知ってた)

XPressoのノードで「角度」が扱われる場合、単位は「度」ではなく「ラジアン」です。つまり上記の状態では「屈曲」の強度は「30ラジアン」=「1718°」が入力されてメッチャ曲がっているのです。

「30°」が何ラジアンなのか直感的にわかる人は「定数」ノードの値をラジアンで入力し直してもいいのですが、「計算」グループにある「角度の変換」ノードを使えばXPresso内部で「度」と「ラジアン」を変換できるので、「定数」には感覚的に扱いやすい「度」で角度を入力できます。

定数「30」の単位が「度」から「ラジアン」に変換されて値が「0.524」になっています。「一般」グループにある「結果」ノードを使うと、それぞれのノードから出力されている値を見ることができ、変換の前後の値が確認できます。

属性マネージャでは「屈曲」の「強度」に入力された値が「30°」と表示されています。属性マネージャの角度の表示は常に「度」になります。また、パラメータの頭にはXPressoから入力されていることを示す三角マークが出ています。

今度は想定通りに曲がっています。

基本の強度「30°」が入力できたので、次は「ノイズ」を加えて揺らぎを出します。

「ノイズ」ノードは「一般」グループにあります。この例では「計算」グループの「数式」ノードに入力ポートを2つ開け、先ほど設定した基本の値と「ノイズ」の値を「$1+$2」で足し算しています。なお、「ノイズ」から出力される値は単位を変換していないので「ラジアン」として扱われます。「ノイズ」の出す値はデフォルトでは「-1から1」の範囲で、「度」に変換するとすごく小さい値になってかえって面倒になるため、そのままにしておきました。

足し算だけなら「計算」ノードでもいいのですが、ここでは「数式」ノードを使っています。この例では2つの入力の足し算しか使っていませんが、「数式」ノードでは入力する変数を任意に増やしたり、加減乗除以外にもたくさんの式や関数(ヘルプに一覧があります)が使えるので、単独のノードでもいろいろと融通が利きます。まあ今回は結局、最後まで足し算しか使わなかったのですが。

アニメーションさせてみます。

揺らぎのスピードはちょうどいいですが(偶然)、揺れ幅が少し大きいようです。「ノイズ」の「振幅」を半分の「0.5」に下げてみます。

揺れ幅が小さくなりました。こんなもんでいいでしょう。

続いて、揺れの「ねじれ」となる「角度」のほうにも「ノイズ」を入力します。「強度」と「角度」で同じ「ノイズ」を使うと両者がシンクロして単に揺れる向きが傾くだけになってしまうので(実際やってみてそうなりました)、設定を変えた「ノイズ」を別に用意します。

「角度」につなげるほうは「周波数」を「0.7」にしました。これで2つの「揺らぎ」は時間的にずれます。

アニメーションで確認します。

少々「ねじれ」を含んだランダムな揺れが作れていますね。

これでとりあえず、枝1本分の「揺らぎ」を自動化し、「キーフレームなし」のアニメーションができました。「なんとなくいい感じに揺れる」ぐらいの動きであれば、手作業でやる必要はないのです。自動化!

多数のデフォーマの一元管理

続いて、10本の枝すべてに「屈曲デフォーマ」を配置します。

枝は上に行くに従って短くなっているので、デフォーマもそれに合わせます。「強度」と「角度」はXPressoから管理するので変更しません。枝の曲がるアールを小さくするには、デフォーマの「強度」を上げるのではなく「サイズ」を小さくすることで対応できます。

デフォーマは10個になりました。XPressoタグはポリゴンオブジェクトのほうに移しておきます。この例でのXPressoタグはどのオブジェクトについていても動作には影響ありませんが、一見して「何をやっているのか」わかりやすいところにつけておくほうがいいですね。

ではデフォーマの数だけ「オブジェクト」ノードを複製し、参照先をそれぞれの「屈曲」に割り当て、同様に「強度」と「角度」に接続します。

ん? 省力化するのが目的なのに同じノード10個並べるのっておかしくね?

いや、僕もわりと最近までこれやってたんですけど、もっと便利な方法があります。「くり返し」グループの「オブジェクトリスト」ノードです。

「オブジェクトリスト」は多数のオブジェクトをリストに登録して、それを全部まとめて(というか順次1回ずつ)出力するノードです。

まず先ほど作った一連のノードの出口、「屈曲」を参照している「オブジェクト」ノードに「オブジェクト」入力ポートを開けて、そこに「オブジェクトリスト」の「オブジェクト」出力をつなげます。

「オブジェクトリスト」には10個の「屈曲」をすべて登録します。

すると、先の10個の「屈曲」を10個の「オブジェクト」ノードで接続した場合と同じ結果になります。「オブジェクトリスト」に登録されている全てのオブジェクトに対して「くり返し」同じ処理が実行された、ということですね。この「くり返し」、英語で言うと「Iterate」はプログラミングでは当たり前の概念だそうなのですが、プログラム素人にはなかなか飲み込みにくく、僕もその有り難みがわかるまで随分かかってしまいました。

なお属性マネージャでは、XPressoで「オブジェクト」ノードが参照している「屈曲」1つだけにしか入力マークが出ませんが、実際にはリストの全てのオブジェクトに同じ値が入力されています(属性マネージャからは値を変更できない状態になっています)。

アニメーションさせてみると、すべての「屈曲」が自動で動いています。

さて、同じ値を入力しているので当然なのですが、10本の枝はすべてシンクロして同じように動いています。これはちょっと使い物になりませんね。個体差をつけたいところです。

「ノイズ」の出す値のパターンは「シード」の値によって変化します。いわゆる「ランダムシード」です。

つまり、それぞれの「屈曲」に対して入力される「ノイズ」の「シード」の値が異なっていれば、「周波数」や「振幅」の値が同じであっても10本の枝は異なった動きをすることになります。

……てことはやっぱり、「シード」の異なる「ノイズ」ノードを「屈曲」の数だけ用意しなくてはならないのか……? いや、大丈夫です。「オブジェクトインデックス」ノードというものがあります。

「一般」グループの「オブジェクトインデックス」ノードは、「オブジェクトリスト」に登録されているオブジェクトの「通し番号」(0から始まる整数)を取得するノードです。

上図のように接続すると、リストの「屈曲」の「通し番号」を「ノイズ」の「シード」に入力してくれます。「通し番号」はユニークな整数なので、すべての「屈曲」がユニークなランダムシードを割り当てられた「ノイズ」の値を受け取ることになります。

結果としてXPressoから10個の「屈曲」に入力されている値はいずれも異なるものになっています。

アニメーションでも、10本の枝はバラバラに揺れているのがわかります。

これで、10本の枝に自動で揺らぎのアニメーションをつけることができました。揺らぎの大きさ、速さはXPressoから一元管理でき、それでいて揺らぎのパターンは枝それぞれが異なっています。自動化!

独自インターフェイスからアニメーション設定

XPressoの利点として「自動化」のほかにも、「ユーザ独自のインターフェイス」の作成というものがあります。大規模なシーンになると、目的のオブジェクト、目的のパラメータをピックアップするのも大変になってきますが、XPressoで専用のインターフェイスを作成すれば効率化できます。

まず、先ほどはXPresso内部の「ノイズ」ノード内で入力していたパラメータを、独自のユーザインターフェイスに引っ張り出しましょう。

XPressoタグは親のヌル(名前は「X-tree_4」)に移します。

その親ヌルに「ユーザデータ」を作成します。「屈曲デフォーマ」の基本の曲がり方を決める「屈曲_基本角度」と、ランダムな揺らぎの量を決める「屈曲_ノイズ量」の2つのユーザデータを作りました。

いずれもデータタイプは「浮動小数」、「インタフェース」は「ボックスとスライダ」ですが、「単位」と「ステップ」、「最大・最小」は目的に合わせて変えてあります。

親ヌル「X_tree_4」をXPressoに入れ(「オブジェクト」ノードで参照)、いま作った2つの「ユーザデータ」の出力ポートを開けます。

「屈曲_基本角度」は、「定数(30)」~「角度の変換」と入れ替わりに「数式」の「V1」に接続します。この値はユーザデータ側で単位を「度」にしてありますが、「角度の変換」を挟まなくてもXPresso内ではラジアンに変換されて扱われます。「定数」と「角度の変換」はもう不要なので削除します。

「屈曲_ノイズ量」のほうは、2つの「ノイズ」ノードの「振幅」の入力ポートを開けて接続します。XPresso全体は以下のようになります。先ほどは「定数」ノードと「ノイズ」ノードにパラメータとして入力していた2つの値が、親ヌルの「ユーザデータ」からの入力に差し替わったことになります。

「ユーザデータ」の2つの項目に先ほどと同じ値を入力すれば、枝がグニャグニャするアニメーションも同じ結果になります。この2つの値で枝の動き方を変えることができ、値にキーを打てば枝のグニャグニャ具合が時間とともに変わるアニメーションになります。

細かく揺れる~上向きに曲がる~揺れが止まる~まっすぐに戻る、という一連の変化をつけてアニメーションさせてみました。

前述の通り、アニメーションさせているトラックは2つのユーザデータだけで、数値の変化も上がって下がるだけです。

仮にこれを、いちばんはじめの「屈曲デフォーマのパラメータに直接キーを打つ」という方法でやっていたとすると、トラックは20個になります。しかも「不規則に波打ちながら振幅が徐々に増減する」カーブを作らなくてはならず、さらに個体差をつけたり、後から全体の調整をするとなると、非常に面倒なことなります。

アニメーションを「自動化できる要素」と「手動で操作する要素」に分解し、前者はXPressoで自動化、キーフレームを打つのは後者のみとすることで、作業を大幅に効率化できるわけですね。

便利スイッチ

次に、「屈曲デフォーマ」を一括して操作するスイッチをつけてみます。アニメーションの結果には影響しませんが、シーン管理の手数を減らせる工夫です。

まず「ユーザデータ」で「有効」と「表示」という2つの「ブール値」スイッチを作ります。

「屈曲」の「オブジェクト」ノードに「オブジェクトの状態(=デフォーマのオンオフ)」の入力ポートを開け、ユーザデータの「有効」を接続します。これらは入力、出力とも「ブール」属性なので、そのままオンオフスイッチとして働きます。

ちなみに上図では、先ほどとは別の場所に「オブジェクト」ノードをもう1つ作成して同じ親ヌル「X_tree_4」を参照していますが、XPressoの中で同一のオブジェクトをダブって参照しても問題ありません(コンフリクトや循環参照を起こさないことには留意します)。

これでユーザデータの「有効」スイッチですべての「屈曲デフォーマ」を一括してオンオフできるようになりました。この例ではデフォーマは一カ所にまとまっているので手動でオンオフしてもたいした手間ではありませんが、深い階層のあちこちに散在しているような場合にはスイッチ1つでまとめてオンオフできるととても便利です。

もう1つのスイッチはデフォーマの「エディタでの表示」を切り替えるためのものですが、こちらは少し面倒なことになります。ユーザデータの「表示」を「屈曲」の「エディタでの表示」にそのままつなげてしまうと、期待したような結果になりません。

ユーザデータの「表示」スイッチがオンのときはデフォーマの「エディタでの表示」は「オフ(赤)」になり、「表示スイッチ」がオフのときは「エディタでの表示」は「オン(緑)」になってしまいます。

これは、「エディタでの表示」の属性が「0と1(FalseとTrue)」の「ブール」スイッチではなく、「0、1、2」の3つのステートを持つスイッチであるためです。3つのステートは「0=表示(緑)」、「1=非表示(赤)」、「2=親から継承(グレー)」となっているので、「ブール」を直結すると上記のような結果になります。ユーザデータのスイッチの使い勝手からすると、スイッチが「0=オフ」のときには「1=非表示」に、スイッチが「1=オン」のときには「2=親から継承」になってほしいところです。

真面目に考えればユーザデータを「ブール値」ではなく「整数」のスイッチにして「1か2」を出力するように変更するとか、XPressoで「条件分岐」ノードを使って「0ならば1、1ならば2を出力」と置き換えるところですが、もっと簡単な方法がありました(某A.氏のデータを見て知りました)。

「ブール」の出力に「1」を加算すればいいのです! すると「オフ=0」が「1=非表示」となり、「オン=1」が「2=親から継承」になります。

これでいつでもボタン1つでデフォーマを非表示にできます。ビューがすっきりしますね。

以上で、操作する必要のあるものはすべて「ユーザデータ」に引っ張り出せたので、あとは親ヌルをパタッと閉じてしまえます。アニメーション作業で必要な設定は親ヌルのユーザデータから一元管理できるので、中のデフォーマに触る必要はありません。

HUD化

ユーザデータは「HUD」としてビューに貼り付けることもできます。特に頻繁に触るもの、プレビュレンダリングに値を記録しておきたいものなどは、HUD化すると便利です。

オブジェクトの名前を書き換える

最後にもう1つ、実用的というよりはちょっと面白い使い方を紹介します。下図の「計算」ノードで「文字」を加算して「屈曲」の「名前」に入力している部分です。

「計算」ノードは計算の手法が「2つの値の加減乗除」に限られる代わりに、「実数」以外にも非常に多くのデータタイプを扱うことができます。「文字」もそのひとつで、「文字」を加算すると2つの文字列をくっつけて出力することができるのです。この際、数値も「文字」として扱えます。

「計算」ノードの1番目の入力には「定数」ノードを使い、モードを「文字」にして、デフォーマの基本的な名前として「屈曲_枝_」という文字列を入れておきます。

「計算」ノードの2番目の入力として「オブジェクトインデックス」の「番号」出力を接続、ノードの出力を「屈曲」の「名前」に入力します。すると、「オブジェクトリスト」にある「屈曲デフォーマ」の名前が「屈曲_枝_通し番号」という形に変更されます。

この例ではオブジェクトマネージャの並び順と一致していますが、通し番号は「オブジェクトリスト」ノードでの並び順になります。

単に末尾に自動で連番を振るだけなら「名称ツール」で「$N」を書き加えるのでもいいのですが、「オブジェクトインデックス」と一致した名前を持つことに利点がある場合もあります。この例では「屈曲」の末尾の番号は「ノイズ」に入力されている「シード」の値と一致しています。「シード」の値の場合はあまり意味がありませんが、たとえば「数式」で「オブジェクトインデックス」を変数として使っているような場合には、オブジェクトの名前に変数を表示できると便利なこともあるでしょう。もちろんXPressoの組み方次第で、それ以外の値を名前に表示させることもできます。