Godot GDScript 16 「Quat と slerp()」 1/2
ラジアンでの回転または角度の決め打ちはGDScriptの15でまとめたが、別の回転表現としてGodotには、Quat
と言うのがあるらしい。これはQuaternion(発:クォータニオン)という[x, y, z, w]の4つの要素から出来ている~~なんたら~かんたら~、、、分からん! ま、あまり深入りせずに、目的の動作である「0°(または360°)をまたいだ回転」を実現できればいいやと考えよう。
線で考えるからまたげない
補間の仕方には、Vector3
型ならlinear_interpolate()
、float
型ならlerp()
(Linear interpolation)がある。しかし、ふたつともAB間を線で考えるから、角度0°をまたげない。
linear_interpolate()
関数はもともと対象がVector3
型だから、角度を扱う事はないと思うけど、復習するとこんな感じ。
当然だが補間点は線分AB上、つまり線で考えてる。(キャラコンの07も参照。)
前回失敗した、無理やりラジアンをlerp()
させるやり方は、起点"0"、終点"2パイ"の値をとる線分上で補間点を求めることになるので、
こうなって、近回りしてほしいのに、0(0°)、2パイ(360°)をまたげない。円をパカッて開いて、0~2パイの線にしちゃってるんだな。
またぐため、円のままで考える事が出来るのがslerp()
(スラープ)
spherical linear interpolation。簡単に言うと、0°(360°)をまたいで補間してくれるもの。角度の近い方でAB間を取ってくれる、近回りしてくれる、と考えればいい。
使い方は、Vector3
型のlinear_interpolate()
と同じだが、変数が、物体の回転を表すQuat
型であることに注意する。
こうやって近回りして、円上に補間点を作ってくれる。
クォータニオン
に関しては考えない。回転を表す型とだけ考えておく。2つの角度でslerp()
出来ればいいだけだから。ただ、クォータニオン(Quat
型)を取ってくる方法と、それを使って回転をセットする方法だけ覚える。
Quat
、「とってき方」と「あてはめ方」
いきなりQuat
もslerp()
もだと辛いので、Quat
を先に練習する。ニュープロジェクト。
[1]
ノードはこんな感じでつくる。
「Spatial」でミーとターゲットを作って、回転が見て分かりやすい様に「MeshInstance」を適当に子として付ける。
ターゲットの方は位置を(-8, 0, -3)にし、y軸で30°回転させた。図は真上から見たもの。
[2]
スクリプトはルートノードに貼る。
最初は簡単にQuat
を使ってターゲットの回転と同じになるようにミーの回転をセットする方法。
L3~4
- いつものようにノードを操作できるように、変数を用意。
L6
- ターゲットが持っている
Quat
値を入れる変数を用意。 - 今回はターゲットが持っている
Quat
値を取って来て、それをミーに反映させるため。
L10~11
- 操作するので、いつものように代入。
L13
Quat
の「とってき方」。Quat()
関数を使う。変換候補として出てくる次の3パターンがあるが、今回は一番下の"basis"を使ったやり方で「とってき」た。
- これで、ターゲットの持つ
Quat
値が"quat_target"に入る。 - ちなみに"basis"はキャラコンの05を参照。
L15
Quat
の「あてはめ方」。- あてはめるには
Transform()
関数を使う。変換候補の下から2番目に、Quat
を使ってノードのトランスフォームをセットする方法があるのが分かる。
Transform()
関数はリターンタイプがTransform
型なので、それに合わせてミーの方も変数を"node_me.global_transform"とし、受け入れられるようにする。
で、[シーン再生]。
ミーがターゲットと同じ回転を示せがイイ。
まとめ
Quat()
でとって来て、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)