diff --git a/Assets/VRM10/Runtime/Components/Constraint/IVrm10Constraint.cs b/Assets/VRM10/Runtime/Components/Constraint/IVrm10Constraint.cs index 774e0597f..06a32e255 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/IVrm10Constraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/IVrm10Constraint.cs @@ -1,11 +1,15 @@ +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 { public interface IVrm10Constraint { - internal void Process(); + Transform ConstraintDst { get; } + Transform ConstriantSrc { get; } - GameObject ConstraintTarget { get; } + /// + /// + internal void Process(in TransformState dstInitState, in TransformState srcInitState); } } diff --git a/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs index 9f500a774..524849bcb 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs @@ -1,5 +1,6 @@ using System; using UniGLTF.Extensions.VRMC_node_constraint; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 @@ -10,8 +11,6 @@ namespace UniVRM10 [DisallowMultipleComponent] public class Vrm10AimConstraint : MonoBehaviour, IVrm10Constraint { - public GameObject ConstraintTarget => gameObject; - [SerializeField] public Transform Source = default; @@ -36,18 +35,10 @@ namespace UniVRM10 } } - Quaternion _dstRestLocalQuat; + Transform IVrm10Constraint.ConstraintDst => transform; - void Start() - { - if (Source == null) - { - this.enabled = false; - return; - } + Transform IVrm10Constraint.ConstriantSrc => Source; - _dstRestLocalQuat = transform.localRotation; - } /// /// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_beta/README.ja.md#example-of-implementation-1 /// @@ -60,19 +51,17 @@ namespace UniVRM10 /// weight /// ) /// - void IVrm10Constraint.Process() + void IVrm10Constraint.Process(in TransformState dstInitState, in TransformState srcInitState) { - if (Source == null) return; - // world coords var dstParentWorldQuat = transform.parent != null ? transform.parent.rotation : Quaternion.identity; - var fromVec = (dstParentWorldQuat * _dstRestLocalQuat) * GetAxisVector(); + var fromVec = (dstParentWorldQuat * dstInitState.LocalRotation) * GetAxisVector(); var toVec = (Source.position - transform.position).normalized; var fromToQuat = Quaternion.FromToRotation(fromVec, toVec); transform.localRotation = Quaternion.SlerpUnclamped( - _dstRestLocalQuat, - Quaternion.Inverse(dstParentWorldQuat) * fromToQuat * dstParentWorldQuat * _dstRestLocalQuat, + dstInitState.LocalRotation, + Quaternion.Inverse(dstParentWorldQuat) * fromToQuat * dstParentWorldQuat * dstInitState.LocalRotation, Weight ); } diff --git a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs index ce0f0f27f..2bc949faa 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs @@ -1,5 +1,6 @@ using System; using UniGLTF.Extensions.VRMC_node_constraint; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 @@ -10,8 +11,6 @@ namespace UniVRM10 [DisallowMultipleComponent] public class Vrm10RollConstraint : MonoBehaviour, IVrm10Constraint { - public GameObject ConstraintTarget => gameObject; - [SerializeField] public Transform Source = default; @@ -32,20 +31,10 @@ namespace UniVRM10 } } - Quaternion _srcRestLocalQuat; - Quaternion _dstRestLocalQuat; + Transform IVrm10Constraint.ConstraintDst => transform; - void Start() - { - if (Source == null) - { - this.enabled = false; - return; - } + Transform IVrm10Constraint.ConstriantSrc => Source?.transform; - _srcRestLocalQuat = Source.localRotation; - _dstRestLocalQuat = transform.localRotation; - } /// /// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_beta/README.ja.md#example-of-implementation /// @@ -62,21 +51,19 @@ namespace UniVRM10 /// weight /// ) /// - void IVrm10Constraint.Process() + void IVrm10Constraint.Process(in TransformState dstInitState, in TransformState srcInitState) { - if (Source == null) return; - - var deltaSrcQuat = Quaternion.Inverse(_srcRestLocalQuat) * Source.localRotation; - var deltaSrcQuatInParent = _srcRestLocalQuat * deltaSrcQuat * Quaternion.Inverse(_srcRestLocalQuat); // source to parent - var deltaSrcQuatInDst = Quaternion.Inverse(_dstRestLocalQuat) * deltaSrcQuatInParent * _dstRestLocalQuat; // parent to destination + var deltaSrcQuat = Quaternion.Inverse(srcInitState.LocalRotation) * Source.localRotation; + var deltaSrcQuatInParent = srcInitState.LocalRotation * deltaSrcQuat * Quaternion.Inverse(srcInitState.LocalRotation); // source to parent + var deltaSrcQuatInDst = Quaternion.Inverse(dstInitState.LocalRotation) * deltaSrcQuatInParent * dstInitState.LocalRotation; // parent to destination var rollAxis = GetRollVector(); var toVec = deltaSrcQuatInDst * rollAxis; var fromToQuat = Quaternion.FromToRotation(rollAxis, toVec); transform.localRotation = Quaternion.SlerpUnclamped( - _dstRestLocalQuat, - _dstRestLocalQuat * Quaternion.Inverse(fromToQuat) * deltaSrcQuatInDst, + dstInitState.LocalRotation, + dstInitState.LocalRotation * Quaternion.Inverse(fromToQuat) * deltaSrcQuatInDst, Weight ); } diff --git a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RotationConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RotationConstraint.cs index a98a608e5..9b3311322 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RotationConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RotationConstraint.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using UniGLTF.Utils; +using UnityEngine; namespace UniVRM10 { @@ -8,7 +9,9 @@ namespace UniVRM10 [DisallowMultipleComponent] public class Vrm10RotationConstraint : MonoBehaviour, IVrm10Constraint { - public GameObject ConstraintTarget => gameObject; + Transform IVrm10Constraint.ConstraintDst => transform; + + Transform IVrm10Constraint.ConstriantSrc => Source; [SerializeField] public Transform Source = default; @@ -17,21 +20,6 @@ namespace UniVRM10 [Range(0, 1.0f)] public float Weight = 1.0f; - Quaternion _srcRestLocalQuatInverse; - Quaternion _dstRestLocalQuat; - - void Start() - { - if (Source == null) - { - this.enabled = false; - return; - } - - _srcRestLocalQuatInverse = Quaternion.Inverse(Source.localRotation); - _dstRestLocalQuat = transform.localRotation; - } - /// /// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_beta/README.ja.md#example-of-implementation-2 /// @@ -42,13 +30,11 @@ namespace UniVRM10 /// weight /// ) /// - void IVrm10Constraint.Process() + void IVrm10Constraint.Process(in TransformState dstInitState, in TransformState srcInitState) { - if (Source == null) return; - // local coords - var srcDeltaLocalQuat = _srcRestLocalQuatInverse * Source.localRotation; - transform.localRotation = Quaternion.SlerpUnclamped(_dstRestLocalQuat, _dstRestLocalQuat * srcDeltaLocalQuat, Weight); + var srcDeltaLocalQuat = Quaternion.Inverse(srcInitState.LocalRotation) * Source.localRotation; + transform.localRotation = Quaternion.SlerpUnclamped(dstInitState.LocalRotation, dstInitState.LocalRotation * srcDeltaLocalQuat, Weight); } } } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index c1d9ea8a4..80da841ec 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; using UniGLTF; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 @@ -46,14 +49,26 @@ namespace UniVRM10 } } + Dictionary _initPose; + public Vrm10Runtime(Vrm10Instance instance, bool useControlRig, IVrm10SpringBoneRuntime springBoneRuntime) { if (!Application.isPlaying) { UniGLTFLogger.Warning($"{nameof(Vrm10Runtime)} expects runtime behaviour."); } + if (instance == null) + { + m_instance = null; + return; + } - m_instance = instance; + if (m_instance != instance) + { + m_instance = instance; + var runtime = m_instance.GetComponent(); + _initPose = runtime.InitialTransformStates.ToDictionary((kv) => kv.Key, (kv) => kv.Value); + } if (!instance.TryGetBoneTransform(HumanBodyBones.Head, out m_head)) { @@ -121,7 +136,12 @@ namespace UniVRM10 // 3. Constraints foreach (var constraint in Constraints) { - constraint.Process(); + if (constraint.ConstriantSrc != null) + { + constraint.Process( + dstInitState: _initPose[constraint.ConstraintDst], + srcInitState: _initPose[constraint.ConstriantSrc]); + } } if (m_instance.LookAtTargetType == VRM10ObjectLookAt.LookAtTargetTypes.SpecifiedTransform diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index db12de492..6eb80dcc5 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -601,7 +601,7 @@ namespace UniVRM10 } // serialize to gltfNode - var node = converter.Nodes[constraint.ConstraintTarget]; + var node = converter.Nodes[constraint.ConstraintDst.gameObject]; var nodeIndex = model.Nodes.IndexOf(node); var gltfNode = nodes[nodeIndex]; UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint);