物理演算設計編

振り子演算器の値仕様の確認

前回のアドカレではLive2Dの物理演算が振り子演算器によるパラメーター変換する仕組みという話をしました。
ここではその振り子演算器の振り子の設定値、出力値が現実の振り子だとどれくらいの値になるか調べていきます。
これは物理演算の設計に必要な情報になっていきます。

●振り子の長さ

振り子は振れ角が非常に小さい時、周期は紐の長さによって決まる等時性を持っています。この原理を逆に応用すれば現実空間の振り子周期とLive2D物理演算内の同周期時の紐の長さ設定をみることにより、物理演算設定内の紐の長さがどういう単位であるか想定することができます。
引いてはそこから各単位を割り出すことにより物理演算の自然さを出すときにキャラクター設定から割り出した大体のサイズ感からおおよその値を推定することが見込めます。

画像1

上の画像は長さ10.0、揺れやすさ1.0、反応速度1.0、収束の速さ1.0の振り子を移動によって30へX移動入力に関してステップで動かしたときの角度について、60FPSでベイク計算させて出力したグラフです。
プラス側の頂点がそれぞれ34Frame、74Frame、114Frameになっています。
一周期は0.66秒になるので周期計算の方程式に当てはめて実際の長さを考えてみます。

Time = 2 * PI * sqrt( Long / Gravity )
0.66s = 2 * PI * sqrt( Long / 9.80665m/ss )
0.66s / 2 / PI = sqrt(Long /9.80665m/ss )
0.10504s = sqrt( Long / 9.80665m/ss )
0.10504s * 0.10504s / 9.80665m/ss = Long
長さ10.0 = Long = 0.1082m = 10.82cm

なのでCubism 4の物理演算における長さ1は大体1.08センチメートルということになります。

入力移動量

紐の長さが判明すると相対的に移動量を把握できます。

画像2

上の図は角度Xを+30へ振り切らせた状態の振り子の設定部分です。
長さが1:1なので位置Xの値は振り子の長さと同じく1=1.08cm換算です。

入力角度

角度はラジアン表記と度数表記の2タイプがあり、sincosの際にはどちらで処理されるかはよく確認しなければなりません。

var totalAngle = 0.0f;
var totalTranslation = Vector2.zero;

for (var i = 0; i < Input.Length; ++i)
{
   var weight = Input[i].Weight / CubismPhysics.MaximumWeight;

   if (Input[i].Source == null)
   {
       Input[i].Source = Rig.Controller.Parameters.FindById(Input[i].SourceId);
   }

   var parameter = Input[i].Source;
   Input[i].GetNormalizedParameterValue(
       ref totalTranslation,
       ref totalAngle,
       parameter,
       Normalization,
       weight
       );
}

var radAngle = CubismPhysicsMath.DegreesToRadian(-totalAngle); // ★

totalTranslation.x = (totalTranslation.x * Mathf.Cos(radAngle) - totalTranslation.y * Mathf.Sin(radAngle));
totalTranslation.y = (totalTranslation.x * Mathf.Sin(radAngle) + totalTranslation.y * Mathf.Cos(radAngle));

この処理部分をみると度数表記からラジアン表記に変換してから三角関数で使用しているので表記は度数表記であることがわかります。

画像3

実際に角度を-90~90で動かしても90度で直角に回転することが確認できます。

入力Xと入力Angleの組み合わせ

入力Xと入力Angleが同時に適用することができます。このときにはAngleが先に適用されて、その後入力Xが適用されます。入力Xの移動がナナメになる形に表現されます。

出力角度

出力側の角度情報はどうでしょうか?
まずはソースコードの方を見てみます。

private float GetOutputAngle(
   Vector2 translation,
   CubismParameter parameter,
   CubismPhysicsParticle[] particles,
   int particleIndex,
   Vector2 gravity
)
{
   var parentGravity = Vector2.zero;

   if (CubismPhysics.UseAngleCorrection)
   {
       if (particleIndex < 2)
       {
           parentGravity = gravity;
           parentGravity.y *= -1.0f;
       }
       else
       {
           parentGravity = particles[particleIndex - 1].Position - particles[particleIndex - 2].Position;
       }
   }
   else
   {
       parentGravity = gravity;
       parentGravity.y *= -1.0f;
   }

   // ★
   var outputValue = CubismPhysicsMath.DirectionToRadian(parentGravity, translation);

   if (IsInverted)
   {
       outputValue *= -1.0f;
   }
   return outputValue;
}

これをみるとどうやらラジアンで書き出されたあと変換されていないのでラジアンで出力されているようです。値をパラメータに変換して確認してみましょう。

画像4

画像5

入力を角度入力だけにして出力は影響度100%倍率1にしているので入力回転は安定するとそのまま出力の角度と一致するはずです。
Radでしめされた-4~4の間のパラメーターはちょうど-π~πの間で推移しているのに対してDegreeの-180~180の表記ではほんのごく一部しか揺れていないのを確認できます。
このことからもラジアンで出力されていることが確認できます。

出力角度のループ

出力の回転角度がラジアンで出力されるのはわかりましたが回転時の値の範囲についても確認しておきます。
これに関しては先程スケールの確認を行ったサンプルがちょうど一回転しているのことから確認ができます。


π以上に出力を上げると-πの方に値がジャンプしますね。このように回転系のパラメータは-πからπの範囲内に収まるので、振り子が一回転する構成でモデル側がきれいな一回転になるように作成しておかないと「あばれる」「飛ぶ」などの現象に繋がります。


物理演算の入力と出力の組み合わせ

物理演算設定エディタで使用できる入力の位置Xと角度の特性の違いとその使い方について述べていきます。

●入力Xと出力Angle
この組み合わせでは入力Xが止まった値に関わらず、必ず振り子は重力方向に収束した状態になります。入力の変化量に対して揺れが発生します。基本的な揺れモノはこれを指定しておけば大丈夫です。

●入力Angleと出力Angle
この組み合わせでは入力の角度入力出力角度を合わせようと動きます。収束は重力方向と入力量によって変化します。入力と出力の差によって揺れが作り出されます。重力方向が一定と仮定すると振り子によるパラメータの遅延処理のように使用できます。

●入力Yや出力XYについて
physics3.jsonへ記述して物理演算設定へ差戻すことによりこれらの要素を使用できるようになりますが、利用シーンはかなり限られます。
入力Yは振り子を縦に動かす操作になりますが静止状態では振り子が振れる横方向への力の分解が行われずに動作しない現象が発生します。振り子が揺れている状態であれば揺れ方向に応じた力を発生しますが揺れている方向によって結果が異なるのできれいな揺れに使用するには難しい挙動になります。

振り子Y

出力XYに関しては上段の振り子の位置との差によって計算されるため、値としてはAngleからくる値にSinCosで変換された値といった感じの値になります。物理演算だけでどうしてもSinCos掛けたいのならば効果はありそうですが拡張補完での変換も可能なためAngleで十分処理できる内容になります。

物理演算の設計

この章ではきれいで安定し、修正しやすい物理演算を構成するために事前調査、モデリングでのテクニックを示して行きます。

事前調査編

・物理演算FPSの指定
公式にも書かれている通りに物理演算の挙動は実行FPSに依存します。
FPSを合わせておかないと利用先にモデルを組み込んだ際に動作ニュアンスが一致せず調整に何度もEditorと行き来することになります。
リモートの受注案件だとやり取り回数が増えるので事前に確認しましょう。

・モデルのスケールの想定
ネックレスやイヤリングなどある程度重さがあり、空気抵抗が無視できる程度の振り子運動をするような小物がある場合、
キャラのおおよその身長を定めてから身長に沿った各寸法を調べておくと振り子運動の設定の際に紐の長さの要素が固定され、他の設定が定めやすくなります。

モデリング編

・パラメータ設計、揺れ幅
モデリングを始める前に物理演算部位が実装時にどれくらい揺れるときれいか、細かくイメージしておきましょう。小さい揺れであればその動きの1.5倍の動きはモデリングしておくことをオススメします。
30度くらいにゆったり揺れるならば45度くらいまで、60度くらい大きく揺れるならば90度、それ以上であれば180度まで作成して円環にしておくと、揺れが思ったより大きく出たときにモデルや物理演算の設定の作り直しという事態を避けられます。

・モデル側の等速設計
物理演算が関係する部分に限らない話ですが、パラメータのなかで3点以上キーが打たれる状況のときにキー間の移動量、方向に変質があるとその境がパタ付きなって目につくようになります。物理演算になるとこれがより一層目立ちます。言い換えるとキーフォーム間の変化ベクトルは隣接する変化ベクトルと大きく変化するとその微分量が目につくという形になります。
Cubism3の頃には実際に動かして動きをみて確認するしか手段がなかったのですがCubism4からはベータ機能ではありますがオニオンスキンの機能によって軌道変化については明瞭に視覚化できるようになりました。

画像6

修正に関しては動きを詰めきったあとでは拡張補完を使って変化加速量を分散化してやるのが良いと思います。

画像7

・物理演算モデルと表示角の一致
振り子状の揺れモノに関しては見た目の揺れ方と振り子の揺れ方を一致させておいたほうが調整項目が減り、揺れ方を調整しやすくなります。具体的にはパラメータの値を度数表記とみてモデリングを行い、物理演算では倍率を固定しておく操作になります。

次回予告

物理演算設定の値の決め方をやろうと思ったのですが分量が多くなりすぎたのと調査で長くなりそうなので次回へ分割します。
早めにと思っていますがiPhoneXRでのモデル制御で遊びたいのでしばらく時間が空きます。

この記事が気に入ったらサポートをしてみませんか?