2019年5月4日土曜日

copyToPointの回転まわり

オブジェクトをcopyToPointでコピーする際、v,N,up,orient,rotを使用して回転する方法をまとめました。なかでも、よく使用するpopで動きを付けた後、sopで回転制御する方法です。
このまとめの発端は、以下のcase3で起こる問題に悩んでたのですが、odforceでみつけたhipにより道がひらけ色々学べたことです。
なので、問題を解決したベースのアイデアとしては、そのhipがもとになっております。
また、他にもっとシンプルなやり方があるかもしれないです。なるべくシンプルで分かりやすい方法でやりたいので、そういうのありましたら教えてくださいませ。

前提知識として、以下の2項目に触れておくと、検証動画もすんなり理解できるかもしれません。

▼v,N,up,orient,rotについて
こちらに詳細が書かれてあります。使い方はこちらとか。
orientはN,upのようにquatanionで姿勢を制御できるようです。なので姿勢を制御するならN,upの二つのアトリビュートかorientの1つのアトリビュートかどちらかでよさそうです。orientは、N,up含む値なのでNとupはdeleteしても大丈夫です。
次に、orientともう一つのquatanionのrotというものがあります。
現状自分なりの解釈ではorientで姿勢決めてrotでその姿勢の任意の軸をもとにspinしてやるときに使うのが分かりやすく便利かなと思います。orientだけでいきたい!という方は姿勢を決めたorientにrotのquatanionをかけてあげれば、同じ結果が得られます。
また、N,up,orient,rotがない場合vがあれば回転してくれるようです。
※姿勢と回転(spin)という言葉がまじりあってますが、計算自体は同じquatanionで、わかりやすく区別しています。

▼quatanionについて
google検索すればたくさん情報でてきますね。
その中でも、こちらがとても参考になりました。
まだ、記事全てを把握はできてませんが、quatanionで姿勢を制御することや補間についてイメージできました。式より図で示してくれるとわかりやすいですね。
他にも姿勢、回転を制御するにはオイラー方式がありますが、制限や計算の負荷の面から考えるとquatanionの方が優位だそうです。2D空間の回転の場合はオイラーのほうがよいでしょう。お互いの利点を見極め使っていくとよいでしょう。そして、quatanion,オイラーは最終的には回転行列に変換され回転されます。
mayaのヘルプにも面白いの発見しました。案外丁寧に説明されてました。mayaだとquatanionの補間にも最短と最長があり選べたりできるみたいですね。
cg wikiにもあります。これ一通りやるほうがためになるでしょう。自分は、まだ追えてません。

では、簡単な回転からやっていきましょう。
ちなみに、以下の検証したhip※随時更新中)です。すべて言葉でカバーするのは大変なのでデータ観ながら以下見てもらった方がよいかもです。

  • case1

randomSpinBasic
適当な姿勢(N,up)をランダムに作り、cross(N,up)で作成した軸をもとにspinさせました。動画を見る通り、時間軸に対し姿勢の各軸に変化はなく一定で、安定したspinです。はじめに回転軸を決めてあげるってのがポイントですね。やり方として飛び散る破片とかはこれで十分ではないでしょうか。

  • case2

VelocitySpinBasic
次に、進行方向vをNとして姿勢(N,up)をつくりspinさせます。姿勢は進行方向vに沿って時間軸で変化が見られますが、これくらいの変化であれば、問題はありません。

velocityDirectionBasic
spinを切って確認しても問題はありません。

  • case3

次に、姿勢が大きく変化するケースを見てみます。シチュエーションでいうと、ジェット機とかのエアロバティックス、空中を飛び回る生物、物体に衝突したり、forceによる強い外力を受けるときなどでしょうか。
こういった姿勢の変化はNG動画のようにやり方によって意図せぬ回転を引き起こします。

velocityDirectionBasicNG
よく見ると、方向転換する時クルっとフリップしたかのように回転しています。エラーのように見えます。
ちなみに今の設定は、case2同様に進行方向vをNにしてcross関数でupを作っております。

velocityDirectionBasicOK
こちらは、フリップのような回転を調整したものになります。
次から、どのように調整したのかを細かく進めながら原因も探っていきます。

  • case4

分かりやすく豚1匹にしました。
そして、それぞれのアトリビュートを比べてみます。

Only v attribute
Only N attribute
v,Nは変わらないようですね。

Only_N&Up_attribute
N&Upはcase.3のNGと同じ動きですが、頭の方向をupで指定することで、姿勢は保たれました。

orient
orientは、豚の初期方向とvからquatanionを作りそれをorientとしました。visualize用に、各軸quatanionで回転させています。
どれも意図しない回転が入ってNGですね。

突き詰めて探ってないので、想像ですが、考えられる原因として述べます。
なぜ意図しない回転が入るのかは、sopなので毎フレcrossだったり、quatanionだったり計算しなおしているので連続性が保たれないのが原因だと思います。
このケースではcrossやquatanionを計算する際、固定された任意の軸をもとに計算しています。
その任意の固定軸と進行方向vによって計算されるので、crossの計算で言うと、フレームによってはvが負の方向で次フレームで正の方向むけば右回り左回りと変化します。
quatanionも演算で外積使ってるみたいなので同じ理由かと。。適当。


  • case5

orient_QuaternionShortest
case4で連続性が保たれていないことが原因とみられたので、クォータニオンの作り方を変えます。そして、ここからはquatanionの性質を利用したいのでNとupは使用しません。性質というのは、quatanionの合成です。
まず、前フレームのvと現フレームのvからクォータニオンを計算します。そのクォータニオンを前フレームのクォータニオンにマルチプライする事で、合成します。そうすることで、前フレームからの最短のクォータニオンが得られます。ベクトル感覚なのが素敵ですね。
これで、大分安定してきました。

  • case6

orient_slerp
さらに、調整を加えます。
case.5をもとに方向転換する際、1フレで回転する量に制限をかけ急な方向転換を抑えます。
これには、quatanion同士をブレンド(球形補間)する方法を取ります。
vに遅れてNが回転するのが見て取れます。
これで姿勢のorientの制御は、充分に安定したかと思います。

  • case7

姿勢が安定したので、現在の姿勢の任意の軸を元に回転させてみます。こういったシチュエーションめったになさそうですが、続けます。
ようやく、初めの方に触れたrotの出番です。任意の軸はvisualizeで作ってる軸のどれかにします。その軸とangleでrotをquatanionとして作ります。そうすると、姿勢を保ったまま回転spinします。※追記5/25 rotをわざわざ作らなくてもqmultiplyで、rotのquatanionをorientにかけてあげればよい。
orientにランダムを加えることも簡単にできます。

orient_spin
orientRand_spin


※追記5/21
vのspeedで回転量を調整したい場合は、注意が必要で回転量が累積処理されているか確認しながらやるとよい。

以上です。
copyToPointは、なんだかんだ頻度高いので回転が必要になった際、自身が困らないようにの意味を含めてまとめました。全てを説明していくと時間がかかるため結構説明を省いてますが、hipをたどればある程度は理解できると思います。
又、houdiniの機能を使えば、quatanionなどの小難しいことに関しても、わかりやすく、そして深いところまで視覚的に説明できるのではないかとも思っています。自分のように数式アレルギーの方にはhoudiniは絶好の勉強道具ではないでしょうか。