MMDアニメーションローダー (VmdLoader, VpdLoader)
このセクションでは、MMDアニメーションファイル(VMD、VPD)をロードするために使用されるコンポーネントについて説明します。
MMDアニメーションは VmdLoader でロードでき、ポーズデータも VpdLoader を使用してアニメーションとしてロードできます。
VmdLoader
VmdLoader は、MMDアニメーションファイル形式である**ボーカロイドモーションデータ(VMD)**ファイルをロードするために使用されます。このローダーはVMDファイルからアニメーションデータを読み取り、babylon-mmdランタイムに適用できる形式でロードします。
VmdLoader はVMDファイルを解析して MmdAnimation インスタンスを返す複数のメソッドを提供しており、最も基本的なメソッドは loadAsync です。
const vmdLoader = new VmdLoader();
const mmdAnimation: MmdAnimation = await vmdLoader.loadAsync("motion1", "path/to/motion1.vmd");
loadAsync メソッドが受け取るパラメータは以下の通りです:
name: アニメーションの名前。fileOrUrl: VMDファイルのURLをstringまたはstring[]、あるいはFileまたはFile[]として指定。onProgress: ロード進捗を定期的に通知するコールバック関数。
ここで注目すべき重要なポイントは、単一の MmdAnimation インスタンスを作成するために複数のアニメーションソースを受け取ることができることです。例えば、複数のVMDファイルを1つの MmdAnimation にロードできます。
const vmdLoader = new VmdLoader();
const mmdAnimation: MmdAnimation = await vmdLoader.loadAsync("motion1", [
"path/to/motion1.vmd",
"path/to/motion2.vmd"
]);
この場合、2つのモーションが結合され、配列内で先に登場するモーションが優先されます。つまり、両方のモーションが同じフレームにキーフレームを持つ場合、配列内で最初に登場するモーションのキーフレームが使用されます。
また、ブラウザの File APIを使用してロードすることもできます。
さらに、以下のメソッドも提供されています:
load: VMDファイルを同期的にロードし、onLoadおよびonErrorコールバックをサポート。loadFromBufferAsync/loadFromBuffer: 複数の**ArrayBuffer** インスタンスを解析して**MmdAnimation** をロード。loadFromVmdDataAsync/loadFromVmdData: 複数の**VmdData** インスタンスから**MmdAnimation** をロード。loadFromVmdObjectAsync/loadFromVmdObject: 複数の**VmdObject** インスタンスから**MmdAnimation** をロード。
これらすべてのメソッドをまとめると、VmdLoader がサポートする入力データ形式は以下のようになります:
- VMDファイル(
Fileまたは**File[]、string** または**string[]**) - アレイバッファ(
ArrayBufferまたは**ArrayBuffer[]**) - VMDデータ(
VmdDataまたは**VmdData[]**) - VMDオブジェクト(
VmdObjectまたは**VmdObject[]**)
ここで、VmdData と VmdObject は以下のような型です:
VmdData: VMDデータを持つバッファを表すコンテナ型VmdObject: 遅延解析されるVMDデータオブジェクト
これらを使用して、解析メソッドを明示的に呼び出して MmdAnimation を作成することができます:
const arrayBuffer = await fetch("path/to/motion1.vmd")
.then(response => response.arrayBuffer());
const vmdData = VmdData.CheckedCreate(arrayBuffer);
if (vmdData === null) {
throw new Error("VMDデータの検証に失敗しました");
}
const vmdObject = VmdObject.Parse(vmdData);
const vmdLoader = new VmdLoader();
const mmdAnimation = await vmdLoader.loadFromVmdObjectAsync("motion1", vmdObject);
このように、すべてのプロセスを明示的に呼び出してロードできるようにすることで、babylon-mmdはロード過程での修正や、完全に異なるコンテナにロードする新しいロジックの記述を可能にする拡張性を提供しています。
さらに、VmdLoader は以下のオプションを提供します:
VmdLoader.optimizeEmptyTracks: アニメーションに影響を与えないトラックを最適化して削除するかどうかを設定します。デフォルトはtrueです。VmdLoader.loggingEnabled: ロード処理中のログ出力を有効にします。値がfalseの場合、発生した問題に関するログは生成されません。デフォルトはfalseです。
VpdLoader
VpdLoader は、MMDポーズデータファイル形式である**ボーカロイドポーズデータ(VPD)**ファイルをロードするために使用されます。このローダーはVPDファイルからポーズデータを読み取り、babylon-mmdランタイムに適用できる形式でロードします。
VpdLoader も VmdLoader と同様に、MmdAnimation を返す複数のメソッドを提供しています。最も基本的なメソッドは loadAsync です。
const vpdLoader = new VpdLoader();
const mmdAnimation: MmdAnimation = await vpdLoader.loadAsync("pose1", "path/to/pose1.vpd");
このとき作成されるアニメーションは1フレームのアニメーションです。
他に提供されるロードメソッドには以下があります:
load: VPDファイルを同期的にロードし、onLoadおよびonErrorコールバックをサポート。loadFromBufferAsync/loadFromBuffer:ArrayBufferインスタンスを解析してMmdAnimationをロード。loadFromVpdObjectAsync/loadFromVpdObject:VpdObjectインスタンスからMmdAnimationをロード。
VmdLoader とは異なり、VpdLoader は一度に複数のVPDファイルをロードすることをサポートしていません。
VpdLoader がサポートする入力データ形式は以下の通りです:
- VPDファイル(
Fileまたは**string[]**) - アレイバッファ(
ArrayBuffer) - VPDオブジェクト(
VpdObject)
ここで、VpdObject はVPDファイルから解析されたデータを表すオブジェクトです。
VMDとは異なり、VPDファイルは遅延解析をサポートしていないため、VpdObjectはクラスではなくJavaScriptオブジェクトとして表されます。
これを使用して、解析メソッドを明示的に呼び出して MmdAnimation を作成する方法は以下の通りです:
const arrayBuffer = await fetch("path/to/pose1.vpd")
.then(response => response.arrayBuffer());
const textDecoder = new TextDecoder("shift_jis");
const text = textDecoder.decode(arrayBuffer);
const vpdObject = VpdReader.Parse(text);
const vpdLoader = new VpdLoader();
const mmdAnimation = await vpdLoader.loadFromVpdObjectAsync("pose1", vpdObject);
また、VpdLoader.loggingEnabled オプションを通じて、ロード処理中のログ出力を有効にすることができます。このオプションのデフォルト値はfalseです。
MmdAnimation
基本的に、MMDアニメーションはBabylon.jsのアニメーションランタイムとは別のアニメーションランタイムで実行されます。これは、MMDアニメーションとBabylon.jsアニメーションランタイム間の仕様の違いが統合するには大きすぎるためです。
したがって、MMDアニメーションを格納するコンテナも、デフォルトではBabylon.jsの Animation や AnimationGroup ではなく、babylon-mmdが提供する MmdAnimation を使用します。
MmdAnimation のプロパティは以下の通りです:
| プロパティ名 | 型 | 説明 |
|---|---|---|
name | string | アニメーションの名前 |
boneTracks | MmdBoneAnimationTrack[] | ボーンの位置と回転アニメーショントラックのリスト |
movableBoneTracks | MmdMovableBoneAnimationTrack[] | ボーンの回転アニメーショントラックのリスト |
morphTracks | MmdMorphAnimationTrack[] | モーフアニメーショントラックのリスト |
propertyTrack | MmdPropertyAnimationTrack | 表示状態とIK切り替えアニメーショントラック |
cameraTrack | MmdCameraAnimationTrack | カメラアニメーショントラック |
すべてのアニメーショントラックはTypedArrayで表され、デフォルトでは不変であることが前提とされています。
これは後述するWebAssemblyに関連する最適化を容易にするための制約です。データを修正しても安全だとわかっている場合は、問題なくトラック値を変更できます。
MmdAnimation の注目すべき点は、モデルアニメーションを表す4つのトラックタイプ(boneTracks、movableBoneTracks、morphTracks、propertyTrack)とカメラアニメーションを表す cameraTrack が分離されていることです。
そのため、vmdアニメーションをロードする際、モデルアニメーションとカメラアニメーションを単一の MmdAnimation インスタンスにロードすることができます。
const vmdLoader = new VmdLoader();
const mmdAnimation: MmdAnimation = await vmdLoader.loadAsync("motion1", [
"path/to/model/anim.vmd",
"path/to/camera/anim.vmd"
]);
この場合、アニメーションは後でMMDモデルとカメラの両方に適用できます。