曲線・補間

弧長パラメータ化

Arc-Length Parameterization

曲線のパラメータと弧長を対応させ、等速移動や等間隔配置に使う。

6 / 10

インタラクティブデモ

デモを準備しています…

弧長パラメータ化

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

ひとことで

曲線のパラメータ tt と「曲線に沿って進んだ距離(弧長)ss」の対応表を作り、距離から tt を逆引きする手法です。ほとんどの曲線は tt を一定に増やしても一定の速さでは進まないため、「一定速度で動かす」「等間隔に物を並べる」ときに欠かせません。

ゲームでの使いどころ

  • 一定速度の移動:レール上のカメラ、乗り物、弾、パトロールする敵。速度むらはプレイヤーにすぐ気づかれます。
  • 等間隔の配置:道路の白線、柵の杭、街灯、ロープの結び目などを曲線に沿って等間隔に置く。
  • 進捗の表示:「コース全体の何 % まで来たか」を距離で計算するレースの順位判定やミニマップ。
  • テクスチャの貼り付け:曲線に沿ったリボンや道路メッシュに、伸び縮みのない UV を与える。

しくみ

弧長は、速度ベクトルの大きさを積分したものです。

s(t)=∫0t∥dPdτ∥dτs(t) = \int_0^t \left\lVert \frac{d\mathbf{P}}{d\tau} \right\rVert d\tau

ほとんどの曲線でこの積分は解析的に解けないため、実用では数値的な表を作ります。

  1. tt を NN 等分し、各点 P(tk)\mathbf{P}(t_k) を求める。
  2. 隣り合う点の距離を累積して sks_k の表を作る(折れ線近似)。
  3. 距離 ss が与えられたら、表を二分探索して sk≤s<sk+1s_k \le s < s_{k+1} となる kk を見つけ、区間内を線形補間して tt を得る。

デモ右下のグラフは s(t)s(t)(全長で正規化)です。等速なら点線の直線になるはずが、実際には曲がっています。傾きが緩い区間は tt が進んでも距離が伸びない、つまり遅い区間です。

実装のポイント

  • 表は形が変わったときだけ作り直す:毎フレーム作る必要はありません。制御点を編集したときに再計算します。
  • three.js:Curve.getPointAt(u) と getSpacedPoints(n) はこの表(getLengths)を内部で使っています。
  • 精度の目安:分割数はカーブの急さ次第ですが、ゲームでは 100〜200 程度で十分なことがほとんどです。ニュートン法で tt を補正するとさらに精度を上げられます。

つまずきやすい点

  • 分割数が少ないと速度むらが残る:表の区間内は直線とみなしているので、急カーブでは誤差が出ます。デモで分割数を 3〜5 にすると、水色の車もぎくしゃくします。
  • 閉じた曲線の継ぎ目:ループするコースでは、s=Ls = L(全長)と s=0s = 0 が同じ点になるよう、剰余の扱いに注意します。
  • 速度が可変の場合:加減速したいなら、距離 ss 自体を時間の関数(イージングや物理)で動かし、その ss から tt を引きます。「速さの設計」と「形の設計」を分離できるのがこの手法の利点です。

デモで試すこと

  1. 赤い車(tt を一定に増やす)は、通過点が詰まった左上のカーブで遅くなり、間隔の広い長い直線で急加速します。水色の車(弧長)は常に同じ速さです。
  2. 「等間隔の目盛り」の赤い点は tt を等間隔にした位置、水色は距離を等間隔にした位置です。赤は偏り、水色は均等に並びます。
  3. 「弧長テーブルの分割数」を 3 にすると、表が粗すぎて水色の車にも速度むらが出ます。

参考資料

The Book of Shaders — Shaping Functions ↗

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