目的
Godotではノードを親子関係にして、子は親の座標系内のローカル位置を保持しています。
また子はglobal座標系の位置も取得することができます。
今回はGlobalと子の中間ノード上の座標系で子の位置を取得する方法を調査しました。
結論から言うと、親のtransform(Transform3D) を子の位置(Vector3)に「*」で計算すると親の座標系上の位置を計算することができました。
参考
GODOT DOCS : Matrices and transforms
https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html#
シーン
下記のようなシーンを作成します。
ノード名:ノードクラス名 | インスペクタ変更値 |
---|---|
Global : Node3D | Rotation : (0°, 90°, 0°) |
┗┳Parent : MeshInstance3D | 新規PlaneMesh3D、Position : (2m, 0m, 1m) |
┗━Child : MeshInstance3D | 新規SphereMesh3D |
座標の確認
Childの位置
Childは初期値なので、(x,y,z)=(0,0,0)になります。
Parent/Childの位置
ParentはPositionを(x,y,z)=(2m, 0m, 1m)に設定していますので、Parent座標系の中ではChildの球の位置も(2m, 0m, 1m)になります。この位置を計算で取得するのが本記事の目的です。
下図は上面図です。右側がXプラス、下がZプラスになります。
Global/Parent/Childの位置
GlobalはY軸周りに90°回転しています。子の位置は(x,y,z)=(1m, 0m, -2m)になります。
トップノードなので、global_positionで位置を取得することができますが、計算でも求めたいと思います。
スクリプトと実行結果
シーン内のGlobalノードを右クリックして、スクリプトをアタッチして下記のように修正します。
extends Node3D
func _ready():
var child : MeshInstance3D = $Parent/Child
var parent : MeshInstance3D = $Parent
var global : Node3D = $"."
print("child pos(x,y,z)")
print(" local :", child.position)
print(" parent coordinate :", parent.transform * child.position)
print(" global coordinate :", global.transform * parent.transform * child.position)
print(" global_position :", child.global_position)
実行結果は下記のように出力されます。
child pos(x,y,z)
local :(0, 0, 0)
parent coordinate :(2, 0, 1)
global coordinate :(1, 0, -2)
global_position :(1, 0, -2)
child.position(Vector3)にparent.transform(Transform3D)を掛け合わせると、parent座標系上の位置に変換できました。
同様にglobal.transform(Transform3D) * parent.transform(Transform3D) * child.position(Vector3)でglobal_positionと同じ値になることを確認できました。
以上