非MMDモデルにMMDアニメーションを適用
MMDアニメーションは、一般的に準標準ボーン構造に従うMMDモデルと互換性があるように設計されています。
しかし、babylon-mmdはヒューマノイドモデルにMMDアニメーションを適用することもサポートしています。
ヒューマノイドモデル
ヒューマノイドモデルは、UnityのHumanoid RigとMixamo rigのボーン構造に従うモデルを指します。
ヒューマノイドモデルのボーン構造は以下の通りです:
/**
* refs:
* https://docs.unity3d.com/ScriptReference/HumanBodyBones.html
* https://github.com/V-Sekai/three-vrm-1-sandbox-mixamo/blob/master/mixamoVRMRigMap.js
*
* unity humanoid bone structure:
*
* - Hips
* - Spine
* - Chest
* - UpperChest
* - Neck
* - Head
* - LeftEye
* - RightEye
* - Jaw
*
* - LeftShoulder
* - LeftUpperArm
* - LeftLowerArm
* - LeftHand
* - LeftThumbProximal
* - LeftThumbIntermediate
* - LeftThumbDistal
* - LeftIndexProximal
* - LeftIndexIntermediate
* - LeftIndexDistal
* - LeftMiddleProximal
* - LeftMiddleIntermediate
* - LeftMiddleDistal
* - LeftRingProximal
* - LeftRingIntermediate
* - LeftRingDistal
* - LeftLittleProximal
* - LeftLittleIntermediate
* - LeftLittleDistal
*
* - RightShoulder
* - RightUpperArm
* - RightLowerArm
* - RightHand
* - RightThumbProximal
* - RightThumbIntermediate
* - RightThumbDistal
* - RightIndexProximal
* - RightIndexIntermediate
* - RightIndexDistal
* - RightMiddleProximal
* - RightMiddleIntermediate
* - RightMiddleDistal
* - RightRingProximal
* - RightRingIntermediate
* - RightRingDistal
* - RightLittleProximal
* - RightLittleIntermediate
* - RightLittleDistal
*
* - LeftUpperLeg
* - LeftLowerLeg
* - LeftFoot
* - LeftToes
*
* - RightUpperLeg
* - RightLowerLeg
* - RightFoot
* - RightToes
*/
Humanoid MMD
HumanoidMmd
は、ヒューマノイドモデルにMMDアニメーションを適用するためのヘルパークラスです。
このクラスを使用して、プロキシ準標準スケルトンを作成してMmdModel
を生成し、リアルタイムリターゲティングを使用してヒューマノイドモデルにMMDアニメーションを適用できます。
const mmdRuntime = new MmdRuntime(scene);
const humanoidMmd = new HumanoidMmd();
const mmdModel = humanoidMmd.createMmdModelFromHumanoid(
mmdRuntime,
modelRoot,
[modelMesh],
{
boneMap: new MmdHumanoidMapper({
hips: "Hips",
spine: "Spine",
chest: "Chest",
neck: "Neck",
head: "Head",
leftShoulder: "LeftShoulder",
leftUpperArm: "LeftUpperArm",
leftLowerArm: "LeftLowerArm",
leftHand: "LeftHand",
rightShoulder: "RightShoulder",
rightUpperArm: "RightUpperArm",
rightLowerArm: "RightLowerArm",
rightHand: "RightHand",
leftUpperLeg: "LeftUpperLeg",
leftLowerLeg: "LeftLowerLeg",
leftFoot: "LeftFoot",
leftToes: "LeftToeBase",
rightUpperLeg: "RightUpperLeg",
rightLowerLeg: "RightLowerLeg",
rightFoot: "RightFoot",
rightToes: "RightToeBase",
leftEye: "LeftEye",
rightEye: "RightEye",
leftThumbProximal: "LeftThumbProximal",
leftThumbIntermediate: "LeftThumbIntermediate",
leftThumbDistal: "LeftThumbDistal",
leftIndexProximal: "LeftIndexProximal",
leftIndexIntermediate: "LeftIndexIntermediate",
leftIndexDistal: "LeftIndexDistal",
leftMiddleProximal: "LeftMiddleProximal",
leftMiddleIntermediate: "LeftMiddleIntermediate",
leftMiddleDistal: "LeftMiddleDistal",
leftRingProximal: "LeftRingProximal",
leftRingIntermediate: "LeftRingIntermediate",
leftRingDistal: "LeftRingDistal",
leftLittleProximal: "LeftLittleProximal",
leftLittleIntermediate: "LeftLittleIntermediate",
leftLittleDistal: "LeftLittleDistal",
rightThumbProximal: "RightThumbProximal",
rightThumbIntermediate: "RightThumbIntermediate",
rightThumbDistal: "RightThumbDistal",
rightIndexProximal: "RightIndexProximal",
rightIndexIntermediate: "RightIndexIntermediate",
rightIndexDistal: "RightIndexDistal",
rightMiddleProximal: "RightMiddleProximal",
rightMiddleIntermediate: "RightMiddleIntermediate",
rightMiddleDistal: "RightMiddleDistal",
rightRingProximal: "RightRingProximal",
rightRingIntermediate: "RightRingIntermediate",
rightRingDistal: "RightRingDistal",
rightLittleProximal: "RightLittleProximal",
rightLittleIntermediate: "RightLittleIntermediate",
rightLittleDistal: "RightLittleDistal"
}).boneMap,
transformOffset: modelArmatureRootWorldTransform
}
);
ヒューマノイドモデルからMmdModel
を作成するファンクションのシグネチャは以下の通りです:
HumanoidMmd.createMmdModelFromHumanoid<T extends IMmdModel>(
mmdRuntime: IMmdRuntime<T>,
humanoidMesh: Mesh,
meshes: readonly Mesh[],
options: ICreateMmdModelFromHumanoidOptions = {}
): T
-
mmdRuntime:
IMmdRuntime<MmdModel>
MmdRuntime
クラスまたはMmdWasmRuntime
クラスのインスタンスが可能です。
-
humanoidMesh:
Mesh
- MMDメタデータを格納するメッシュ。このメッシュはダックタイピングを通じてMMDモデルとして扱われます。
MmdModel
が作成された後、このメッシュはMmdSkinnedMesh
インターフェースを満たします。
-
meshes:
readonly Mesh[]
- ヒューマノイドモデルを構成するメッシュの配列。
HumanoidMmd
は、MmdModel
の初期化時にこのメッシュ配列でスケルトンとモーフターゲットマージャーを検索します。 - したがって、モーフターゲットアニメーションを使用したい場合は、モーフターゲットを含むメッシュをこの配列に含める必要があります。
- ヒューマノイドモデルを構成するメッシュの配列。
-
options:
ICreateMmdModelFromHumanoidOptions
- boneMap:
{ [key: string]: string }
- ヒューマノイドモデルのボーン名マップ。
- UnityのHumanoid Rigはボーン名を特定の文字列に固定しないため、ユーザーはボーン名マップを直接指定する必要があります。
- morphMap:
{ [key: string]: string }
- ヒューマノイドモデルのモーフターゲット名マップ。
- ヒューマノイドモデルに「あ」、「い」、「う」、「え」、「お」などのMMDモーフに相当するモーフターゲットが含まれている場合、このオプションを使用してそれらをマッピングし、モーフターゲット名マップを指定できます。
- このオプションが指定されない場合、MMDモーフと同じ名前のモーフターゲットを探します。
- transformOffset?:
Matrix
- ヒューマノイドモデルのルートボーンに適用するトランスフォームマトリックス。
- このオプションは、モデルのワールドトランスフォームがレストポーズで特定の方向に回転している場合に必要です。
- 例えば、GLTFモデルはBabylon.jsにインポートされる際にy軸周りに180度の回転がルートノードに適用されるため、このオプションを使用してスケルトンのルートノードを指定する必要があります。
- また、一部のモデルはアイデンティティではないスケルトントランスフォームを持っています。この場合も、このオプションを使用してレストポーズのワールドトランスフォームを修正できます。
- boneMap:
すべてのオプションは慎重に設定する必要があります。boneMapが間違っていたり、transformOffsetが不適切に設定されている場合、MMDアニメーションがヒューマノイドモデルに正しく適用されない可能性があります。
レストポーズ設定
また、モデルのレストポーズをAポーズに設定する必要があります。
HumanoidMmd
は、バインディング時のポーズをレストポーズとして考慮します。
したがって、モデルがTポーズの場合、バインディング前に腕の角度を調整してAポーズを作成する必要があります。
以下のコードは、腕をAポーズに調整する例です:
const modelMesh = modelLoadResult.meshes[1] as Mesh;
{
const transformNodes = modelLoadResult.transformNodes;
const leftArm = transformNodes.find((transformNode) => transformNode.name === "LeftUpperArm")!;
const rightArm = transformNodes.find((transformNode) => transformNode.name === "RightUpperArm")!;
const degToRad = Math.PI / 180;
leftArm.rotationQuaternion = leftArm.rotationQuaternion!.multiply(Quaternion.FromEulerAngles(0, 0, -35 * degToRad));
rightArm.rotationQuaternion = rightArm.rotationQuaternion!.multiply(Quaternion.FromEulerAngles(0, 0, 35 * degToRad));
}
アプリケーション例
以下は、babylon-mmdのヒューマノイドモデルサポート機能を使用してヒューマノイドモデルにMMDアニメーションを適用する例です:
あまとうさぎさんのカリンです
これで、babylon-mmdはpmx/pmdモデルだけでなくヒューマノイドモデルもサポートします
仮想mmdスケルトンを構築した後、ランタイムにリターゲティングを行う構造です。 https://t.co/1D5mR2FpQl pic.twitter.com/AoRirjzVj4
— noname0310 (@noname20310) October 4, 2023
モデル: あまとうさぎのカリン
このデモのコードはbabylon-mmdのテストコードで確認できます。
制限事項
- ヒューマノイドMMDにはハードコードされてアドホックに実装された部分が多くあります。そのため、すべてのヒューマノイドモデルで完璧に動作しない可能性があります。
- ヒューマノイドMMDはリアルタイムでリターゲティングを実行するため、MMDモデルと比較してパフォーマンスが低下する可能性があります。
- ヒューマノイドMMDは物理シミュレーションを処理しません。非MMDモデルに物理シミュレーションを適用したい場合は、シミュレーションソルバーを自分で実装する必要があります。
したがって、可能な場合は、非MMDモデルをPMXフォーマットに変換してMMDモデルとして使用することが推奨されます。