針金のブログ

アクセスカウンタ

zoom RSS VMDメモ

<<   作成日時 : 2011/03/02 02:00   >>

トラックバック 0 / コメント 0

VMDの内部フォーマットを自己解析してみました.

同様の物はネット上でいくつか紹介されていますが,情報が抜けていたり,微妙に違いがあるようなので,VMDパーサ作成の際に確認を兼ねて解析.
あくまで個人でやった解析なので,内容の正確さを保証する物ではありませんが・・

2013/7/23 : 表示・IK等について追記しました。


・VMDデータ構造は以下の通り(記述はC言語形式)

struct Header header; // ヘッダ

DWORD boneCount; // ボーンキーフレーム数
struct BoneFrame bone[boneCount]; // ボーン要素データ

DWORD morphCount; // 表情キーフレーム数
struct MorphFrame morph[morphCount]; // 表情要素データ

DWORD cameraCount; // カメラキーフレーム数
struct CameraFrame camera[cameraCount]; // カメラ要素データ

DWORD lightCount; // 照明キーフレーム数
struct LightFrame light[lightCount]; // 照明要素データ
// MMDv6.19以前で保存されたVMDはここまで

DWORD sshadowCount; // セルフ影キーフレーム数
struct SelfShadowFrame sShadow[sshadowCount]; // セルフ影要素データ
// MMDv7.39.x64以前で保存されたVMDはここまで

DWORD showIKCount; // モデル表示・IK on/offキーフレーム数
struct ShowIKFrame showIK[showIKCount]; // 表示・IK on/off要素データ


・各要素のデータ構造は以下の通り

// ヘッダ
struct Header
{
char header[30]; // "Vocaloid Motion Data 0002\0\0\0\0\0" 30byte
// (MMDver2以前のvmdは"Vocaloid Motion Data file\0")
char modelName[20]; // モデル名 20byte(MMDver2以前のvmdは10byte)
// 内容がカメラ,照明,セルフ影の場合は"カメラ・照明\0on Data"となる
};

//ボーンキーフレーム要素データ(111Bytes/要素)
struct BoneFrame
{
char name[15]; // "センター\0"などのボーン名の文字列 15byte
DWORD frame; // フレーム番号
float x; // ボーンのX軸位置,位置データがない場合は0
float y; // ボーンのY軸位置,位置データがない場合は0
float z; // ボーンのZ軸位置,位置データがない場合は0
float qx; // ボーンのクォータニオンX回転,データがない場合は0
float qy; // ボーンのクォータニオンY回転,データがない場合は0
float qz; // ボーンのクォータニオンZ回転,データがない場合は0
float qw; // ボーンのクォータニオンW回転,データがない場合は1
char bezier[64]; // 補間パラメータ
};
/*
補間パラメータは4点のベジェ曲線(0,0),(x1,y1),(x2,y2),(127,127)で
表している.各軸のパラメータを
X軸の補間パラメータ (X_x1,X_y1),(X_x2,X_y2)
Y軸の補間パラメータ (Y_x1,Y_y1),(Y_x2,Y_y2)
Z軸の補間パラメータ (Z_x1,Z_y1),(Z_x2,Z_y2)
回転の補間パラメータ (R_x1,R_y1),(R_x2,R_y2)
とした時、補間パラメータは以下の通り.
X_x1,Y_x1,Z_x1,R_x1,X_y1,Y_y1,Z_y1,R_y1,
X_x2,Y_x2,Z_x2,R_x2,X_y2,Y_y2,Z_y2,R_y2,
Y_x1,Z_x1,R_x1,X_y1,Y_y1,Z_y1,R_y1,X_x2,
Y_x2,Z_x2,R_x2,X_y2,Y_y2,Z_y2,R_y2, 01,
Z_x1,R_x1,X_y1,Y_y1,Z_y1,R_y1,X_x2,Y_x2,
Z_x2,R_x2,X_y2,Y_y2,Z_y2,R_y2, 01, 00,
R_x1,X_y1,Y_y1,Z_y1,R_y1,X_x2,Y_x2,Z_x2,
R_x2,X_y2,Y_y2,Z_y2,R_y2, 01, 00, 00
*/


//表情キーフレーム要素データ(23Bytes/要素)
struct MorphFrame
{
char name[15] // "まばたき\0"などの表情名の文字列 15byte
DWORD frame; // フレーム番号
float value // 表情値(0〜1)
};


//カメラキーフレーム要素データ(61Bytes/要素)
struct CameraFrame
{
DWORD frame; // フレーム番号
float distance // 目標点とカメラの距離(目標点がカメラ前面でマイナス)
float x; // 目標点のX軸位置
float y; // 目標点のY軸位置
float z; // 目標点のZ軸位置
float rx; // カメラのx軸回転(rad)(MMD数値入力のマイナス値)
float ry; // カメラのy軸回転(rad)
float rz; // カメラのz軸回転(rad)
char bezier[24]; // 補間パラメータ
DWORD viewAngle; // 視野角(deg)
char parth; // パースペクティブ, 0:ON, 1:OFF
};
/*
補間パラメータは4点のベジェ曲線(0,0),(x1,y1),(x2,y2),(127,127)で
表している.各軸のパラメータを
X軸の補間パラメータ  (X_x1,X_y1),(X_x2,X_y2)
Y軸の補間パラメータ  (Y_x1,Y_y1),(Y_x2,Y_y2)
Z軸の補間パラメータ  (Z_x1,Z_y1),(Z_x2,Z_y2)
回転の補間パラメータ (R_x1,R_y1),(R_x2,R_y2)
距離の補間パラメータ (L_x1,L_y1),(L_x2,L_y2)
視野角の補間パラメータ(V_x1,V_y1),(V_x2,V_y2)
とした時、補間パラメータは以下の通り.
X_x1 X_x2 X_y1 X_y2
Y_x1 Y_x2 Y_y1 Y_y2
Z_x1 Z_x2 Z_y1 Z_y2
R_x1 R_x2 R_y1 R_y2
L_x1 L_x2 L_y1 L_y2
V_x1 V_x2 V_y1 V_y2
*/


//照明キーフレーム要素データ(28Bytes/要素)
struct LightFrame
{
DWORD frame; // フレーム番号
float r; // 照明色赤(MMD入力値を256で割った値)
float g; // 照明色緑(MMD入力値を256で割った値)
float b; // 照明色青(MMD入力値を256で割った値)
float x; // 照明x位置(MMD入力値)
float y; // 照明y位置(MMD入力値)
float z; // 照明z位置(MMD入力値)
};


//セルフ影キーフレーム要素データ(9Bytes/要素)
struct SelfShadowFrame
{
DWORD frame; // フレーム番号
char type; // セルフシャドウ種類, 0:OFF, 1:mode1, 2:mode2
float distance ; // シャドウ距離(MMD入力値Lを(10000-L)/100000とした値)
};


//モデル表示・IK on/offキーフレーム要素データ((9+21*IK数)Bytes/要素)
struct ShowIKFrame
{
DWORD frame; // フレーム番号
char show; // モデル表示, 0:OFF, 1:ON
DWORD ik_count; // 記録するIKの数
struct InfoIK ik[ik_count]; // IK on/off情報配列
};

struct InfoIK
{
char name[20]; // "右足IK\0"などのIKボーン名の文字列 20byte
char on_off; // IKのon/off, 0:OFF, 1:ON
};


特記事項
・文字列に関するTips
文字コードはシフトJIS(モデル名・ボーン名・表情名・IKボーン名)
終端 0x00, パディング 0xFD(PMXモデルで保存した場合はパディング 0x00)
文字列が限界バイト数を超える場合、ヘッダモデル名・ボーン名は
終端 0x00なしでそれぞれ20Byte,15Byteまで保存される。
ただしMMDロード時に照合出来なくなる。
モーフ名は15Byte終端 0x00なしで保存され、MMDロード時も照合可能
IKボーン名は19Byteまで保存され20Byte目は終端 0x00文字になる。
MMDロード時の照合は19Byteまでで行われるもよう。

・フレーム番号は保存されるフレームの中で最小値を0として、そこからの
相対的なフレーム位置が記録される。

・数値データのバイト列は全てリトルエンディアン


月別リンク

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
VMDメモ 針金のブログ/BIGLOBEウェブリブログ
文字サイズ:       閉じる