メッシュ生成・変形

ARAP変形

As-Rigid-As-Possible Deformation

局所形状を保ちながらメッシュを変形する。

9 / 10

インタラクティブデモ

デモを準備しています…

ARAP変形

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

ひとことで

メッシュの一部をつかんで動かしたとき、各部分がなるべく「回転しただけ」に近い形を保つように、全体の頂点の位置を決める変形の方法です。単純に周りの頂点との位置関係を保とうとすると、腕を回したときに腕が伸びたりつぶれたりしますが、ARAP は各部分の回転を許すので、太さや形を保ったまま自然に曲がります。骨を入れなくても、柔らかい人形のように動かせます。

ゲームでの使いどころ

  • 2D キャラクターのメッシュ変形:イラストを三角形の網に分け、手足の点をつかんで動かすだけでポーズを付ける(Spine や Live2D のような表現、パペットアニメーション)。
  • エディタでの形の調整:モデルの一部を引っ張って、周りを自然に追従させる。
  • 柔らかい物体:スライムやゼリーのように、ぶつかって変形しても元の形を保とうとする物体。物理版はシェイプマッチングと考え方が近い。
  • リターゲット・補正:骨の入った変形の結果を、形を保つように整える。

しくみ

元の頂点の位置を p\mathbf{p}、変形後を p′\mathbf{p}' とし、各頂点 ii に回転 RiR_i を持たせます。最小にするエネルギーは、

E=∑i∑j∈N(i)wij ∥(pi′−pj′)−Ri(pi−pj)∥2E = \sum_i \sum_{j \in N(i)} w_{ij}\, \big\| (\mathbf{p}'_i - \mathbf{p}'_j) - R_i (\mathbf{p}_i - \mathbf{p}_j) \big\|^2

つまり「今の辺」が「元の辺を回したもの」にどれだけ近いかです。wijw_{ij} は辺の重み(余接重み)です。これを 2 つの手順の交互のくり返しで解きます(Sorkine & Alexa 2007)。

  1. 局所の一歩:今の位置を固定し、各頂点で最もよく合う回転 RiR_i を求めます。2 次元では、S=∑jwij eijeij′⊤S = \sum_j w_{ij}\, \mathbf{e}_{ij} \mathbf{e}'^\top_{ij} から角度 θ=atan2⁡(S01−S10, S00+S11)\theta = \operatorname{atan2}(S_{01} - S_{10},\ S_{00} + S_{11}) で一発で求まります(3 次元では特異値分解)。
  2. 全体の一歩:回転を固定すると、エネルギーは位置の 2 次式になるので、連立一次方程式 L p′=bL\,\mathbf{p}' = \mathbf{b} を解きます。
bi=∑jwij2(Ri+Rj)(pi−pj)\mathbf{b}_i = \sum_{j} \frac{w_{ij}}{2} (R_i + R_j)(\mathbf{p}_i - \mathbf{p}_j)

つかんだ点の位置は固定値として右辺に移します。LL は変わらないので、前もって分解(コレスキー分解)しておけば、毎回の解き直しは速くなります。

実装のポイント

  • 前のフレームの結果から始める:毎フレーム、前の結果を初期値にして数回くり返すだけで、ドラッグに滑らかについてきます。
  • 余接重み:均一な重みだと、三角形の大きさや形のばらつきが変形のゆがみとして出ます。辺の向かいの角から決める余接重みを使います(負になる場合は小さな正の値に切り上げます)。
  • 固定点の選び方:足などを固定し、手や頭をつかむ点にします。1 点だけを固定すると、周りが引っ張られてとがるので、小さな範囲の頂点をまとめて固定します。
  • 分解の使い回し:つかむ点の組み合わせが変わらない間は、LL の分解を使い回せます。点を追加・削除したときだけ分解し直します。

つまずきやすい点

  • くり返しが足りない:局所と全体の一歩を交互に行う方法は、少しずつ正解に近づきます。回数が少ないと、伸び縮みが残ります。
  • 大きく動かすと反転する:つかんだ点を極端に動かすと、三角形が裏返ることがあります。
  • メッシュの細かさ:三角形が粗すぎると、曲がる所がかくかくします。曲げたい所(関節のあたり)は細かくしておきます。

デモで試すこと

  1. 両手と頭が自動で動き、人形の腕が太さを保ったまま曲がります。黄色い点をドラッグすると、自分で動かせます(自動の動きは止まります)。
  2. 「変形の方法」を「回転を考えない」にすると、同じ動きでも腕が細く引き伸ばされ、赤(伸び)や青(縮み)の三角形が増えます。
  3. 「伸び縮みを色で表示」で、ARAP ではほとんど色が付かないことを確かめてください。色が付くのは、どうしても伸び縮みが必要な所だけです。
  4. 「1 フレームのくり返し」を 1 にすると、ドラッグに対する追従が遅れ、伸び縮みが残りやすくなります。

参考資料

libigl Tutorial ↗

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