四元数を用いて方向や回転の補間を行う際の注意点
はじめに
三次元的な回転や方向を表現する方法として、四元数 (Quaternion) は大変重要なツールです。先日、四元数同士を補間するプログラムを書いていて、ある不具合が起き、原因が分からずしばらく悩んでいました。日本語での情報が少ないようでなので、その件について簡単に紹介したいと思います。
四元数とは
四元数の基本については Wikipedia を参考にして下さい。
コンピュータグラフィクスやゲームプログラミングの文脈で四元数が登場するのは、方向 (Orientation) や回転 (Rotation) を扱うときです。四元数それ自体は方向や回転を扱うためのものではないのですが、単位四元数 (長さが 1 になるように正規化された四元数) は方向や回転を記述するために利用できるということです。
四元数同士の補間 (Lerp と Slerp)
四元数で表された 2 つの方向や回転を補間したい場合は Lerp (Linear Interpolation, 線形補間) または Slerp (Spherical Linear Interpolation, 球面線形補間) を用います。
これらは、こちらの記事でも詳しく解説されている通り、「距離最小性」という数学的な性質を充たしながら補間してくれます。
補間された方向や回転、本当に距離は最小なのか?
さて、ここからが本題です。
正負の四元数は同じ回転や方向を表す
ある単位四元数 について、 と は全く同じ回転や方向を表しています。
そこで、ある 2 つの単位四元数 と を補間する際には、 と 、または と のどちらを用いても良いのか、という疑問が出てきます。
The Long Path Problem (長い道筋問題)
実は、Lerp (q0, q1) と Lerp (q0, -q1) とでは意味が異なってきてしまうそうです。
このことは、この記事 (英語) で詳しく解説されています。簡単に言えば、q0 の表す方向や回転から q1 の表す方向や回転に向かう道筋 (Path) には 2 つあって、短い道筋と長い道筋があるということです。それが、Lerp (q0, q1) と Lerp (q0, -q1) の違いに表れてきます。
短い道筋と長い道筋、どちらが距離最小性を充たしているかという話ではなく、距離最小性と呼ばれる性質を充たすような補間の道筋が 2 つあるという意味だと思います。
では正負の符号はどのように決定するべきなのでしょうか。
短い道筋を選ぶ
再びこの記事 (英語) に依れば、q0 と q1 の内積の値が正ならば短い道筋、負ならば長い道筋で補間されるとのことです。ここでの内積とは四元数を四次元のベクトルと見たときの内積のことです。
普通、2 つの方向や回転を補間する際には短い道筋を選びたいことが多いでしょうから、そういった場合には
Quaternion result; double value = DotProduct (q0, q1); if (value > 0.0) { result = Lerp (q0, q1, t); } else { result = Lerp (q0, -q1, t); }
のようにして補間結果を得れば良いということになります。
もしこの記事の内容に誤りや誤解を招く表現等があることを発見された場合は、是非コメント欄にてお知らせ下さい。