俺に解るように説明する "Godot Engine 3.x" 入門+

ゲームエンジン Godot Engine に関すること。入門とか使い方とかチュートリアルとか、あれとかこれとか。日本語解説。

Godot GDScript 16 「Quat と slerp()」 1/2

ラジアンでの回転または角度の決め打ちはGDScriptの15でまとめたが、別の回転表現としてGodotには、Quatと言うのがあるらしい。これはQuaternion(発:クォータニオン)という[x, y, z, w]の4つの要素から出来ている~~なんたらかんたら~、、、分からん! ま、あまり深入りせずに、目的の動作である「0°(または360°)をまたいだ回転」を実現できればいいやと考えよう。

f:id:ore2wakaru:20180421171741p:plain


線で考えるからまたげない

補間の仕方には、Vector3型ならlinear_interpolate()float型ならlerp()(Linear interpolation)がある。しかし、ふたつともAB間をで考えるから、角度0°をまたげない。

linear_interpolate()関数はもともと対象がVector3型だから、角度を扱う事はないと思うけど、復習するとこんな感じ。

f:id:ore2wakaru:20180421171544p:plain

当然だが補間点は線分AB上、つまりで考えてる。(キャラコンの07も参照。)

前回失敗した、無理やりラジアンlerp()させるやり方は、起点"0"、終点"2パイ"の値をとる線分上で補間点を求めることになるので、

f:id:ore2wakaru:20180421173124p:plain

こうなって、近回りしてほしいのに、0(0°)、2パイ(360°)をまたげない。円をパカッて開いて、0~2パイのにしちゃってるんだな。


またぐため、円のままで考える事が出来るのがslerp()(スラープ)

spherical linear interpolation。簡単に言うと、0°(360°)をまたいで補間してくれるもの。角度の近い方でAB間を取ってくれる、近回りしてくれる、と考えればいい。

使い方は、Vector3型のlinear_interpolate()と同じだが、変数が、物体の回転を表すQuat型であることに注意する。

f:id:ore2wakaru:20180421182648p:plain

こうやって近回りして、上に補間点を作ってくれる。


クォータニオン

に関しては考えない。回転を表す型とだけ考えておく。2つの角度でslerp()出来ればいいだけだから。ただ、クォータニオンQuat型)を取ってくる方法と、それを使って回転をセットする方法だけ覚える。


Quat、「とってき方」と「あてはめ方」

いきなりQuatslerp()もだと辛いので、Quatを先に練習する。ニュープロジェクト。

[1]

ノードはこんな感じでつくる。

f:id:ore2wakaru:20180421191824p:plain

Spatial」でミーターゲットを作って、回転が見て分かりやすい様に「MeshInstance」を適当に子として付ける。

ターゲットの方は位置を(-8, 0, -3)にし、y軸で30°回転させた。図は真上から見たもの。

[2]

スクリプトはルートノードに貼る。

最初は簡単にQuatを使ってターゲットの回転と同じになるようにミーの回転をセットする方法。

f:id:ore2wakaru:20180421195017p:plain

L3~4

  • いつものようにノードを操作できるように、変数を用意。

L6

  • ターゲットが持っているQuat値を入れる変数を用意。
  • 今回はターゲットが持っているQuat値を取って来て、それをミーに反映させるため。

L10~11

  • 操作するので、いつものように代入。

L13

  • Quat「とってき方」
  • Quat()関数を使う。変換候補として出てくる次の3パターンがあるが、今回は一番下の"basis"を使ったやり方で「とってき」た。
    f:id:ore2wakaru:20180421195628p:plain
  • これで、ターゲットの持つQuat値が"quat_target"に入る。
  • ちなみに"basis"はキャラコンの05を参照。

L15

  • Quat「あてはめ方」
  • あてはめるにはTransform()関数を使う。変換候補の下から2番目に、Quatを使ってノードのトランスフォームをセットする方法があるのが分かる。
    f:id:ore2wakaru:20180421200458p:plain
  • Transform()関数はリターンタイプがTransform型なので、それに合わせてミーの方も変数を"node_me.global_transform"とし、受け入れられるようにする。

で、[シーン再生]。

ミーターゲットと同じ回転を示せがイイ。

f:id:ore2wakaru:20180421202854p:plain


まとめ
  1. Quat()とって来て
  2. Transform()あてはめる

あとはslerp()させるだけだが、それは次回にしよう。


こぴぺ

extends Node

var node_me
var node_target

var quat_target

func _ready():
    
    node_me = get_node("Spatial_Me")
    node_target = get_node("Spatial_Target")
    
    quat_target = Quat(node_target.global_transform.basis)
    
    node_me.global_transform = Transform(quat_target)