俺に解るように説明する "Armory Engine" 入門+

ゲームエンジン Armory Engine (Armory3D) の使い方を手探りで学んで入門しようって感じかな。

P6.ねぇ、アリシアちゃん☆.04「回転テスト。Rotation と Atan2(Arctan2) と ノードで簡易 Lerp Slerp」

f:id:ore2wakaru:20190616091759p:plain

カメラ制御も移動も出来た。で、今度はアリシアちゃんを進行方向に(まー出来ればスムーズに)向かせたいわけだが、色々やってみた結果「結構回転って難しいんだなー」ってのが分かった。で、間違ってるかもしれないが(多分あってるとは思うけど・・・)、分かった事を忘れないうちに書いておこうと思う。

真上から見て Z 軸で回転させる

BlenderXY 平面Z 高さ(Z Height)。だから、Z 軸を回転させることで XY 平面のあっちを向いたりこっちを向いたりできるわけだ。「玉転がし」でやったようにRotate Objectで、Z にだけ数値を入れてやれば Z 軸回転させられる。

だが、Z 軸に着目してアリシアちゃんが向いている方向向かせたい方向(移動方向)の差角を取って来るのが意外と難しい。

何でかって言うと、Armory は何か変な回転の仕組みを取ってる感じなんだ。いや、これが一般的なのかもしれないが、、、俺にとって変であることは間違いない。

どーなってるかというと

物体を真上から見たときの Z 角(Angle)を見ていく。基本的に角はラジアン(360° は 2π ってやつね)。で、こう。

f:id:ore2wakaru:20190616041255p:plain

図の左(Rotation):

  • Z 軸でプラス方向に回転させていくと回転する。スタート は真上で Z は "0"。そこから増えていき、+90° で、Z は " + \frac{1}{2} π" となる。だがそのまま回転させていくと、ここから数値が減っていき、+180° で "0" になる。
  • 今度はマイナス方向に回転させてみる。回りとなる。スタート は真上で Z は "0"。これは一緒。そこから減っていき-90° で、Z は " - \frac{1}{2} π" となる。今度はここで数値が増加に変わり、-180°"0" になる。
  • これで、例えば +45° を考えると、Z は " + \frac{1}{4} π" だよね。だけど、+135° でも同じ " + \frac{1}{4} π" になるだろ! これじゃ区別がつかないわけだよ。どーすんの?

f:id:ore2wakaru:20190616045336p:plain

  • ってことで、なんと、関係ないと思われた XY の値が変化する。+45° の場合は "0"。+135° の場合は "-2π" となる。これで区別するようだ。物体が上(プラスY方向)を向いてる場合は、X Y は "0" で、下(マイナスY方向)を向いてる場合は "-2π" ってことだ。(まー、最初の図に書き入れてあるから注意してみろな。)
  • +45° は(X: 0, Y: 0, Z:  + \frac{1}{4} π)。+135° は(X: -2π, Y: -2π, Z:  + \frac{1}{4} π)。 めんどくさい。 だから、Get RotationZ だけ持って来て単にセットするってのが出来ないんだわな。XY も考えないとイケナイ。 めんどくさすぎる・・・。

といわけで、こんどは右の図で考えることにする。Godot の時にもやったけど(この辺参照)、回転角度は Atan2 という関数をゴニョゴニョすることでもってこれる。幸いなことに Armory でもこの関数が使えるので、これを使ってやってみる。ただしこっちでは平面が XY なので、Atan2(X, Y)Z 角が取り出せるって感じになる。

f:id:ore2wakaru:20190616041255p:plain

図の右Atan2):

  • ただ、Godot では Atan2(アタン2)だったが、Armory では Arctan2(アークタン2)だけどな。細かい事は気にするな。あ~くタン、かわいいな。
  • プラス回転回り。Rotation の時とは逆回転で表せるようだ。 で "0"、+90° で " + \frac{1}{2} π"、+180° で ""。非常にスムーズ、一直線。
  • マイナス回転は、回り。 で "0"、-90° で " - \frac{1}{2} π"、-180° で ""。こちらも非常にスムーズ、一直線。
  • 角は "-π ≦ Z ≦ +π" の範囲で推移し重複は無し。つまり、XY のことを考えなくていいわけだ。こっちのがじゃね?

ってことで、丸1日かけて Arctan2 で物体を向かせたい方向に向かせるノードトゥリーを作ったわけなんだ。何かの参考になるじゃろ。一応載せとくな。

Arctan2 で回転

先ずは全体図。

f:id:ore2wakaru:20190616075532p:plain

以下、パーツで区切って解説。

f:id:ore2wakaru:20190616075916p:plain

  • "targetZ" が目標とする Z 角。向きたい方向。で、"meZ" が自分の Z 角。
  • まずは、それぞれの大砲の先っちょとの位置の差を取って来て XY のベクトルをつくる。
  • 次に、Arctan2 を使って Z を取り出す。Arctan2 は上図のようにMathの中にあるから探してくれ。Value は、XY を設定する。

f:id:ore2wakaru:20190616080844p:plain

  • "saZ": "targetZ" と "meZ" の差角を入れる。
  • "piPls": 。 "piMns": 。 ノードでは定数が使えないんだろうか? "3.14159" までの精度(6桁?)しか入らないようだ。

f:id:ore2wakaru:20190616081635p:plain

  • 差角が「 未満」または「 超」の時、自分の Z("meZ")を再設定し、遠回りしないで回るようにする。(簡易 Slerp
未満 以上 以下
イベント "UNDER" で修正 修正なし イベント "OVER" で修正

f:id:ore2wakaru:20190616082909p:plain

  • イベント "BETWEEN" で Lerp させて、最後に角度をセット。RotationArctan2 では Z が逆回りだから "-1" を掛けている。

f:id:ore2wakaru:20190616084052p:plain

  • "meZ" を "targetZ" へ近づける。(Lerp
  • Lerp させるにはMixノードの "Linear" を使う。Value1Value2 の間の数値が取り出せる。Factor が "0" なら Value1 の値、Factor が "1" なら Value2 の値となる。
  • 上図のように Factor: "0.9" とは、Value1 から Value2 へ向かう数値の 90% の位置にある数値を取り出してくれという事。つまり、角は差角が 10% ずつ縮まっていくという事。
  • ただし、UpdateDelta 時間に左右されるから物理時間で作業させるか、上手くタイマーを使うかしないとPC毎に動きが違くなる。(今回は考慮しなかった)

f:id:ore2wakaru:20190616090228p:plain

  • "2π" 引いて遠回りしないようにする。
  • なんで "2π" 引くのかは、数直線で考えると分かりやすい。(だがメンドクサイので図は書かない。時間があったらいつか追加しよう。)

f:id:ore2wakaru:20190616090238p:plain

  • "2π" 足して遠回りしないようにする。
  • 上と同じ。

以上。


 またまたノードだけで実現させてしまったか。やっぱり俺、天才だな。うんうん。