メッシュ生成・変形

ボロノイ破砕

Voronoi Fracture

種点に近い領域で石やガラスを割る。

4 / 10

インタラクティブデモ

デモを準備しています…

ボロノイ破砕

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

ひとことで

物体の中に種点をばらまき、各種点に一番近い領域(ボロノイ領域)ごとに物体を切り分けて破片にする方法です。ボロノイ領域は必ず凸な多面体になるので、物理エンジンでそのまま剛体として扱えます。種点を衝撃の中心の近くに集めれば、中心ほど細かく、外側ほど大きく割れる、それらしい割れ方になります。

ゲームでの使いどころ

  • 壊れる壁・柱・床:銃撃や爆発で壁に穴が開き、破片が飛ぶ。
  • ガラス・氷・陶器:割れる窓や花瓶。ガラスは衝撃点から放射状に種点を並べると、ひびの入り方らしくなる。
  • プリフラクチャー:割れ方を前もって作っておき(事前破砕)、壊れた瞬間に 1 枚の物体を破片の集まりに差し替える。実行時の計算がほぼいらないので、多くのゲームで使われる(Unreal の Chaos、Houdini の Voronoi Fracture など)。
  • 岩の自動生成:大きな岩を割って、形のばらばらな石をたくさん作る。

しくみ

種点 sis_i のボロノイ領域は、「ほかのどの種点より sis_i に近い点」の集まりです。

Vi={ x∣∣x−si∣≤∣x−sj∣  (すべての j) }V_i = \{\, x \mid |x - s_i| \le |x - s_j| \ \ (\text{すべての } j) \,\}

sis_i と sjs_j から等しい距離の点は、2 点を結ぶ線分の垂直二等分面の上にあります。つまり ViV_i は、「sis_i 側の半空間」をすべての jj について重ねたもの(共通部分)です。

  1. 元の物体(ここでは箱)の多面体から始めます。
  2. ほかの種点 sjs_j ごとに、法線 n=(sj−si)/∣sj−si∣\mathbf{n} = (s_j - s_i)/|s_j - s_i| の平面で多面体を切り、sis_i 側だけを残します。
  3. 面を平面で切るには、各面の多角形をサザーランド・ホッジマン法で切り、切り口にできた点を集めて新しい面(割れ口)にします。

遠い種点との二等分面は領域に届かないので、近い順に調べ、「領域のいちばん遠い点までの距離」が「種点までの距離の半分」より小さくなったら打ち切れます。

実装のポイント

  • 割れ口に別の素材:切り口の面に印を付けて、外側の面とは別のマテリアル(石の中身、ガラスの断面)にすると、割れた感じが強く出ます。
  • 凹んだ物体:ボロノイ領域は凸ですが、元の物体が凹んでいる場合(L 字の壁など)は、凸な部分に分けてから割るか、メッシュのブーリアン演算で切り取ります。
  • 全部を飛ばさない:衝撃の弱い破片は元の場所に残すと、穴の開いた壁になります。破片どうしを「接着」しておき、一定以上の力で外れるようにする方法もあります。
  • 破片の後始末:破片が増えすぎると重くなるので、小さな破片は時間とともに消す、オブジェクトプールで使い回す、などの工夫をします。

つまずきやすい点

  • 規則正しすぎる割れ方:種点を一様にばらまくと、どこも同じ大きさの破片になり、不自然です。衝撃点の近くに集めたり、ひびの方向に伸ばしたりします。
  • 極端に小さい破片:種点が近すぎると、とても小さい破片ができ、物理が不安定になります。種点の間隔に下限を設けます(ポアソンディスク分布など)。
  • 切り口の点の並び:切り口の点を角度順に並べ忘れると、面がねじれて描かれます。平面の法線の周りで反時計回りに並べます。

デモで試すこと

  1. 壁をクリックすると、その場所を撃ちます。当たった場所の周りだけが細かく砕けて飛び、外側は壁に残って穴が開きます。
  2. 「分解表示」を動かすと、割れる前の切り分け方(ボロノイ領域)が見えます。当たった場所の近くほど破片が小さいことを確かめてください。
  3. 「当たった場所への集中」を 0 にすると、どこも同じくらいの大きさの破片になります。
  4. 「壁に残す破片」を 0 にすると、すべての破片が崩れ落ちます。「素材」をガラスにすると、透けた破片と明るい割れ口になります。

参考資料

libigl Tutorial ↗

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