例のごとく、Unity Gemsからの翻訳をどうぞ!
--------
http://unitygems.com/quaternions-rotations-part-1-c/
October 14, 2012
クォータニオン入門
クォータニオンはUnityで回転を表現するために使用される内部形式だ。(つまり変換するための行列とは別次元のもの)そしてクォータニオンは多くの開発者がいきなりつまづくところだ。分からなくなる大きな要因はインスペクタ上の表示でもあり、初めて見るとき x、y、z軸のVector3 で表示されていてこれがミスリードだ。この表示は本当はクォータニオンではない。むしろ回転のオイラー角に当たる。クォータニオン自身は確かに、x、y、zというプロパティを本当に持っているのだが、ひどいことにそれらの値はインスペクタで表示されているものと一切関係がないことだ。(反論もあるかもしれないが、あえてここでは言い切ってみよう)
クォータニオンを作成する方法はいくつかある。角度のVector3 から作成するには 三つの回転軸をパラメータとしてQuaternion.Euler を使用するか、回転を表すVector3を使用する。一定方向に向けた回転を作成するにはQuaternion.LookRotation(directionVector) を使用する。このチュートリアルでは、進めて行きながらクォータニオンを作成する様々な方法や組み合わせをみていきたい。
さて、オイラー角およびクォータニオンの違いについて整理すると:
オイラー角:
長所:
- 3Dベクトルを使用するので、理解しやすく視覚化も容易
- クォータニオンで扱うのは4変数、こちらは3変数なので演算が速い
- 回転により得られる結果が必ずひととおりでない。エンジンによって (x,y,z) または (y,x,z) またはそれ以外の順番を使用することがある。結果は毎回異なる
- ジンバル ロックが発生する。一つの回転が他と並んだとき、互いにロックされ、一つの軸が失われる。
クォータニオン:
- ジンバル ロックの発生を回避できる
- 回転を、複数の軸回転の組み合わせでなく、ターゲット ベクトル にもとづいて処理できる
- オイラー角以外にもう一つ値があるため僅かに遅い
- スティーブン・ホーキングでもないかぎり完全には理解出来ない(笑
var newVector = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.LookRotation(someDirection) * someVector;+ (プラス記号) ではクォータニオンを追加、組み合わせることは出来ない。 * (アスタリスク記号) で複数の回転を組み合わせる。
回転を表すのにVector3 の代わりにクォータニオンを使用する理由の一つはオブジェクトを回転させて、あるターゲットの値をセットするのに、3つの軸回転の値を動かすだけでは実現出来ないケースがあるためだ。これはオイラー角に影響するジンバル ロックと呼ばれる現象に起因するものであり、興味あるならばウィキペディアで調べると良いが、原因は値をひとつづつ個別に動かす必要があることに起因していて、特定の組み合わせにおいては、一つの次元による変更のために別の次元がターゲットの値に到達出来ないケースがある。クォータニオンはこの問題を解決するために、回転全体を基本的に四次元にてワンステップで実現する。
オイラー角で物事を考えるのは簡単だが、クォータニオンほど強力ではない。Unityにより二つの表現方法を互いに変換させることが容易なので使用する都度に最適な方法を選択することが可能だ。例えば、ローテーションをClamp (ある値の範囲に限定 ) したい場合、クォータニオンの .eulerAngles を取得すれば良く、それからMathf.Clamp の演算で Clamp 処理を適用してオイラー角を、.eulerAngles の値を更新するか、または新しいクォータニオンをQuaternion.Euler(指定した角度)にて作成することで、クォータニオンに再び変換すれば良い。
回転を組み合わせたいとき、例えば頭の傾きと体の回転を組み合わせたいとき、どちらのアプローチも使うことが出来るが、これらの回転はワールド座標軸を中心とした回転ではない場合、例えばキャラクターがさらに前にかがんでいるようなケースはクォータニオンを使用すべきだ。クォータニオンを使用して各々の軸の周りの回転を作成してそれらを組み合わせるのは実に簡単だ。
Unityはさらに便利な軸の定義として、transform.forward, transform.right および transform.up を使用することが出来て Quaternion.AngleAxis とともに使用することで既存のオブジェクト回転に重ねて適用することご出来る。
//回転する体のうえで頭を傾けるような動作
transform.rotation = Quaternion.AngleAxis(degrees, transform.right) * transform.rotation;
0 件のコメント:
コメントを投稿