glTF-2.0のバイナリ形式glbをベースにした、VR向けモデルフォーマットです。 VRM仕様のリポジトリはこちら:VRM specification。
- 20181109: JsonShcemaの
Vector3
のタイプが誤ってarray
になっていた部分を修正
{
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
}
}
- 拡張子
- Json拡張
- VRM拡張: VRMバージョンなど
- 保存できる要素
- 保存する値に対する規約
- VRMが提供するシェーダー
- VRM拡張: モデルのボーンマッピング(json.extensions.VRM.humanoid)
- VRM拡張: モデル情報(json.extensions.VRM.meta)
- VRM拡張: モーフ設定(json.extensions.VRM.blendShapeMaster)
- VRM拡張: 一人称設定(json.extensions.VRM.firstPerson)
- VRM拡張: 揺れモノ設定(json.extensions.VRM.secondaryAnimation)
.vrm
を使います。
gltfのバイナリ形式.glb
と互換性があるので、拡張子を.glb
に変更するとGLTF対応のアプリケーションで読み込むことができます(VRM独自の追加情報は無くなります)。
GLBのJSON部にVRM Extension
として拡張しています。
{
"extensionsUsed": {
"VRM"
},
"extensions": {
"VRM": {
// VRMの拡張情報
}
},
// 通常のGLTF-2.0の情報
}
仕様のJsonSchemaを作成しました
GLTF-2.0のJsonSchema
/extensions/VRM/exporterVersion
はv0.36から
{
"title": "vrm",
"description": "VRM extension is for 3d humanoid avatars (and models) in VR applications.",
"type": "object",
"properties": {
"exporterVersion": {
"description": "Version of exporter that vrm created. UniVRM-0.42",
"type": "string"
},
"meta": {
"$ref": "vrm.meta.schema.json"
},
"humanoid": {
"$ref": "vrm.humanoid.schema.json"
},
"firstPerson": {
"$ref": "vrm.firstperson.schema.json"
},
"blendShapeMaster": {
"$ref": "vrm.blendshape.schema.json"
},
"secondaryAnimation": {
"$ref": "vrm.secondaryanimation.schema.json"
},
"materialProperties": {
"type": "array",
"items": {
"$ref": "vrm.material.schema.json"
}
}
}
}
人間型モデル一体分の情報を保存します。
- GLTF-2.0の
/textures/
VRM拡張はありません。
- GLTF-2.0の
/materials/
GLTFのマテリアルにフォールバックした情報を保存しています(拡張子をGLBに変更した場合に使われる)。
VRM独自のマテリアル情報を保存しています。 現状、Unityに必要な項目を保存しています。 選択可能なShaderは、VRMが提供するシェーダーを参照してください。
{
"title": "vrm.material",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"shader": {
"type": "string"
},
"renderQueue": {
"type": "integer"
},
"floatProperties": {
"type": "object"
},
"vectorProperties": {
"type": "object"
},
"textureProperties": {
"type": "object"
},
"keywordMap": {
"type": "object"
},
"tagMap": {
"type": "object"
}
}
}
- GLTF-2.0の
/meshes/
VRM拡張はありません。
-
GLTF-2.0の
/meshes/*/primitives/*/attributes
- TANGENT (vec4) // v0.42から保存するのをやめて、import時にnormalとuvから計算するようにしています。
/meshes/*/primitives/*/extras/targetNames
にMoprhTargetの名称を記録しています。
- GLTF-2.0の
/skins/
VRM拡張はありません。
- GLTF-2.0の
/nodes/
VRM拡張はありません。
- node
- name
- position(vec3)
- rotation(quaternion)
- scale(vec3)
GLTF2の規約に準拠します。 特に重要な項目です。
- メートル単位
- 右手Y-UP座標系1
人間型モデルに特化して互換性を高めるために、以下の制約を課します。
- モデルは原点に位置する
- モデルは-Z向き1
- モデルのヒエラルキーはY-UP2
- モデルのメッシュはY-UP2
- モデルのヒエラルキーはT-Pose
- モデルのメッシュはT-Pose
- ボーンに回転を入れない
- ボーンにスケールを入れない
- ヘッドボーンは真正面を向いている3
セル調のキャラクタモデルの運用を想定して以下のシェーダーを用意しています。
ライティング・シェーディングせずにテクスチャ色をそのまま表示します。 半透明の扱い別に4種類を用意しています。
- UnlitTexture(不透明)
- UnlitCutout(透明度が閾値以下の部分を透明とする)
- UnlitTransparent(アルファブレンド。ZWriteしない)4
- UnlitTransparentZWrite(アルファブレンド。ZWriteする)5
セルシェーディング、輪郭線に対応したシェーダー。 Unlitよりもきめ細かく設定できます。
NodeとHumanoidで定義される標準ボーンの対応表です。
{
"title": "vrm.humanoid.bone",
"type": "object",
"properties": {
"bone": {
"description": "Human bone name.",
"type": "string",
"enum": ["hips","leftUpperLeg","rightUpperLeg","leftLowerLeg","rightLowerLeg","leftFoot","rightFoot","spine","chest","neck","head","leftShoulder","rightShoulder","leftUpperArm","rightUpperArm","leftLowerArm","rightLowerArm","leftHand","rightHand","leftToes","rightToes","leftEye","rightEye","jaw","leftThumbProximal","leftThumbIntermediate","leftThumbDistal","leftIndexProximal","leftIndexIntermediate","leftIndexDistal","leftMiddleProximal","leftMiddleIntermediate","leftMiddleDistal","leftRingProximal","leftRingIntermediate","leftRingDistal","leftLittleProximal","leftLittleIntermediate","leftLittleDistal","rightThumbProximal","rightThumbIntermediate","rightThumbDistal","rightIndexProximal","rightIndexIntermediate","rightIndexDistal","rightMiddleProximal","rightMiddleIntermediate","rightMiddleDistal","rightRingProximal","rightRingIntermediate","rightRingDistal","rightLittleProximal","rightLittleIntermediate","rightLittleDistal","upperChest"]
},
"node": {
"description": "Reference node index",
"type": "integer"
},
"useDefaultValues": {
"description": "Unity's HumanLimit.useDefaultValues",
"type": "boolean"
},
"min": {
"description": "Unity's HumanLimit.min",
"type": "array"
},
"max": {
"description": "Unity's HumanLimit.max",
"type": "array"
},
"center": {
"description": "Unity's HumanLimit.center",
"type": "array"
},
"axisLength": {
"description": "Unity's HumanLimit.axisLength",
"type": "number"
}
}
}
ボーン名前 | 必須・オプション |
---|---|
neck | 必須 |
head | 必須 |
left/right Eye | オプション |
jaw | オプション |
hips | 必須 |
spine | 必須 |
chest | 必須 |
upperChest | オプション |
left/right Shoulder | オプション |
left/right UpperArm | 必須 |
left/right LowerArm | 必須 |
left/right Hand | 必須 |
left/right UpperLeg | 必須 |
left/right LowerLeg | 必須 |
left/right Foot | 必須 |
left/right Toe | オプション |
left/right Thumb Proximal, Intermediate, Distal | オプション |
left/right Index Proximal, Intermediate, Distal | オプション |
left/right Middle Proximal, Intermediate, Distal | オプション |
left/right Ring Proximal, Intermediate, Distal | オプション |
left/right Little Proximal, Intermediate, Distal | オプション |
{
"title": "vrm.meta",
"type": "object",
"properties": {
"title": {
"description": "Title of VRM model",
"type": "string"
},
"version": {
"description": "Version of VRM model",
"type": "string"
},
"author": {
"description": "Author of VRM model",
"type": "string"
},
"contactInformation": {
"description": "Contact Information of VRM model author",
"type": "string"
},
"reference": {
"description": "Reference of VRM model",
"type": "string"
},
"texture": {
"description": "Thumbnail of VRM model",
"type": "integer"
},
"allowedUserName": {
"description": "A person who can perform with this avatar",
"type": "string",
"enum": ["OnlyAuthor","ExplicitlyLicensedPerson","Everyone"]
},
"violentUssageName": {
"description": "Permission to perform violent acts with this avatar",
"type": "string",
"enum": ["Disallow","Allow"]
},
"sexualUssageName": {
"description": "Permission to perform sexual acts with this avatar",
"type": "string",
"enum": ["Disallow","Allow"]
},
"commercialUssageName": {
"description": "For commercial use",
"type": "string",
"enum": ["Disallow","Allow"]
},
"otherPermissionUrl": {
"description": "If there are any conditions not mentioned above, put the URL link of the license document here.",
"type": "string"
},
"licenseName": {
"description": "License type",
"type": "string",
"enum": ["Redistribution_Prohibited","CC0","CC_BY","CC_BY_NC","CC_BY_SA","CC_BY_NC_SA","CC_BY_ND","CC_BY_NC_ND","Other"]
},
"otherLicenseUrl": {
"description": "If “Other” is selected, put the URL link of the license document here.",
"type": "string"
}
}
}
アバターモデルの名前を設定します
モデルの作者の名前を記述します
モデルの作者への連絡先を記述します
何か「親作品」に相当するものがある場合は参照URLなどを記述します
アバターモデルのサムネイルを登録します。2048x2048程度の解像度テクスチャを推奨します。meta情報内ではtexture番号を指定します。
モデルの作成バージョンです。
License
Personation / Charaterization Permission
A person who can perform with this avatar
- アバターを操作することはアバター作者にのみ許される(Only Author)
- 明確に許可された人限定(Explictly Licensed Person)
- 全員に許可(Everyone)
Violent acts using this avatar
- 不許可(Disallow)
- 許可(Allow)
Sexuality acts using this avatar
- 不許可(Disallow)
- 許可(Allow)
For commercial use
- 不許可(Disallow)
- 許可(Allow)
Other License Url
上記許諾条件以外のライセンス条件がある場合はそのライセンス文書へのURLを記述
Redistribution / Modifications License
License Type
- 再配布禁止(Redistribution Prohibited)
- 著作権放棄(CC0)
- Creative Commons CC BYライセンス(CC_BY)
- Creative Commons CC BY NCライセンス(CC_BY_NC)
- Creative Commons CC BY SAライセンス(CC_BY_SA)
- Creative Commons CC BY NC SAライセンス(CC_BY_NC_SA)
- Creative Commons CC BY NDライセンス(CC_BY_ND)
- Creative Commons CC BY NC NDライセンス(CC_BY_NC_ND)
- その他(Other)
Other License Url
上記許諾条件以外のライセンス条件がある場合はそのライセンス文書へのURLを記述
BlendShapeをグループ化するBlendShapeGroupの配列を設定します。
{
"title": "vrm.blendshape",
"type": "object",
"properties": {
"blendShapeGroups": {
"type": "array",
"items": {
"$ref": "vrm.blendshape.group.schema.json"
}
}
}
}
{
"title": "vrm.blendshape.group",
"type": "object",
"properties": {
"name": {
"description": "Expression name",
"type": "string"
},
"presetName": {
"description": "Predefined Expression name",
"type": "string",
"enum": ["Neutral","A","I","U","E","O","Blink","Joy","Angry","Sorrow","Fun","LookUp","LookDown","LookLeft","LookRight","Blink_L","Blink_R"]
},
"binds": {
"description": "Low level blendshape references.",
"type": "array",
"items": {
"$ref": "vrm.blendshape.bind.schema.json"
}
},
"materialValues": {
"description": "Material animation references.",
"type": "array",
"items": {
"$ref": "vrm.blendshape.materialbind.schema.json"
}
}
}
}
{
"title": "vrm.blendshape.bind",
"type": "object",
"properties": {
"mesh": {
"type": "integer"
},
"index": {
"type": "integer"
},
"weight": {
"type": "number"
}
}
}
{
"title": "vrm.blendshape.materialbind",
"type": "object",
"properties": {
"materialName": {
"type": "string"
},
"propertyName": {
"type": "string"
},
"targetValue": {
"type": "array",
"items": {
"type": "number"
}
}
}
}
名前です。事前定義名と同じ(大文字)を推奨します
待機状態の表情
- Neutral
リップシンク
- A
- I
- U
- E
- O
瞬き
- Blink
- Blink_L
- Blink_R
喜怒哀楽
- Fun
- Angry
- Sorrow
- Joy
視線制御
- LookUp
- LookDown
- LookLeft
- LookRight
その他
- Unknown
システムからブレンドシェイプを一意に認識する文字列IDを以下のロジックで決定します。
// 疑似コード
function GetID(preset, name)
{
if (Preset != BlendShapePreset.Unknown)
{
return preset.ToString().ToUpper();
}
else
{
return name.ToUpper();
}
}
- ブレンドシェイプIDがユニークになるようにPresetとNameを設定する
{
"title": "vrm.firstperson",
"type": "object",
"properties": {
"firstPersonBone": {
"description": "The bone whose rendering should be turned off in first-person view. Usually Head is specified.",
"type": "integer"
},
"firstPersonBoneOffset": {
"description": "The target position of the VR headset in first-person view. It is assumed that an offset from the head bone to the VR headset is added.",
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
}
}
},
"meshAnnotations": {
"description": "Switch display \/ undisplay for each mesh in first-person view or the others.",
"type": "array",
"items": {
"$ref": "vrm.firstperson.meshannotation.schema.json"
}
},
"lookAtTypeName": {
"description": "Eye controller mode.",
"type": "string",
"enum": ["Bone","BlendShape"]
},
"lookAtHorizontalInner": {
"$ref": "vrm.firstperson.degreemap.schema.json"
},
"lookAtHorizontalOuter": {
"$ref": "vrm.firstperson.degreemap.schema.json"
},
"lookAtVerticalDown": {
"$ref": "vrm.firstperson.degreemap.schema.json"
},
"lookAtVerticalUp": {
"$ref": "vrm.firstperson.degreemap.schema.json"
}
}
}
一人称視点のアバターを描画する場合、自モデルの頭部の中が見えてしまうという問題が生じます6。 これに対応するために、一人称時の表示状態を指定できます。
一人称時に描画を切り替えるべきボーンを指定します。通常Head
です。
一人時のヘッドセットの目標位置。 頭ボーンからヘッドセットへのオフセットを加味することを想定している。
各メッシュに対して一人称時とそれ以外で表示・非表示を切り替えることができます。 以下の設定があります。
- Auto: firstPersonBoneとその子孫に対するボーンWeightを持つポリゴンを自動で非表示にする7
- FirstPersonOnly: 一人称のみ表示
- ThirdPersonOnly: 三人称のみ表示(頭など一人称時に非表示にするメッシュに指定する)
- Both: 特に表示切替をしない
ターゲットの方向を向くようにキャラクタの視線を制御します。
- Bone: ボーンにより目線を操作します。
- BlendShape: BlendShapeにより目線を操作します。BlendShapePreset.LookUp, LookDown, LookLeft, LookRightを使います。
頭と目標物の角度差を目ボーンに適用する場合の角度を調整します。
尻尾や髪の毛などのひも状のオブジェクトの自動アニメーションの設定です。
{
"title": "vrm.secondaryanimation",
"type": "object",
"properties": {
"boneGroups": {
"type": "array",
"items": {
"$ref": "vrm.secondaryanimation.spring.schema.json"
}
},
"colliderGroups": {
"type": "array",
"items": {
"$ref": "vrm.secondaryanimation.collidergroup.schema.json"
}
}
}
}
{
"title": "vrm.secondaryanimation.spring",
"type": "object",
"properties": {
"comment": {
"description": "Annotation comment",
"type": "string"
},
"stiffiness": {
"description": "The resilience of the swaying object (the power of returning to the initial pose).",
"type": "number"
},
"gravityPower": {
"description": "The strength of gravity.",
"type": "number"
},
"gravityDir": {
"description": "The direction of gravity. Set (0, -1, 0) for simulating the gravity. Set (1, 0, 0) for simulating the wind.",
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
}
}
},
"dragForce": {
"description": "The resistance (deceleration) of automatic animation.",
"type": "number"
},
"center": {
"description": "The reference point of a swaying object can be set at any location except the origin. When implementing UI moving with warp, the parent node to move with warp can be specified if you don't want to make the object swaying with warp movement.",
"type": "integer"
},
"hitRadius": {
"description": "The radius of the sphere used for the collision detection with colliders.",
"type": "number"
},
"bones": {
"description": "Specify the node index of the root bone of the swaying object.",
"type": "array",
"items": {
"type": "integer"
}
},
"colliderGroups": {
"description": "Specify the index of the collider group for collisions with swaying objects.",
"type": "array",
"items": {
"type": "integer"
}
}
}
}
揺れモノの根元のボーンのノードインデックスを指定します。
揺れモノに対する衝突判定グループのインデックスを指定します。
world原点以外の、揺れモノの基準点を設定できます。 ワープで移動するUIを実装した場合に、ワープ移動で揺れモノを揺らしたくない場合にワープで移動する親ノードを指定できます。
自動アニメーションの抵抗(減速)です。
重力の方向です。(0, -1, 0)にすると重力に、(1, 0, 0)にすると風のように作用します。
重力の強さです。
Colliderとの当たり判定の半径です
揺れモノの復元力(初期姿勢に戻る力)です
揺れモノと衝突する球を設定します。
{
"title": "vrm.secondaryanimation.collidergroup",
"type": "object",
"properties": {
"node": {
"description": "The node of the collider group for setting up collision detections.",
"type": "integer"
},
"colliders": {
"type": "array",
"items": {
"type": "object",
"properties": {
"offset": {
"description": "The local coordinate from the node of the collider group.",
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
}
}
},
"radius": {
"description": "The radius of the collider.",
"type": "number"
}
}
}
}
}
}
当たり判定を設置するノードです。
当たり判定のノードからのローカル座標です。
当たり判定の半径です。