下の記事でQuaternionについてまとめたので、
ついでにUnityでQuaternionを使う方法をまとめてみます。
作り方
Quaternionはいろんな方法で作れます。
// 回転角度と回転軸から作る transform.rotation = Quaternion.AngleAxis(90, Vector3.forward); // 角軸に対する回転角度を指定して作る transform.rotation = Quaternion.Euler(0, 0, 90); // 第一引数のベクトルを第二引数のベクトルまで回転させるためのQuaternionを作る transform.rotation = Quaternion.FromToRotation(Vector3.up, Vector3.left); // 無回転のQuaternionを作る transform.rotation = Quaternion.identity;
また、Quaternionの仕組みを知っていれば成分の値を直接入れることもできます。
あまりやらないとは思いますが。
var axis = Vector3.forward; var halfRad = 90 * Mathf.Deg2Rad * 0.5f; var sin = Mathf.Sin(halfRad); var cos = Mathf.Cos(halfRad); transform.rotation = new Quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos);
回転を合成する
回転を合成するにはQuaternionの積を求めます。
var a = Quaternion.AngleAxis(90, Vector3.forward); var b = Quaternion.AngleAxis(90, Vector3.up); var rotation = a * b;
ベクトルを回転する
ベクトルを回転するにはQuaternionとVector3の積を求めます。
var vec = Quaternion.AngleAxis(90, Vector3.forward) * Vector3.up;
演算子としては積を計算していますが、内部的には下記の計算をしています。
: Quaternion
: 回転させるベクトルにw=1を加えて4次元にしたもの
: 共役Quaternion
逆回転にする
回転を逆にするためには、Quaternion.Inverse()を使います。
var quaternion = Quaternion.AngleAxis(90, Vector3.forward);
transform.rotation = Quaternion.Inverse(quaternion);
また、Quaternionは下記のように定義されます。
: 回転軸
: 回転角度
このため、に-1をかける、 つまり、、成分に-1を掛けても逆回転のQuaternionを求められます。
var quaternion = Quaternion.AngleAxis(90, Vector3.forward); quaternion.x *= -1; quaternion.y *= -1; quaternion.z *= -1; transform.rotation = quaternion;
Quaternion間の角度を求める
Quaternion間の角度はQuaternion.Angle()を用いて求めます。
var a = Quaternion.identity;
var b = Quaternion.AngleAxis(90, Vector3.forward);
Quaternion.Angle(a, b);
また、内積を使って下記のように求めることもできます。
//a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; var cos = Quaternion.Dot(a, b); var rad = Mathf.Acos(cos) * 2; rad * Mathf.Rad2Deg;
回転軸を求める
回転軸を求めるには、Quaternionのxyz成分を使って3次元ベクトルを作り、必要に応じて正規化します。
var quaternion = Quaternion.AngleAxis(90, Vector3.forward);
var axis = Vector3.zero;
axis.x = quaternion.x;
axis.y = quaternion.y;
axis.z = quaternion.z;
axis.Normalize();
回転角度も同時に求めたい場合はQuaternion.ToAngleAxis()を使うのが良いと思います。