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);