距離場・暗黙形状

CSG

Constructive Solid Geometry

形の和、差、交差で穴やくり抜きを作る。

3 / 10

インタラクティブデモ

デモを準備しています…

CSG

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

ひとことで

箱・球・円柱のような単純な形を、和(くっつける)・差(くり抜く)・交差(共通部分だけ残す)で組み合わせて複雑な形を作る方法です。符号付き距離場で形を表していると、これらの操作は距離の最小値と最大値だけで書けてしまいます。

A∪B:min⁡(dA,dB)A−B:max⁡(dA,−dB)A∩B:max⁡(dA,dB)\begin{aligned} A \cup B &: \min(d_A, d_B)\\ A - B &: \max(d_A, -d_B)\\ A \cap B &: \max(d_A, d_B) \end{aligned}

ゲームでの使いどころ

  • レベルの組み立て:Quake や Unreal のブラシ(BSP)エディタは、箱を足したり引いたりして部屋や通路を作る CSG の考え方で作られていました。
  • 破壊・掘削:壁に弾痕や穴を開ける、地面を掘る、トンネルを開ける。距離場の地形なら、球を差し引くだけで形が変わります。
  • 造形ゲーム・プロシージャルモデル:『Dreams』や『Claybook』のように、プレイヤーが形を足し引きして造形する。
  • レベル内のギミック:扉の開口部、窓、ドーナツ状の足場などを、簡単な形の組み合わせで作る。

しくみ

距離場で考えると、各操作は次のように理解できます。

  • 和(min):どちらかの形に近ければその距離。どちらかの内側(負)なら結果も内側。
  • 交差(max):両方の内側にあるときだけ負になる。遠いほうの距離を取るので、外側の値は「近すぎる」ことはない。
  • 差(max と符号反転):−dB-d_B は「B の外側を内側とみなした形」です。それと A の交差が「A から B を引いた形」になります。削られてできた新しい面は B の表面なので、デモでは B の色で塗られます。

操作を木構造(CSG 木)に組み合わせれば、デモの機械部品のように「箱と球の交差から、3 本の円柱を引く」といった形も 1 つの式で表せます。

メッシュの CSG との違い:ポリゴンメッシュ同士のブール演算は、面同士の交線を求めて切り貼りする難しい計算で、数値誤差で穴が開くこともあります。距離場なら min と max だけなので確実で、形を動かしながらリアルタイムに組み替えることもできます。

実装のポイント

  • 色や材質の割り当て:min や max でどちらの値が選ばれたかを覚えておけば、面ごとに材質を変えられます(差の面を焼け焦げた色にする、など)。
  • ゲームロジック側の対応:見た目の穴に合わせて当たり判定も変える必要があります。距離場で当たり判定をしていれば同じ式を使えますが、物理エンジンのメッシュ形状を使う場合は、形を作り直すか、マーチングキューブなどでメッシュ化します。
  • 多数の穴:穴の数だけ距離の評価が増えます。数が多い場合は、穴を空間ハッシュで管理して近くのものだけ評価したり、ボクセルに焼き込んだりします。

つまずきやすい点

  • 差と交差の結果は厳密な距離ではない:max を取った結果は、内側・角の近くで正確な距離より小さく(保守的に)なることがあります。描画には問題ありませんが、距離の値そのものを使う効果(ソフトシャドウの柔らかさなど)はわずかにずれます。
  • 薄い壁の突き抜け:差で壁を薄く削った部分は、スフィアトレーシングの許容誤差より薄いと穴が開いて見えることがあります。
  • 角が鋭すぎる:min と max は角をそのまま残すので、機械的な形には向きますが、有機的な形にはスムーズユニオンが向いています。

デモで試すこと

  1. 「和」「差」「交差」を切り替え、B(球)が動くにつれて形がどう変わるかを見てください。線で表示された元の箱と球との関係が分かります。
  2. 「差」では、削られた面が球の形(赤)になっていることを確認してください。
  3. 「CSG 木(部品)」では、箱 ∩ 球 − 3 本の円柱という 1 つの式で、機械部品のような形ができています。
  4. 「壊せる壁」で壁をクリックすると、その位置の球が差し引かれて穴が開きます。メッシュを作り直さずに、何度でも削れます。

参考資料

Unreal Engine Mesh Distance Fields ↗

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