PMXの剛体とジョイントの中身|衝突グループ・ばね・回転の順番

髪やスカートの揺れは、PMXに書かれた剛体(当たり判定のある形)とジョイント(剛体どうしをつなぐばね)で決まります。中身を実物で数えると、three.jsでの扱いと食い違う点が1つ見つかりました。剛体の回転の読み方です。

最終更新: 2026-10-07 · 実PMX 3体(人物A・アリシア・ステージ)の剛体とジョイントを three.js 同梱のパーサで読んで数え、MMDPhysics(r171)のソースで扱いを確認。回転の順番は、カプセル形の剛体の軸と骨の向きの角度で比べた

このサイトの再生は、2026-10-07から剛体とジョイントの回転を YXZ の順で読んでいます(読み込んだ直後に、three.js が読む XYZ の角度へ書き換えています)。

剛体に書かれているもの

項目中身
形球・箱・カプセルの3種類と、その大きさ
種類0 = ボーンに付いていく / 1 = 物理で動く / 2 = 物理で動くが、位置はボーンに合わせる
グループ0〜15の番号。自分がどのグループか
衝突するグループ16ビット。どのグループと当たるか(下で説明)
質量・移動減衰・回転減衰・反発・摩擦揺れ方と、当たったときの跳ね方
位置・回転つながるボーンからではなく、モデルの原点からの位置と向き
人物Aアリシア
剛体141(球8・箱67・カプセル66)79(球4・箱1・カプセル74)
種類 0 / 1 / 239 / 50 / 5226 / 0 / 53
ジョイント23653
反発全部0全部0
摩擦0が94、0.5が47全部0.5

ステージ(15ボーン)には剛体もジョイントもありませんでした。アリシアは物理で動く剛体が全部「種類2」で、位置はボーンに合わせ、回転だけを物理に任せる作りです。

衝突するグループは「立っているビットと当たる」

16ビットの値は、実物では fffe・fffa・ffdb のように、ほとんどのビットが立った形でした(アリシアは79件すべてがこの形)。three.js の MMDPhysics は、自分のグループを 1 << 番号、この値をそのまま「衝突する相手」の条件として物理エンジン(Bullet)に渡します。立っているビットのグループとは当たり、落ちているビットのグループとは当たりません。

たとえばグループ0の剛体の値が fffe なら、0番のビットだけが落ちているので、同じグループ0どうしでは当たりません。髪の剛体どうしが絡まないようにする、よくある設定です。人物Aには値が 0(どのグループとも当たらない)の剛体が1つありました。

ジョイントに書かれているもの

ジョイントは2つの剛体をつなぎ、動ける範囲(移動の下限・上限、回転の下限・上限)と、ばねの強さ(移動3軸・回転3軸)を持ちます。実物のジョイントは全部「6自由度ばね」の種類でした。

人物A(236)アリシア(53)
移動の範囲が0〜0(動かない)17653
回転の範囲が全部0(固定)20
移動のばねが0でない160
回転のばねが0でない4022
  • three.js は Bullet の btGeneric6DofSpringConstraint を使い、ばねが0でない軸だけばねを有効にします
  • MMDに近い動きにするための設定(setParam)は、ソースのコメントでは「改造した Ammo.js にしか無い」とされています。このサイトが配っている Ammo.js には入っていたので、効いています
  • 剛体の種類0はボーンの動きをそのまま写し、1はボーンの回転と位置を物理の結果で上書きし、2は回転だけを上書きして位置はボーンに戻します

剛体の回転は YXZ の順で読むと合う

剛体とジョイントの回転は、3つの角度(オイラー角)で書かれています。オイラー角は「どの軸から回すか」で結果が変わりますが、PMXには順番が書かれていません。three.js の MMDPhysics は、three.js の既定の XYZ の順で読んでいます。

そこで、カプセル形の剛体を使って確かめました。カプセルは髪やスカートの骨(ボーンから、つながる先のボーンへの向き)に沿わせて置くのが普通なので、正しい順で読めばカプセルの軸が骨の向きに揃うはずです。回転が2軸以上にまたがるカプセル(1軸だけなら順番は関係ない)で、軸と骨の向きの角度を6通りの順番で測りました。

読む順番人物A(25本)アリシア(30本)
XYZ(three.jsの既定)中央値2.00°・5°以内16本中央値2.54°・5°以内24本
YXZ中央値1.03°・5°以内21本中央値1.18°・5°以内30本
ZXY中央値2.37°・5°以内18本中央値2.61°・5°以内24本
ZYX中央値2.00°・5°以内18本中央値2.39°・5°以内24本
YZX中央値2.00°・5°以内18本中央値2.80°・5°以内22本
XZY中央値2.69°・5°以内18本中央値4.13°・5°以内16本

2体とも YXZ がいちばんよく合い、アリシアは30本すべてが5°以内に収まりました。回転が2軸以上にまたがる剛体は人物Aで141中95、アリシアで79中48あり、ジョイントは人物Aで236中198あります。読む順番が違うと、これらの向きが少しずつずれます。

このサイトでは、読み込んだ直後に「YXZ で表された回転」を「同じ回転を XYZ で表した角度」へ書き換えてから three.js に渡しています(回転そのものは変わらず、three.js のコードにも手を入れていません)。

見た目の違いは小さく、物理の揺らぎと区別できませんでした。 物理を入れたまま4秒置いて、物理で動くボーンの位置を直す前と後で比べると、ずれは最大0.23ユニット(人物Aのスカート)・0.06ユニット(アリシアの髪)でした。ところが同じ設定で2回動かしただけでも0.14・0.03ずれます。直したのは剛体の置き方が骨に合うようになった点で、揺れ方がどれだけ変わるかは測れていません。