火花などのライン化した擬似モーションブラーとレンダーのモーションブラーの共存

遥か昔に自分のブログ[Link](http://blog.livedoor.jp/fujitarium/archives/52302877.html#more)の中でカメラスペースモーションブラーについて書きましたが、その時はchf()でタイミングをずらしたカメラを複数作って用意したのに対し、今回はforEachを交え、もっとプロシージャルに尚且つサブサンプル可能にします。それ用のカメラもわざわざ用意しません。

サンプルファイルはこちらになります。
https://drive.google.com/file/d/0B8GmDmE-WRSTV2ZDaWx5Y1NzSHc/view?usp=sharing

#NDCの説明
別のカメラからの見た目のポジションを現在のカメラへ見た目のポジションへの変換はNDCを使えば簡単に出来ます。
toNDCにより、ポイントの位置情報をカメラからの見た目の位置情報をxyzのベクター情報に変換し、
fromNDCによりNDC座標をワールドスペースのxyz座標に変換します。
![NDC01.png](https://qiita-image-store.s3.amazonaws.com/0/152922/c3e861dd-1209-e82e-de0d-898b4bf5fe47.png)
Wrangleにではこんな感じ。chsは　/obj/cam1　のようなカメラパス。
`@P = toNDC(chs("otherCamera"),@P);
@P = fromNDC(chs("currentCamera"),@P);`
時間別のそれぞれのNDC座標を取得し現在のカメラへの見た目のポジションに戻してやり、それを繋ぐ事でカメラからの見た目の軌跡を描く事が出来ます。
#先ずは止まってるポイントに対しての動いてるカメラから見たモーションライン
こんな感じに適当にポイントを作り、その周りをグルグルカメラが回るようにします。
ポイントには`@id=@ptnum`とかでいidアトリビュートをセットして置いてください。
![NDC02.png](https://qiita-image-store.s3.amazonaws.com/0/152922/6a9d5c3f-c69e-8c0f-8a7d-26cb999d82e7.png)

それにForEach内の**TimeShift**でずらしたフレーム毎にカメラのndcスペースの値をv@ndcに取得していき、
ForEachの外でfromNDCによりまとめて現在のカメラへのワールドスペースのポジションへ変換してやります。
TimeShifはForEachのiterationを利用して-0.5~0.5フレーム内の値をiteration数取る様にしています。
![NDC03.png](https://qiita-image-store.s3.amazonaws.com/0/152922/b62b1cfc-4519-513d-cbac-fb90fad7ca7e.png)

結果はこのような感じです。ForEachのIterationの値を上げる事で補間が滑らかになります。
長さ(シャッタースピード)を変えたいときはTimeShiftの値を調整してください。
![NDC04.png](https://qiita-image-store.s3.amazonaws.com/0/152922/e6729775-fa21-36bb-49e8-1171be5a23a3.png)

#動いてるポイントに対しての動いてるカメラから見たモーションライン
ポイントがアニメーションによって動いてる場合はTimeShiftが必要なフレームを取得してくれているのでさっきと同じので全く問題ありませんが、ポイントがパーティクルシミュレーションによって動き、フレーム毎にキャッシュしてる場合は多少セットアップを必要とします。なぜなら0.25フレームずらすとかだとキャッシュがそこに無かったりするから。

なのでポイントは現在のフレームに固定し、vとforce(accel)から前後のフレームポジションを算出しつつカメラスペースは各時間軸から取得しなければいけません。

答えは簡単で、ndc取得前の段階でTimeShiftを逆にずらしてndc取得段階でフレームが+-0になるようにするだけです。
ndc取得時には0.5フレームずらした所からIteration毎に進みながらndcを取得するので、事前にその逆のTimeShiftをしておきます。
![NDC05.png](https://qiita-image-store.s3.amazonaws.com/0/152922/41298e86-a7c5-c751-8ed1-9a806529fae2.png)
vとforceからのオフセットポジションはこんな感じです。時間上のフォースの変化などは考慮されてないので正確って訳ではないですけどね。
`float offset = ch("offset");
@P += @v*offset*@TimeInc + @force * pow(offset*@TimeInc,2)*0.5;`
![NDC06.png](https://qiita-image-store.s3.amazonaws.com/0/152922/65cd2067-98cc-7232-f6ed-ab851c20a6e4.png)
さっきの回るカメラでこうなる
![NDC07.png](https://qiita-image-store.s3.amazonaws.com/0/152922/bbb5df29-d69d-7795-3d66-217d7676dfd9.png)

#レンダリング時にモーションブラーを打ち消す！
こういうラインの火花エレメントが出来たとして、これはこれでモーションブラーを切って独立してレンダリングする事になると思います。が、他のマットオブジェクトと絡んだりすると、コンポジターの方々から「マスクが合わねぇ！」と言うメッセージが飛んでくる事になってしまいます。マットにはモーションブラーが必要だがラインには掛けたくないのです。
オブジェクト毎にデフォ－ム、ベロシテー、カメラモーションブラーを細かくオンオフ出来るレンダラーなら良いですがそうでないレンダラーのほうが多い。そこでカメラースペースのモーションブラーを逆算してそれをvelocity blurとして入れてやり見かけ上カメラから見て動いてないように騙しましょう。

シャッタータイミングがセントラルとして、これは前後のフレームのカメラスペース上の位置が分かれば可能です。
なるべく現フレームに近いほうが正確ですがとりあえず0.5フレーム前後取ります。
最後のｖ計算で`@opinput1_P`を取得するときのidが残ってると結果がぶっ壊れるので、attribute to matchのデフォルト値のidは消しておきましょう。これに関しては2パターンとればいいのでforEachでなくこんな感じで。
![NDC08.png](https://qiita-image-store.s3.amazonaws.com/0/152922/8686eea0-fa4a-623e-5c6c-76c2fdef816b.png)


モーションブラーオフ、オン、そして逆算velocity入りのモーションブラーオンの比較です。
![NDC09.png](https://qiita-image-store.s3.amazonaws.com/0/152922/bdffebbd-3797-6cc9-7da0-11f46256e0d6.png)

https://youtu.be/bJBrylsJJ-c

ちょっとラインが長すぎますかね？よくコンポジターから短いのもくれって言われます。その辺はいろいろ各自調整ということで。