diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/ControlRigGenerationOption.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/ControlRigGenerationOption.cs index b5a09268a..d99dfc4de 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/ControlRigGenerationOption.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/ControlRigGenerationOption.cs @@ -24,6 +24,13 @@ namespace UniVRM10 /// https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_hand_tracking /// Vrm0XCompatibleWithXR_EXT_hand_tracking = 2, + + /// + /// コントロールリグのボーン Transform を生成し、Root の Animator はコントロールリグのボーンを制御するようになります。 + /// 上半身に関して、XR_FB_body_tracking の初期回転を持ちます。 + /// https://developer.oculus.com/documentation/native/android/move-ref-body-joints/ + /// + Vrm0XCompatibleWithXR_FB_body_tracking = 3, } internal static class ControlRigGenerationOptionExtensions @@ -42,6 +49,9 @@ namespace UniVRM10 case ControlRigGenerationOption.Vrm0XCompatibleWithXR_EXT_hand_tracking: return XR_EXT_hand_tracking.InitialRotations; + case ControlRigGenerationOption.Vrm0XCompatibleWithXR_FB_body_tracking: + return XR_FB_body_tracking.InitialRotations; + default: throw new ArgumentException(); } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs new file mode 100644 index 000000000..296cee4e8 --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UniVRM10 +{ + /// + /// XR_FB_body_tracking の joint を VRM-1.0 の TPose に当てはめたときの方向を定義します。 + /// + /// * https://developer.oculus.com/documentation/native/android/move-ref-body-joints/ + /// + /// OpenXR は右手系なのに対して Unityは左手系です。 + /// この Rig が期待するボーンの値は、XR_FB_body_tracking の Joint の値を Z軸反転で座標変換したものです。 + /// + public static class XR_FB_body_tracking + { + /// + /// up vector と forward vector の外積により空間を算出して、回転を得ます。 + /// + /// + /// + /// + public static Quaternion GetRotation(Vector3 yAxis, Vector3 zAxis) + { + var xAxis = Vector3.Cross(yAxis, zAxis).normalized; + var m = new Matrix4x4(xAxis, yAxis, zAxis, new Vector4(0, 0, 0, 1)); + return m.rotation; + } + + public static Quaternion Spine = GetRotation(Vector3.forward, Vector3.left); + + public static Quaternion Left = GetRotation(Vector3.forward, Vector3.down); + public static Quaternion LeftThumb = GetRotation((Vector3.left + Vector3.back).normalized, Vector3.up); + public static Quaternion LeftHand = GetRotation(Vector3.down, Vector3.back); + + public static Quaternion Right = GetRotation(Vector3.back, Vector3.up); + public static Quaternion RightThumb = GetRotation((Vector3.left + Vector3.forward).normalized, Vector3.down); + public static Quaternion RightHand = GetRotation(Vector3.up, Vector3.forward); + + public static IReadOnlyDictionary InitialRotations => new Dictionary() + { + {HumanBodyBones.Hips, Spine}, + {HumanBodyBones.Spine, Spine}, + {HumanBodyBones.Chest, Spine}, + {HumanBodyBones.UpperChest, Spine}, + {HumanBodyBones.Neck, Spine}, + {HumanBodyBones.Head, Spine}, + {HumanBodyBones.LeftShoulder, Left}, + {HumanBodyBones.LeftUpperArm, Left}, + {HumanBodyBones.LeftLowerArm, Left}, + {HumanBodyBones.RightShoulder, Right}, + {HumanBodyBones.RightUpperArm, Right}, + {HumanBodyBones.RightLowerArm, Right}, + // left + {HumanBodyBones.LeftHand, LeftHand}, + {HumanBodyBones.LeftThumbProximal, LeftThumb}, + {HumanBodyBones.LeftThumbIntermediate, LeftThumb}, + {HumanBodyBones.LeftThumbDistal, LeftThumb}, + {HumanBodyBones.LeftIndexProximal, LeftHand}, + {HumanBodyBones.LeftIndexIntermediate, LeftHand}, + {HumanBodyBones.LeftIndexDistal, LeftHand}, + {HumanBodyBones.LeftMiddleProximal, LeftHand}, + {HumanBodyBones.LeftMiddleIntermediate, LeftHand}, + {HumanBodyBones.LeftMiddleDistal, LeftHand}, + {HumanBodyBones.LeftRingProximal, LeftHand}, + {HumanBodyBones.LeftRingIntermediate, LeftHand}, + {HumanBodyBones.LeftRingDistal, LeftHand}, + {HumanBodyBones.LeftLittleProximal, LeftHand}, + {HumanBodyBones.LeftLittleIntermediate, LeftHand}, + {HumanBodyBones.LeftLittleDistal, LeftHand}, + // right + {HumanBodyBones.RightHand, RightHand}, + {HumanBodyBones.RightThumbProximal, RightThumb}, + {HumanBodyBones.RightThumbIntermediate, RightThumb}, + {HumanBodyBones.RightThumbDistal, RightThumb}, + {HumanBodyBones.RightIndexProximal, RightHand}, + {HumanBodyBones.RightIndexIntermediate, RightHand}, + {HumanBodyBones.RightIndexDistal, RightHand}, + {HumanBodyBones.RightMiddleProximal, RightHand}, + {HumanBodyBones.RightMiddleIntermediate, RightHand}, + {HumanBodyBones.RightMiddleDistal, RightHand}, + {HumanBodyBones.RightRingProximal, RightHand}, + {HumanBodyBones.RightRingIntermediate, RightHand}, + {HumanBodyBones.RightRingDistal, RightHand}, + {HumanBodyBones.RightLittleProximal, RightHand}, + {HumanBodyBones.RightLittleIntermediate, RightHand}, + {HumanBodyBones.RightLittleDistal, RightHand}, + }; + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs.meta new file mode 100644 index 000000000..4e602f484 --- /dev/null +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Rigs/XR_FB_body_tracking.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4e5ee6aa707a2044a9903133bbf085f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: