P6.ねぇ、アリシアちゃん☆.04「回転テスト。Rotation と Atan2(Arctan2) と ノードで簡易 Lerp Slerp」
カメラ制御も移動も出来た。で、今度はアリシアちゃんを進行方向に(まー出来ればスムーズに)向かせたいわけだが、色々やってみた結果「結構回転って難しいんだなー」ってのが分かった。で、間違ってるかもしれないが(多分あってるとは思うけど・・・)、分かった事を忘れないうちに書いておこうと思う。
真上から見て Z 軸で回転させる
Blender は XY 平面の Z 高さ(Z Height)。だから、Z 軸を回転させることで XY 平面のあっちを向いたりこっちを向いたりできるわけだ。「玉転がし」でやったようにRotate Object
で、Z にだけ数値を入れてやれば Z 軸回転させられる。
だが、Z 軸に着目してアリシアちゃんが向いている方向と向かせたい方向(移動方向)の差角を取って来るのが意外と難しい。
何でかって言うと、Armory は何か変な回転の仕組みを取ってる感じなんだ。いや、これが一般的なのかもしれないが、、、俺にとって変であることは間違いない。
どーなってるかというと
物体を真上から見たときの Z 角(Angle)を見ていく。基本的に角はラジアン(360° は 2π ってやつね)。で、こう。
図の左(Rotation):
- Z 軸でプラス方向に回転させていくと左回転する。スタート 0° は真上で Z は "0"。そこから増えていき、+90° で、Z は "" となる。だがそのまま回転させていくと、ここから数値が減っていき、+180° で "0" になる。
- 今度はマイナス方向に回転させてみる。右回りとなる。スタート 0° は真上で Z は "0"。これは一緒。そこから減っていき-90° で、Z は "" となる。今度はここで数値が増加に変わり、-180° で "0" になる。
- これで、例えば +45° を考えると、Z は "" だよね。だけど、+135° でも同じ "" になるだろ! これじゃ区別がつかないわけだよ。どーすんの?
- ってことで、なんと、関係ないと思われた X と Y の値が変化する。+45° の場合は "0"。+135° の場合は "-2π" となる。これで区別するようだ。物体が上(プラスY方向)を向いてる場合は、X Y は "0" で、下(マイナスY方向)を向いてる場合は "-2π" ってことだ。(まー、最初の図に書き入れてあるから注意してみろな。)
- +45° は(X: 0, Y: 0, Z: )。+135° は(X: -2π, Y: -2π, Z: )。 めんどくさい。 だから、
Get Rotation
で Z だけ持って来て単にセットするってのが出来ないんだわな。XY も考えないとイケナイ。 めんどくさすぎる・・・。
といわけで、こんどは右の図で考えることにする。Godot の時にもやったけど(この辺参照)、回転角度は Atan2 という関数をゴニョゴニョすることでもってこれる。幸いなことに Armory でもこの関数が使えるので、これを使ってやってみる。ただしこっちでは平面が XY なので、Atan2(X, Y) で Z 角が取り出せるって感じになる。
図の右(Atan2):
- ただ、Godot では Atan2(アタン2)だったが、Armory では Arctan2(アークタン2)だけどな。細かい事は気にするな。あ~くタン、かわいいな。
- プラス回転は右回り。Rotation の時とは逆回転で表せるようだ。0° で "0"、+90° で ""、+180° で "+π"。非常にスムーズ、一直線。
- マイナス回転は、左回り。0° で "0"、-90° で ""、-180° で "-π"。こちらも非常にスムーズ、一直線。
- 角は "-π ≦ Z ≦ +π" の範囲で推移し重複は無し。つまり、XY のことを考えなくていいわけだ。こっちのが楽じゃね?
ってことで、丸1日かけて Arctan2 で物体を向かせたい方向に向かせるノードトゥリーを作ったわけなんだ。何かの参考になるじゃろ。一応載せとくな。
Arctan2 で回転
先ずは全体図。
以下、パーツで区切って解説。
- "targetZ" が目標とする Z 角。向きたい方向。で、"meZ" が自分の Z 角。
- まずは、それぞれの大砲の先っちょとの位置の差を取って来て XY のベクトルをつくる。
- 次に、Arctan2 を使って Z を取り出す。Arctan2 は上図のように
Math
の中にあるから探してくれ。Value は、上に X、下に Y を設定する。
- "saZ": "targetZ" と "meZ" の差角を入れる。
- "piPls": +π。 "piMns": -π。 ノードでは定数が使えないんだろうか? "3.14159" までの精度(6桁?)しか入らないようだ。
- 差角が「-π 未満」または「+π 超」の時、自分の Z("meZ")を再設定し、遠回りしないで回るようにする。(簡易 Slerp)
-π 未満 | -π 以上 +π 以下 | +π 超 |
---|---|---|
イベント "UNDER" で修正 | 修正なし | イベント "OVER" で修正 |
- イベント "BETWEEN" で Lerp させて、最後に角度をセット。Rotation と Arctan2 では Z が逆回りだから "-1" を掛けている。
- "meZ" を "targetZ" へ近づける。(Lerp)
- Lerp させるには
Mix
ノードの "Linear" を使う。Value1 と Value2 の間の数値が取り出せる。Factor が "0" なら Value1 の値、Factor が "1" なら Value2 の値となる。 - 上図のように Factor: "0.9" とは、Value1 から Value2 へ向かう数値の 90% の位置にある数値を取り出してくれという事。つまり、角は差角が 10% ずつ縮まっていくという事。
- ただし、Update の Delta 時間に左右されるから物理時間で作業させるか、上手くタイマーを使うかしないとPC毎に動きが違くなる。(今回は考慮しなかった)
- "2π" 引いて遠回りしないようにする。
- なんで "2π" 引くのかは、数直線で考えると分かりやすい。(だがメンドクサイので図は書かない。時間があったらいつか追加しよう。)
- "2π" 足して遠回りしないようにする。
- 上と同じ。
以上。
★ またまたノードだけで実現させてしまったか。やっぱり俺、天才だな。うんうん。