#author("2026-10-05T18:05:08+09:00","","") * VPD姿势数据格式 [#na2bd3d0] &size(13){''単一フレーム姿勢データの構造と用途''}; #contents ** VPD とは [#a96461e5] ''VPD'' は、''1 つのフレームの姿勢だけ''を保存するフォーマットです。 ''時間軸の情報を持ちません''。 |~項目|~内容| |拡張子|.vpd| |マジック|`Vocaloid Pose Data file`(30 バイト)| |文字|Shift-JIS| |形式|''半テキスト''(バイナリ + テキスト行)| |内容|''ボーンの姿勢のみ''(モーフは含まない場合が多い)| > '''VPD と VMD の違い''': > ''VMD = 時間軸のあるアニメーション''。 > ''VPD = 時間軸のない「ポーズ 1 枚」''。 > 用途がまったく異なります。 ** 用途 [#z0437ef9] |~用途|~内容| |ポーズの保存|作業中の姿勢を保存・復元する| |ポーズ素材の配布|「座りポーズ」「かわいいポーズ」等を配布| |初期姿勢の指定|モデルの基準姿勢として使う| |ポーズの中継|外部ツールと姿勢を受け渡す| > '''注意''':VPD は''モーフ(表情)を含みません''。 > 表情込みで保存したい場合は''VMD''を使うか、 > ''VPD + モーフ情報''の両方を管理する必要があります。 ** ファイル構造 [#pa7cdc2c] #code(){{ ┌──────────────────────────────┐ │ char[30] "Vocaloid Pose Data file" │ ├──────────────────────────────┤ │ char[20] モデルファイル名 │ ├──────────────────────────────┤ │ uint32 ボーン数 │ ├──────────────────────────────┤ │ (以下、ボーン数分繰り返し) │ │ char[15] ボーン名 │ │ テキスト行 ボーン番号;座標;回転; │ └──────────────────────────────┘ }} ** Header [#w9e46bdd] |~フィールド|~型|~内容| |magic|char[30]|`Vocaloid Pose Data file`(残りは \0 埋め)| |modelFileName|char[20]|''モデルファイル名''(例:`Model.pmx;`)| |boneCount|uint32|''ボーン数(バイナリ)''| > '''注目点''':`boneCount` だけが''バイナリの整数''です。 > 前後のフィールドはテキストなのに、ここだけ数値が生で入ります。 > この''中途半端な設計''が VPD の特徴です。 *** modelFileName の意味 [#cc5c1304] ''その VPD が前提とするモデルのファイル名''です。 ''適用時には使われません'' — VMD の modelName と同じ扱いです。 ** ボーンデータ [#h2cfcdcf] 各ボーンは''バイナリ部''と''テキスト部''の組み合わせです。 #code(){{ char[15] boneName // バイナリ(Shift-JIS) "<index>;<x>,<y>,<z>;<rx>,<ry>,<rz>,<rw>;\n" // テキスト 1 行 }} *** テキスト行の書式 [#s67c667f] #code(){{ BoneIndex;PosX,PosY,PosZ;RotX,RotY,RotZ,RotW; }} ''例'': #code(){{ 0;0.000000,0.000000,0.000000;0.000000,0.000000,0.000000,1.000000; }} |~フィールド|~内容| |index|''ボーン番号''(int)| |PosX, PosY, PosZ|位置オフセット(float)| |RotX, RotY, RotZ, RotW|''クォータニオン''(float)| > '''実装の注意''': > - 数値は''小数点以下 6 桁''で出力されるのが一般的ですが、 > ''桁数は可変''です。パース時は''柔軟に読む''必要があります。 > - 区切りは''セミコロン''、数値の区切りは''カンマ''です。 > - ''行末は改行''(`\n` または `\r\n`)。環境により異なります。 *** 回転はクォータニオン [#zcd8b940] VMD のボーン回転と同じく、''クォータニオン''です。 ''順序は (x, y, z, w)'' です。 > '''注意''':VPD のクォータニオンは''正規化されているとは限りません''。 > 読み込み時に''正規化''するのが安全です。 ** バイナリ部とテキスト部が混在する理由 [#v177e326] ''歴史的な経緯''によるものです。 - VPD は''人の手で編集できる''ことを意図してテキスト形式で設計された - しかし''ボーン数''だけは''ループ制御''に必要でバイナリになった - 結果として''ハイブリッド''な形式になった > '''実務的な含意''':''テキストエディタで開いて手修正できる''のが VPD の利点です。 > 座標を微調整したいときに便利です。 ** パースの実装 [#u28b7b28] #region(VPD 読み込みの擬似コード) #code(){{ read magic[30] read modelFileName[20] read boneCount (uint32) for i in 0 .. boneCount-1: read boneName[15] read line until '\n' split line by ';' index = int(field[0]) pos = float3(field[1]) rot = float4(field[2]) // クォータニオン normalize(rot) }} #endregion *** 落とし穴 [#jf1048f8] |~症状|~原因| |読み込みが途中で壊れる|''改行コード''の違い(\n / \r\n)| |座標が全部 0 になる|''ロケール''の問題(小数点がカンマ扱い)| |回転がおかしい|''クォータニオンの正規化漏れ''| |ボーン名が文字化け|''Shift-JIS 以外で解釈''している| > '''要注意''':C 言語の `scanf` / `atof` は''ロケール依存''です。 > ヨーロッパ系ロケールでは''小数点がカンマ''になるため、 > VPD の ''カンマ区切り''と衝突して''数値が正しく読めません''。 > パースは''明示的に''行うべきです。 ** VPD と VMD の相互運用 [#zc8cbf07] *** VPD から VMD を作る [#v44735a9] ''1 フレームだけの VMD''を作ることで実現できます。 + VPD をモデルに読み込む + そのフレームにキーを打つ(''キー登録'') + VMD として保存する *** VMD から VPD を取り出す [#zcfc9a65] + 対象フレームへ移動する + その時点の姿勢を''VPD として保存''する ** VPD の活用パターン [#d773b117] *** 1. ポーズ素材として [#r2ffafd1] ''配布されているポーズ VPD''を読み込むことで、 ''手を付けずに自然な姿勢''を得られます。 ダンスモーションの''一部分だけ差し替える''用途にも使えます。 *** 2. 初期姿勢の定義 [#q649efec] ''モデルの基準姿勢''を VPD にしておき、 毎回それを''読み込んでから''作業を始める運用です。 *** 3. 外部ツールとの連携 [#hce79e5b] ''Blender などで作った姿勢''を VPD 経由で MMD に持っていく、 あるいはその逆ができます。 *** 4. 差分の適用 [#b6e33eef] ''一部のボーンだけを含む VPD''を作れば、 ''そのボーンだけを上書き''できます。 > '''応用例''':手のポーズだけを 10 種類用意し、 > ダンスモーションに''後から差し替える''。 ** 制限事項 [#zd0708f3] |~制限|~内容| |モーフ非対応|表情は保存されない| |時間軸なし|アニメーションは作れない| |カメラ非対応|カメラは保存されない| |照明非対応|照明も保存されない| |物理非対応|揺れ物の姿勢は保存されない| > '''特に注意''':''物理で動くボーン(髪・スカート)''は > VPD に保存されても''物理演算に上書きされます''。 > 物理の姿勢を固定したい場合は''物理をオフ''にする必要があります。 ** 関連ページ [#m50d1364] - [[VMD动作数据格式]] — 時間軸のあるデータ - [[数据格式速查表]] — 一覧表 - [[动作制作基础]] — 姿勢の作り方 - [[外部工具与桥接]] — 外部との連携 #comment(num=5,noname,below)