2017年12月4日月曜日

好きな方向にグラデーションを。

この記事はHoudiniアドベントカレンダー用の記事です。
https://qiita.com/advent-calendar/2017/houdini

ついこの間、同僚にやり方を聞かれたのでアドベントカレンダーの記事にちょうど良いと思い記事にしてみました。

ある方向にグラデーションを作るというのは、静止オブジェクトやX,Y,Zどれか決まった軸ならば簡単ですが、同僚に質問されたシチュエーションは以下の様な感じでした。

マッチムーブされた自転しながら動き回るオブジェクトの進行方向に対して
0-1.0の値のグラデーションを作りたいという事でした。(火の量をコントロールするため。)
大体この様な場合は、エミットに前もってグラデーションを与え、マッチムーブされたオブジェクトの中心点にcopy to pointsで終わりなんですが、彼の場合は複雑な形状かつ直接そのキャッシュされたジオメトリに既にアレコレ編集を加えたあとで後戻りしたくないという事でした。

この様な結果を得たいという事でした。常に全体の指向方向の前が白、後ろが黒い状態です。

前置きが長くなりましたが、簡単に言うと内積を使えば終了です。
内積の細かい説明は省きますが、2つのベクトルa→(正規化)、 b→を内積した場合b→のa→の向きの長さを返します。

共に正規化されているベクトルの場合は分かりやすく、同じ方向を向いていたら1、反対方向を向いていたら−1を返します。
コレを利用してカメラの向きとオブジェクトの法線を内積をとる事で
カメラから見えないポリゴン削除や、トゥーンシェーディングや輪郭線抽出、リライティングツールなども簡単にできます。

少し話がそれましたが、分かりやすい例で説明します。
赤い矢印の方向にグラデーションが出来るように設定してみました。


ネットワークはこんな感じです。
左がメインです。arrowノードは赤い矢印が向いている'direction'という正規化されたアトリビュートを持っています。

このTipsは向けたいの向き'direction'のベクトルとどのようなベクトルと内積とるかとという点がポイントです。

まずはオブジェクトの中心座標をとります。その中心座標を各ポイントのポジション(@P)から引くことで、各ポイントのローカルポジション
(つまり各ポイントがそのオブジェクトのどの辺りにあるかという事が分かります。)
その値'N'と矢印の方向'dir'を内積 'dot(N,dir) 'を取ることで、各ポイントの矢印方向の成分が取り出せます(@dot)。


N(@P-center)は正規化されたベクトルではなく(今回ぬいぐるみジオメトリを使用しているので形も大きさも不明です)
これではグラデーション0-1.0の値を作るには不都合なのでattribute promoteで全体の最大値(dotmax)・最小値(dotmin)を作ります。



あとは作成したdotアトリビュートを最大値・最小値でfitすれば完成です。
値をカラー(@Cd)に割り当てました。

この手法で向けたい方向と内積をとれば、どんな複雑な形状であろうと
UVが無かろうと自転しながら移動するオブジェクトであろうと好きな方向にグラデーションが作れます。
一番上の例では、全体の中心点のvを作り(@P-center)と内積をとりました。

以上です。










0 件のコメント :