Curves & interpolation

Catmull–Rom Spline

カトマル・ロムスプライン

指定点を通る滑らかな経路を作る。

3 / 10

Interactive demo

Preparing the demo…

Catmull–Rom Spline

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

並べた通過点をすべて通る滑らかな曲線を、追加の制御ハンドルなしで作れるスプラインです。各点での接線を「前後の点を結ぶ向き」から自動で決めるので、配置するのは通過点だけ。カメラレール、パトロール経路、レースの走行ラインなど、「ここを通ってほしい」という指定が明確な場面の定番です。

ゲームでの使いどころ

  • カメラの移動経路:カットシーンやアトラクションのように、見せたい位置を順に通るカメラワーク。デモ右上はレール上のカメラから見た映像です。
  • 敵の巡回ルート:ウェイポイントを置くだけで、角で急旋回しない自然な移動経路になります。
  • レースゲームのライン:AI が走るレーシングラインや、コース上のチェックポイントをつなぐ曲線。
  • ネットワーク補間:過去数フレーム分の受信位置を通る曲線で、他プレイヤーの動きを滑らかに再生します。

しくみ

区間 P1→P2\mathbf{P}_1 \to \mathbf{P}_2 を描くとき、前後の点 P0,P3\mathbf{P}_0, \mathbf{P}_3 を使って両端の接線を決め、エルミート曲線として補間します。一様な場合の接線は次のとおりです。

T1=P2−P02,T2=P3−P12\mathbf{T}_1 = \frac{\mathbf{P}_2 - \mathbf{P}_0}{2}, \qquad \mathbf{T}_2 = \frac{\mathbf{P}_3 - \mathbf{P}_1}{2}

ただし、通過点の間隔が不均一だと、一様パラメータ化では曲線が行き過ぎて尖り(カスプ)や小さなループができます。そこで、点どうしの距離に応じてパラメータの間隔を変えます。

ti+1=ti+∥Pi+1−Pi∥αt_{i+1} = t_i + \lVert \mathbf{P}_{i+1} - \mathbf{P}_i \rVert^{\alpha}
α\alpha名前性質
0一様(uniform)計算が単純。間隔が偏るとループやカスプが出る
0.5求心(centripetal)区間内に自己交差やカスプが生じないことが証明されている
1弦長(chordal)大きく膨らみやすいが、曲率の変化はなだらか

実用上は求心(α=0.5\alpha = 0.5)が第一候補です。three.js の CatmullRomCurve3 も curveType: "centripetal" で使えます。

実装のポイント

  • 始点と終点の扱い:開いた曲線では最初と最後の区間に「前後の点」がありません。端の点を複製するか、延長した仮想点を置きます。
  • 注視点は別に持つ:カメラの向きを進行方向にすると、急なカーブで画面が大きく振られます。見せたい対象を別の曲線や固定点で持つと安定します(デモの「カメラの向き」)。
  • 速度は弧長で:点の間隔が違うと、tt を一定に進めたときの速さが区間ごとに変わります。getPointAt のような弧長ベースの関数を使います。

つまずきやすい点

  • 高さ方向の揺れ:3D の通過点の高さを少しずつ変えると、区間ごとに上下のうねりが出ます。カメラ酔いの原因になるので、高さは別に滑らかに補間するのも手です。
  • 局所制御はほぼ:1 点を動かすと、その点をはさむ前後 2 区間ずつ(計 4 区間)が変わります。B スプラインほど局所的ではありませんが、実用上は十分です。
  • 2 階微分は連続しない:つなぎ目で曲率が不連続になるため、非常に速い移動では加速度の変化が感じられることがあります。

デモで試すこと

  1. 「パラメータ化」を一様にすると、間隔の詰まった通過点 2・3 の付近に小さなループができます。求心に戻すとループが消えます。
  2. 通過点をドラッグしてステージの近くを通るようにすると、右上のカメラ映像が迫力のあるアングルに変わります。
  3. 「カメラの向き」を進行方向にすると、カーブで画面が振られる様子が分かります。

References

The Book of Shaders — Shaping Functions ↗

A general reference for this subcategory.