曲線・補間

球面線形補間

Slerp / Quaternion Interpolation

回転姿勢を球面上で滑らかにつなぐ。

10 / 10

インタラクティブデモ

デモを準備しています…

球面線形補間

ドラッグで視点を回転、Ctrl(⌘)+ スクロールでズーム。タッチ操作は 2 本指です。

ひとことで

四元数(クォータニオン)で表した 2 つの回転の間を、最短の経路に沿って一定の角速度で補間する方法です。Spherical Linear intERPolation の略。キャラクターの向き、カメラの回転、アニメーションの姿勢ブレンドなど、「回転の途中」を求めるあらゆる場面で使われます。

ゲームでの使いどころ

  • 向きの切り替え:キャラクターや砲塔、宇宙船が目標の方向へ振り向く動き。
  • アニメーションのブレンド:歩きと走りのように 2 つのアニメーションを混ぜるとき、各ボーンの回転を slerp(または nlerp)します。
  • カメラの補間:カットシーンのキーフレーム間でカメラの向きを補間する。
  • 物理・ネットワーク:受信した姿勢の間を補間して、回転を滑らかに再生する。

しくみ

オイラー角(x, y, z 軸まわりの角度)をそれぞれ線形補間すると、3 つの回転が別々に進むため、先端が遠回りの経路を描き、途中で不自然なねじれが起きます(デモの赤い経路)。ジンバルロックの問題もあります。

単位四元数 qq は 4 次元の単位球面上の点として回転を表します。slerp はこの球面上の大円に沿って補間します。

slerp(q0,q1,t)=sin⁡((1−t) Ω)sin⁡Ω q0+sin⁡(t Ω)sin⁡Ω q1,cos⁡Ω=q0⋅q1\text{slerp}(q_0, q_1, t) = \frac{\sin\big((1 - t)\,\Omega\big)}{\sin\Omega}\,q_0 + \frac{\sin(t\,\Omega)}{\sin\Omega}\,q_1, \qquad \cos\Omega = q_0 \cdot q_1
  • 最短経路:qq と −q-q は同じ回転を表します。内積 q0⋅q1q_0 \cdot q_1 が負なら q1q_1 の符号を反転してから補間しないと、遠回り(360° − 角度)の回転になります。
  • 一定の角速度:tt を一定に進めると、回転角も一定に進みます。

nlerp(正規化線形補間)は、4 成分を線形補間してから正規化するだけの安価な近似です。経路は slerp と同じ大円ですが、角速度が一定ではなく、中央が速く端が遅くなります。2 つの回転の差が小さい場合(アニメーションのブレンドなど)はほぼ区別がつかず、計算も速く、複数の回転を平均するのにも向くため、実務ではよく使われます。

実装のポイント

  • 符号の反転:three.js の slerp は内部で内積の符号をチェックして最短経路を選びます。自作する場合は忘れずに。
  • 角度がほぼ 0 のとき:sin⁡Ω≈0\sin\Omega \approx 0 で割り算が不安定になるため、差が小さいときは nlerp に切り替えます。
  • 一定速度で振り向く:目標までの角度に関係なく「毎秒 180°」で回したいときは、rotateTowards(target, maxStep) のような最大角度制限つきの回転を使います。

つまずきやすい点

  • オイラー角のまま補間する:エディタの数値がオイラー角でも、補間は四元数に変換してから行います。
  • 180° 付近の回転:2 つの回転がちょうど反対向きに近いと、最短経路が一意に決まらず、わずかな差で回る方向が反転します。演出上どちら回りかを決めたい場合は中間のキーを追加します。
  • スケールや位置は別扱い:slerp は回転専用です。位置は Lerp、スケールは Lerp(または対数空間での補間)で別に補間します。

デモで試すこと

  1. 宇宙船の補間方法を切り替え、先端の経路を比べてください。赤(オイラー角)は大きく遠回りし、黄(nlerp)と水色(slerp)は同じ最短経路を通ります。
  2. 球面上の点は tt を 1/12 ずつ進めた位置です。水色の点だけが等間隔に並び、黄色は中央でまばら、端で密になっています。
  3. 「新しい目標の向き」を何度か押し、角度が大きいほど 3 つの違いが大きくなることを確認してください。

参考資料

The Book of Shaders — Shaping Functions ↗

分野全体の資料で、この項目を直接扱っているとは限りません。