■PMX仕様 (by 極北P)

PMDエディタ0.1.0.1以降より対応されている PMX形式(2.0以降)のデータフォーマット及び動作仕様です。


■使用条件(念のため)

管理はこちらで一括して行います。勝手な改変についてはNG、というかこちらでは一切対応しません。
各アプリケーションなどでのフォーマットの利用については、非営利であれば自己責任で。
できれば出所(MikuMikuDance／PMDエディタ／VPVPwikiなど)の記載をお願い致します。

(ないと思いますが)営利目的であれば応相談

※特に連絡先は取り決めておりませんが、みくだん(http://mikudan.blog120.fc2.com/)の管理人さん宛でおそらく大丈夫かと？
※フォーマット公開についてもこちらで管理するかと思われます。

お約束として、
営利／非営利にかかわらず、データフォーマット及び周辺ツールの使用に関して損害他一切の責任を負いませんのでよろしくお願い致します。


■バージョン管理と互換性

PMXの互換性はverで厳密に管理します。
非対応verの場合はすみやかに処理を中断してください。

尚、PMX1.0は非公開となります(先頭キーやヘッダ構造も多少異なるので、間違って読み込まないように)

現在の最新verは 2.0 となります。


■データフォーマット

形式 : バイナリのみ
バイト順 : リトルエンディアン
テキストエンコード : ユニコード(UTF16LE) 及び UTF8 の選択方式

○基本データ型とバイトサイズ

[C#/HLSL方式+] : バイトサイズ  | [C方式]

byte	: 1  - 符号なし  | unsigned char
sbyte	: 1  - 符号あり  | char

ushort	: 2  - 符号なし  | unsigned short
short	: 2  - 符号あり  | short

uint	: 4  - 符号なし  | unsigned int
int	: 4  - 符号あり  | int (32bit固定)

float	: 4  - 単精度実数 | float

float2	: 8  (4 * 2)  | Vector2 - X,Y(or U,V) の順
float3	: 12 (4 * 3)  | Vector3 - X,Y,Z(or R,G,B) の順
float4	: 16 (4 * 4)  | Vector4 - X,Y,Z,W(or R,G,B,A) の順

TextBuf	: 可変 | 4 + バッファ長

bitFlag : 1 | 1byte につき 8フラグ bit-0:OFF 1:ON


○TextBuf (テキストバッファ)
int : バイト長
byte * バイト長 : byte列 エンコード形式はPMXヘッダに記載

※バッファサイズは 4 + n [byte]

※PMDエディタ内のエンコード処理は、

→バイト列
byte[] buf = Encoding.Unicode.GetBytes(str);	// UTF16
byte[] buf = Encoding.UTF8.GetBytes(str);	// UTF8

→文字列
string str = Encoding.Unicode.GetString(buf, 0, buf.Length);	// UTF16
string str = Encoding.UTF8.GetString(buf, 0, buf.Length);	// UTF8

これだけです。
変換はすべてライブラリ(.NET Framework)にまかせているので、内部で発生する問題などには対応できないかと思われます。
※サロゲートペアの取り扱いについてなど詳細不明


○Index参照のバイトサイズ
各データのIndex参照値は データの総数に対して 1,2,4バイトで最適化。

対象は、

頂点
テクスチャ(内部テーブル管理)
材質
ボーン
モーフ
剛体

の各項目。参照している側のIndex値が可変サイズになります。

各データサイズについてはPMXヘッダに記載されます。

※データ数の範囲とバイトサイズの関係 - 頂点 8／16bitのみ符号なしとして扱います。

・頂点 - 符号なし
[バイトサイズ] : 頂点数範囲
1 : 0 〜 255
2 : 256 〜 65535
4 : 65536 〜 2147483647  ※符号ありになるので注意


・ボーン／テクスチャ／材質／モーフ／剛体 - 符号あり
[バイトサイズ] : データ数範囲
1 : 0 〜 127
2 : 128 〜 32767
4 : 32768 〜 2147483647

※ボーンや剛体などは -1を非参照値として扱います。材質は材質モーフにより-1:全材質とみなします。
※PMDエディタ内ではIndex参照は基本的にすべて int(符号あり32bit) で管理しています。


●PMXのデータ構造概要

-先頭-

PMXヘッダ
-
モデル情報
-
頂点数 [int]
頂点 * 頂点数
-
面数 [int]
参照頂点Index * 面数
-
テクスチャ数 [int]
テクスチャパス * テクスチャ数
-
材質数 [int]
材質 * 材質数
-
ボーン数 [int]
ボーン * ボーン数
-
モーフ数 [int]
モーフ * モーフ数
-
表示枠数 [int]
表示枠 * 表示枠数
-
剛体数 [int]
剛体 * 剛体数
-
Joint数 [int]
Joint * Joint数

-終了-


各要素数は int (4バイト) で固定。各データ内部は可変サイズで記録されるので注意。



●PMXヘッダ

4 : byte[4]	| "PMX " | ASCIIで 0x50,0x4d,0x58,0x20  ※末尾空白に注意 (PMX1.0は"Pmx "になっているので間違えないように)
4 : float	| ver (2.0)

↑ここまでマジックナンバー

1 : byte	| 後続するデータ列のバイトサイズ  PMX2.0は 8 で固定
n : byte[8]	| byte * バイトサイズ

バイト列 - byte
  [0] - エンコード方式  | 0:UTF16 1:UTF8
  [1] - 追加UV数 	| 0〜4 詳細は頂点参照

  [2] - 頂点Indexサイズ | 1,2,4 のいずれか
  [3] - テクスチャIndexサイズ | 1,2,4 のいずれか
  [4] - 材質Indexサイズ | 1,2,4 のいずれか
  [5] - ボーンIndexサイズ | 1,2,4 のいずれか
  [6] - モーフIndexサイズ | 1,2,4 のいずれか
  [7] - 剛体Indexサイズ | 1,2,4 のいずれか


●モデル情報

4 + n : TextBuf	| モデル名
4 + n : TextBuf	| モデル名英
4 + n : TextBuf	| コメント
4 + n : TextBuf	| コメント英


●頂点

○追加UVについて
PMXの頂点には追加UV(中身は4Dベクトル)を最大4つまで格納することが可能。追加数はヘッダで指定される。
尚、追加UV数はファイルサイズに大きく影響するので、不要なら入れない状態が望ましい。

○ウェイトについて
1頂点につき最大4ボーンまでのウェイト情報を格納可能。
格納方法は対応ボーン数及びSDEFに関連し、

BDEF1
BDEF2
BDEF4
SDEF

の 4パターンに分類される(1byteで形式記録)
記録されるデータは、(ボーンIndex参照をintとして仮定)

BDEF1 : int 		| 4   | ボーンのみ
BDEF2 : int,int,float 	| 4*3 | ボーン2つと、ボーン1のウェイト値(PMD方式)
BDEF4 : int*4, float*4	| 4*8 | ボーン4つと、それぞれのウェイト値。ウェイト合計が1.0である保障はしない
SDEF  : int,int,float, float3*3 
			| 4*12 | BDEF2に加え、SDEF用のfloat3(Vector3)が3つ。実際の計算ではさらに補正値の算出が必要(一応そのままBDEF2としても使用可能)

と可変サイズになるので注意。


[頂点データ]

12 : float3  | 位置(x,y,z)
12 : float3  | 法線(x,y,z)
8  : float2  | UV(u,v)

16 * n : float4[n] | 追加UV(x,y,z,w)  PMXヘッダの追加UV数による
  n:追加UV数 0〜4

1 : byte    | ウェイト変形方式 0:BDEF1 1:BDEF2 2:BDEF4 3:SDEF

※変形方式により継続データが異なる／参照Indexは-1:非参照の場合があるので注意

BDEF1 ->
  n : ボーンIndexサイズ  | ウェイト1.0の単一ボーン(参照Index)

BDEF2 ->
  n : ボーンIndexサイズ  | ボーン1の参照Index
  n : ボーンIndexサイズ  | ボーン2の参照Index
  4 : float              | ボーン1のウェイト値(0〜1.0), ボーン2のウェイト値は 1.0-ボーン1ウェイト

BDEF4 ->
  n : ボーンIndexサイズ  | ボーン1の参照Index
  n : ボーンIndexサイズ  | ボーン2の参照Index
  n : ボーンIndexサイズ  | ボーン3の参照Index
  n : ボーンIndexサイズ  | ボーン4の参照Index
  4 : float              | ボーン1のウェイト値
  4 : float              | ボーン2のウェイト値
  4 : float              | ボーン3のウェイト値
  4 : float              | ボーン4のウェイト値 (ウェイト計1.0の保障はない)

SDEF ->
  n : ボーンIndexサイズ  | ボーン1の参照Index
  n : ボーンIndexサイズ  | ボーン2の参照Index
  4 : float              | ボーン1のウェイト値(0〜1.0), ボーン2のウェイト値は 1.0-ボーン1ウェイト
 12 : float3             | SDEF-C値(x,y,z)
 12 : float3             | SDEF-R0値(x,y,z)
 12 : float3             | SDEF-R1値(x,y,z) ※修正値を要計算

↑ウェイトここまで

4 : float    | エッジ倍率  材質のエッジサイズに対しての倍率値


●面

n : 頂点Indexサイズ     | 頂点の参照Index

※3点(3頂点Index)で1面
材質毎の面数は材質内の面(頂点)数で管理 (同PMD方式)


●テクスチャ

材質内で参照されるテクスチャパスのテーブル

4 + n : TextBuf	| テクスチャパス

※材質からはこちらのIndexを参照。テクスチャ／スフィア／個別Toonで一括して利用
※共有Toon -> toon01.bmp〜toon10.bmp はテクスチャテーブルには入れないので注意

※PMDと同様にモデル位置を基準としてサブフォルダ指定が可能
パス区切りについてはシステム側で認識可能な文字('\'or'/'など)とし、PMXとして固定はしない。


●材質

4 + n : TextBuf	| 材質名
4 + n : TextBuf	| 材質名英

16 : float4	| Diffuse (R,G,B,A)
12 : float3	| Specular (R,G,B)
4  : float	| Specular係数
12 : float3	| Ambient (R,G,B)

1  : bitFlag  	| 描画フラグ(8bit) - 各bit 0:OFF 1:ON
                   0x01:両面描画, 0x02:地面影, 0x04:セルフシャドウマップへの描画, 0x08:セルフシャドウの描画, 
                   0x10:エッジ描画

16 : float4	| エッジ色 (R,G,B,A)
4  : float	| エッジサイズ

n  : テクスチャIndexサイズ     | 通常テクスチャ, テクスチャテーブルの参照Index
n  : テクスチャIndexサイズ     | スフィアテクスチャ, テクスチャテーブルの参照Index  ※テクスチャ拡張子の制限なし
1  : byte	| スフィアモード 0:無効 1:乗算(sph) 2:加算(spa) 3:サブテクスチャ(追加UV1のx,yをUV参照して通常テクスチャ描画を行う)

1  : byte	| 共有Toonフラグ 0:継続値は個別Toon 1:継続値は共有Toon
--
共有Toonフラグ:0 の場合
 n : テクスチャIndexサイズ     | Toonテクスチャ, テクスチャテーブルの参照Index

共有Toonフラグ:1 の場合
 1 : byte	| 共有Toonテクスチャ[0〜9] -> それぞれ toon01.bmp〜toon10.bmp に対応
--
↑どちらか一方なので注意


4 + n : TextBuf	| メモ : 自由欄／スクリプト記述／エフェクトへのパラメータ配置など

4  : int	| 材質に対応する面(頂点)数 (必ず3の倍数になる)


●ボーン

4 + n : TextBuf	| ボーン名
4 + n : TextBuf	| ボーン名英

12 : float3	| 位置
n  : ボーンIndexサイズ  | 親ボーンのボーンIndex
4  : int		| 変形階層

2  : bitFlag*2	| ボーンフラグ(16bit) 各bit 0:OFF 1:ON

○ボーンフラグ
 0x0001  : 接続先(PMD子ボーン指定)表示方法 -> 0:座標オフセットで指定 1:ボーンで指定

 0x0002  : 回転可能
 0x0004  : 移動可能
 0x0008  : 表示
 0x0010  : 操作可

 0x0020  : IK

 0x0100  : 回転付与
 0x0200  : 移動付与

 0x0400  : 軸固定
 0x0800  : ローカル軸

 0x1000  : 物理後変形
 0x2000  : 外部親変形

※それぞれの機能詳細は後述の機能概要で行います。

↓フラグによって継続する格納データが変化するので注意

--
接続先:0 の場合
 12 : float3	| 座標オフセット, ボーン位置からの相対分

接続先:1 の場合
 n  : ボーンIndexサイズ  | 接続先ボーンのボーンIndex
--

---
回転付与:1 または 移動付与:1 の場合
 n  : ボーンIndexサイズ  | 付与親ボーンのボーンIndex
 4  : float	| 付与率
---

--
軸固定:1 の場合
 12 : float3	| 軸の方向ベクトル
--

---
ローカル軸:1 の場合
 12 : float3	| X軸の方向ベクトル
 12 : float3	| Z軸の方向ベクトル ※フレーム軸算出方法は後述
---

--
外部親変形:1 の場合
 4  : int  	| Key値
--

---
IK:1 の場合 IKデータを格納

 n  : ボーンIndexサイズ  | IKターゲットボーンのボーンIndex
 4  : int  	| IKループ回数 (PMD及びMMD環境では255回が最大になるようです)
 4  : float	| IKループ計算時の1回あたりの制限角度 -> ラジアン角 | PMDのIK値とは4倍異なるので注意

 4  : int  	| IKリンク数 : 後続の要素数
 <IKリンク>
   n  : ボーンIndexサイズ  | リンクボーンのボーンIndex
   1  : byte	| 角度制限 0:OFF 1:ON
   ----
   角度制限:1の場合
     12 : float3	| 下限 (x,y,z) -> ラジアン角
     12 : float3	| 上限 (x,y,z) -> ラジアン角
   ----
 </IKリンク>
 * IKリンク数
---


●モーフ

○モーフ種類
格納可能なモーフは大別して、

頂点モーフ
UVモーフ
ボーンモーフ
材質モーフ
グループモーフ

の5種類。さらにUVモーフは、UV／追加UV1〜4の計5種類に分類される。
※追加UV数によっては不要なUVモーフが格納されることがあるが、モーフ側は特に削除などは行わないので注意。


それぞれ、

○頂点モーフ
n  : 頂点Indexサイズ  | 頂点Index
12 : float3	| 座標オフセット量(x,y,z)

○UVモーフ
n  : 頂点Indexサイズ  | 頂点Index
16 : float4	| UVオフセット量(x,y,z,w) ※通常UVはz,wが不要項目になるがモーフとしてのデータ値は記録しておく

○ボーンモーフ
n  : ボーンIndexサイズ  | ボーンIndex
12 : float3	| 移動量(x,y,z)
16 : float4	| 回転量-クォータニオン(x,y,z,w)

○材質モーフ
n  : 材質Indexサイズ  | 材質Index -> -1:全材質対象
1  : オフセット演算形式 | 0:乗算, 1:加算 - 詳細は後述
16 : float4	| Diffuse (R,G,B,A) - 乗算:1.0／加算:0.0 が初期値となる(同以下)
12 : float3	| Specular (R,G,B)
4  : float	| Specular係数
12 : float3	| Ambient (R,G,B)
16 : float4	| エッジ色 (R,G,B,A)
4  : float	| エッジサイズ
16 : float4	| テクスチャ係数 (R,G,B,A)
16 : float4	| スフィアテクスチャ係数 (R,G,B,A)
16 : float4	| Toonテクスチャ係数 (R,G,B,A)

○グループモーフ
n  : モーフIndexサイズ  | モーフIndex  ※仕様上グループモーフのグループ化は非対応とする
4  : float	| モーフ率 : グループモーフのモーフ値 * モーフ率 = 対象モーフのモーフ値

を個々のモーフオフセットとする。


[モーフデータ]

4 + n : TextBuf	| モーフ名
4 + n : TextBuf	| モーフ名英

1  : byte	| 操作パネル (PMD:カテゴリ) 1:眉(左下) 2:目(左上) 3:口(右上) 4:その他(右下)  | 0:システム予約

1  : byte	| モーフ種類 - 0:グループ, 1:頂点, 2:ボーン, 3:UV, 4:追加UV1, 5:追加UV2, 6:追加UV3, 7:追加UV4, 8:材質

4  : int  	| モーフのオフセット数 : 後続の要素数
オフセットデータ * n  | モーフ種類に従ってオフセットデータを格納 ※異なる種類の混合は不可


※材質モーフの演算形式について
複数のモーフからの呼び出しを考慮して、乗算用の材質モーフ値と加算用の材質モーフ値は別管理が望ましい。
想定している動作は、モーフ設定の分だけ乗算分を乗算／加算分を加算して保持、描画時に、

材質値 x 乗算値 + 加算値 

でモーフ適用を行う。
乗算／加算仕様があるのは、初期状態で完全透過(A:0)→非透過(A:1) といったモーフ構造を乗算のみでは作成できないため。
また乗算0+加算により、(元の材質値に関わらず)任意の指定値への変換も簡易になる。

テクスチャ(テクスチャ／スフィア／Toon)のモーフA値(非透過度)はテクスチャのRGB透過合成(乗算:白(1,1,1)との比率混合／加算:黒(0,0,0)との比率混合)に使用。
描画に使用するテクスチャA値はモーフ適用後も元のテクスチャの値を使うこと。


●表示枠

ボーン／モーフを共通化して格納可能
PMDエディタでは Root用とPMD互換の表情枠を特殊枠として初期配置される。

4 + n : TextBuf	| 枠名
4 + n : TextBuf	| 枠名英

1  : byte	| 特殊枠フラグ - 0:通常枠 1:特殊枠

4  : int  	| 枠内要素数 : 後続の要素数
<枠内要素>
  1 : byte	| 要素対象 0:ボーン 1:モーフ
  ----
  要素対象:0の場合
    n  : ボーンIndexサイズ  | ボーンIndex

  要素対象:1の場合
    n  : モーフIndexサイズ  | モーフIndex
  ----
</枠内要素>
* 枠内要素数


※PMXの初期状態では、

表示枠:0(先頭) -> "Root"(特殊枠指定) | 枠内に ボーン:0(先頭ボーン)を追加。対応されれば枠のルート位置への設定用
表示枠:1       -> "表情"(特殊枠指定) | PMD変換時は枠内に 表情枠 と同様の配置 (一部複製処理などで自動的に追加される場合あり)

という特殊枠が配置されます。特殊枠判定は、特殊枠フラグ1及び枠名で判断(編集時に誤って削除しないように注意)


●剛体

※パラメータはPMDの剛体と同様

4 + n : TextBuf	| 剛体名
4 + n : TextBuf	| 剛体名英

n  : ボーンIndexサイズ  | 関連ボーンIndex - 関連なしの場合は-1

1  : byte	| グループ
2  : ushort	| 非衝突グループフラグ

1  : byte	| 形状 - 0:球 1:箱 2:カプセル
12 : float3	| サイズ(x,y,z)

12 : float3	| 位置(x,y,z)
12 : float3	| 回転(x,y,z) -> ラジアン角

4  : float	| 質量
4  : float	| 移動減衰
4  : float	| 回転減衰
4  : float	| 反発力
4  : float	| 摩擦力

1  : byte	| 剛体の物理演算 - 0:ボーン追従(static) 1:物理演算(dynamic) 2:物理演算 + Bone位置合わせ


●Joint

※パラメータはPMDのJointと同様

4 + n : TextBuf	| Joint名
4 + n : TextBuf	| Joint名英

1  : byte	| Joint種類 - 0:スプリング6DOF   | PMX2.0では 0 のみ(拡張用)
--
Joint種類:0 の場合

n  : 剛体Indexサイズ  | 関連剛体AのIndex - 関連なしの場合は-1
n  : 剛体Indexサイズ  | 関連剛体BのIndex - 関連なしの場合は-1

12 : float3	| 位置(x,y,z)
12 : float3	| 回転(x,y,z) -> ラジアン角

12 : float3	| 移動制限-下限(x,y,z)
12 : float3	| 移動制限-上限(x,y,z)
12 : float3	| 回転制限-下限(x,y,z) -> ラジアン角
12 : float3	| 回転制限-上限(x,y,z) -> ラジアン角

12 : float3	| バネ定数-移動(x,y,z)
12 : float3	| バネ定数-回転(x,y,z)
--





■機能概要

●追加UV

PMXの各頂点には4つまで4Dベクトルを追加配置可能。
内部データ的にはPMXヘッダの指定に係わらず常に 4つの4Dベクトルを配置しておくことが望ましい。

・エフェクトから見た頂点バッファ例(セマンティックとの関係)

struct PmxVertex{

float3 Position : POSITION;
float3 Normal : NORMAL;

float2 UV    : TEXCOORD0;

float4 UVA1  : TEXCOORD1;
float4 UVA2  : TEXCOORD2;
float4 UVA3  : TEXCOORD3;
float4 UVA4  : TEXCOORD4;

...
};

※UVモーフの対象になっている追加UVがPMXファイルの頂点に存在しない場合でも、
(0,0,0,0)がデフォルト値として配置されていれば、UVモーフ→エフェクトから任意の処理が可能になると思われます。



●ボーン変形

□変形順序
ボーンの変形順序は

1. 物理前／後
2. 階層順
3. Index順

にて調整(正規化)後、順に変形を行う。1つのボーンにおけるローカル変形処理はIKからのリンク参照を除いて1回のみ。

例：
A, 前,階層2,Index0
B, 後,階層1,Index1
C, 前,階層0,Index2
D, 後,階層0,Index3
E, 前,階層0,Index4
F, 前,階層1,Index5

↓

C, 前,階層0,Index2
E, 前,階層0,Index4
F, 前,階層1,Index5
A, 前,階層2,Index0

<物理演算>

D, 後,階層0,Index3
B, 後,階層1,Index1

という順序で変形処理を行う。


□変形パラメータ
1つのボーンが所持する変形パラメータは以下の通り

・ユーザー操作による 回転／移動量  	| PMDエディタ内ではスケール値も所持
・ボーンモーフによる 回転／移動量
・付与ありの場合     付与回転／付与移動量  | 保存しておくことで多重付与が可能になる
・IKリンクの場合     IK回転量

・ボーン変形処理によるローカル変形状態
・頂点など形状変形用のグローバル変形状態

※回転はクォータニオン、移動は3Dベクトル、変形状態は同次変換行列を想定


□付与について

付与は付与親ボーンの

・ユーザー操作による 回転／移動量
・ボーンモーフによる 回転／移動量
・付与ありの場合     付与回転／付与移動量
・IKリンクの場合     IK回転量

上記変形量を自分自身の変形量にさらに加える変形を行う。
回転／移動は別項目としてそれぞれ追加される(片方だけでもOK)

付与親の親子変形によるボーン変形状態は付与対象ではないので注意。

付与変形を行った後、付与した変形量をボーン内に保存し、
別の付与ボーンから付与親参照された場合にその変形量を渡す→多重付与構造

当然ながら付与ボーンでも親子関係による通常のボーン変形は可能となる。


□変形パラメータの適用順序

0. すべてのボーンのローカル／グローバル変形状態を初期化
1. ユーザー操作の回転／移動量をすべてのボーンに設定
2. ボーンモーフによる回転／移動量を対応するボーンに設定

3. 変形順序の正規化
4. 正規化後の順にボーン変形を行う

4.1. ボーンのローカル変形(詳細は後述)
4.2. IKの場合IK変形


以上の手順ですべてのボーンを変形。

物理変形後の適用は、物理変形によるグローバル変形量をローカル変形量に一旦戻し、
それを親参照する変形を継続することで行われる。



□ローカル変形順序

※暫定設定なので順序など変更になるかもしれません
※PMDエディタ0.1.3.6以降、IKリンクの回転順序を変更(MMDのIK変形と合致させるため／前→後)

・回転量(クォータニオン)の計算
[親付与回転量(or 親回転 * 親回転モーフ) * 付与親のIKリンク]:付与率 * 回転 * 回転モーフ * IKリンク
--
計算例:
0. 回転量を単位回転量として開始

1. 当該ボーンが付与の場合 : 
 1.1 付与親が付与ボーンの場合 : * 付与親の付与回転量(※後述) <> 付与ボーンではない場合 : * 付与親の回転 * 付与親の回転モーフ
 1.2 付与率が1以外の場合 : 2.1／2.2の回転量を付与率で補正(Quaternion.Slerp()想定)
 1.3 付与親がIKリンクの場合 : * 付与親のIKリンク回転量

 1.4 付与親のIKリンク〜回転モーフ(付与率で補正済み)〜回転モーフ を当該ボーンの付与回転量として保存(別の付与ボーンの付与親になった場合の多重付与変形用)
    ※付与回転量 → { [親付与回転量(or 親回転 * 親回転モーフ) * 付与親のIKリンク]:付与率 * 回転 * 回転モーフ }

2. 当該ボーンの回転量追加 : * 回転 * 回転モーフ

3. 当該ボーンがIKリンク回転量を持つ場合 : * IKリンク回転量

※IKリンク回転量は当該ボーンが付与参照される間に別のIKボーンによって変形／更新される可能性があるので、
それを考慮して付与回転量から一旦外す形(付与参照時に再計算)になっています。
乗算順序が少々怪しいのと、付与親のIKリンクは参照時に確定されてしまうなどの問題がありますが、暫定的にこのような計算順序としておきます。


・移動量(3Dベクトル)の計算
[親付与移動量(or 親移動 + 親移動モーフ)]*付与率 + 移動 + 移動モーフ
--
計算例:(基本的に回転と同じ)

0. 移動量を0移動量として開始

1. 当該ボーンが付与の場合 : 
 1.1 付与親が付与ボーンの場合 : + 付与親の付与移動量(※後述) <> 付与ボーンではない場合 : + 付与親の移動 + 付与親の移動モーフ
 1.2 付与率が1以外の場合 : 1.1の移動量を付与率で補正(付与率乗算でOK)

 1.3 親付与移動量(付与率で補正済み)〜移動モーフ を当該ボーンの付与移動量として保存(別の付与ボーンの付与親になった場合の多重付与変形用)
    ※付与移動量 → { [親付与移動量(or 親移動 + 親移動モーフ)]:付与率 + 移動 + 移動モーフ }

2. 当該ボーンの移動量追加 : + 移動 + 移動モーフ


→
算出された回転／移動の両値から、

ローカル行列 = (スケール行列) * 回転行列 * 移動行列

を計算、親ボーンからのオフセット及び親のローカル行列に合成する。

当該ボーンがIKボーンの場合、(IKボーン／IKターゲットの位置関係より)IKリンクのIK回転量を再計算 → ボーンのIKリンク回転量を更新。
PMXのIK変形はIKボーンの変形順序時にそのまま変形を行う(PMDのように全ボーン変形後などの順序固定ではないので注意)


以上の手順ですべてのボーンのローカル変形を更新。

物理変形後の適用は、物理変形によるグローバル変形量をローカル変形量に戻し、
それを親参照する変形を継続することで行われる。



□変形順序による変形量の参照について

親子変形による伝達が必要な変形は、親→子順にボーン変形を呼び出す必要がある。
子→親の順序では正しく変形しない。

ユーザー操作量を参照する付与伝達の場合は、付与親の変形前にボーン変形が呼び出されても正常に変形する
(ただし1段階のみ／多重付与を行う場合は付与親が先に変形されている必要がある)

ボーンモーフを参照する付与の場合も同様である。


□制限軸

PMDの捩りボーンと同系の仕組み。捩りボーン同様ボーンの内部変形量には関与しない。
操作時の移動及び回転軸を指定した軸方向で固定化する機能を有する。


□ローカル軸

操作上のローカルフレームを任意に定義するための軸方向パラメータ。
X／Zで指定するが、それらが直交関係ではない場合もあるので以下の計算式で補正する。

Y = Vector3.Cross(Z, X);   // Vector3.Cross():ベクトル積
Z' = Vector3.Cross(X, Y);

※PMDでは腕関連のみ子ボーンの方向をX、手前を-Zとする軸でローカルフレームが自動作成される模様。


□外部親変形

指定されたボーンはモデル外部のボーンを親ボーンとして変形することが可能。
その場合の識別用IDとしてKey値(int)が用意されている。

この構成を利用することで、例えばモデルをアクセサリのように特定のモデルの特定ボーンに関係付ける構造や、
腕IKを使った手同士の接続及び操作モデルによる一括操作を実現することが可能となる。

※ただし、これらの機構を接続するための外部仕様が非常にややこしいので、実現の可能性は低いと思われる。


□ボーンの属性(フラグ値)について

 0x0001  : 接続先
 0x0002  : 回転可能
 0x0004  : 移動可能
 0x0008  : 表示
 0x0010  : 操作可
 0x0020  : IK
 0x0100  : 回転付与
 0x0200  : 移動付与
 0x0400  : 軸固定
 0x0800  : ローカル軸
 0x1000  : 物理後変形
 0x2000  : 外部親変形

とあるが、この中でボーンの変形特性に係わる属性は

 0x0020  : IK
 0x0100  : 回転付与
 0x0200  : 移動付与
 0x1000  : 物理後変形
 0x2000  : 外部親変形

のみで、残りの

 0x0001  : 接続先
 0x0002  : 回転可能
 0x0004  : 移動可能
 0x0008  : 表示
 0x0010  : 操作可
 0x0400  : 軸固定
 0x0800  : ローカル軸

は、表示及び操作時の制限項目になる。
ボーンの変形特性や内部値には関与しないので注意。


□PMDとの互換性

IK／回転影響下 以外のボーン構造は問題なく変換可能。
上記2種類は、親子系列での変形後、特定タイミングでさらに特定の変形を行うので、
基本的に1ボーン1度のみの変形が基準であるPMXのボーン構造ではうまく変換できない場合がある。

PMD→PMX 変換では、

IKボーン及びそのIKを親としている系列の変形階層を 0→1
回転影響下以下の変形階層を 0→2

にすべて変換して対応しているが、ボーン構造によってはこの変換では異なる変形様式になる可能性があるので注意。

対応方法としては、PMDの複数回変形の構造に対して、PMX側も複数のボーン構造(分割したボーンは親子結合or付与結合)を
用いることが考えられる。








以上
