From d2f17b925772a46416e69cf4f839911bda603f09 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 12 Apr 2022 15:04:12 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BB=95=E6=A7=98=E3=81=AB=E6=BA=96=E6=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VRM10/Editor/VRM10RotationOffsetDrawer.cs | 28 --------- .../Editor/VRM10RotationOffsetDrawer.cs.meta | 11 ---- .../Constraint/VRM10RotationConstraint.cs | 31 +++++++++- .../Constraint/VRM10RotationOffset.cs | 17 ----- .../Constraint/VRM10RotationOffset.cs.meta | 11 ---- .../Constraint/Vrm10AimConstraint.cs | 58 ++++++++++++++++- .../Constraint/Vrm10RollConstraint.cs | 62 ++++++++++++++++++- 7 files changed, 144 insertions(+), 74 deletions(-) delete mode 100644 Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs delete mode 100644 Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs.meta delete mode 100644 Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs delete mode 100644 Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs.meta diff --git a/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs b/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs deleted file mode 100644 index a893ecbe7..000000000 --- a/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs +++ /dev/null @@ -1,28 +0,0 @@ - -using UnityEditor; -using UnityEngine; - -namespace UniVRM10 -{ - [CustomPropertyDrawer(typeof(VRM10RotationOffset))] - public class IngredientDrawer : PropertyDrawer - { - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return 16f + 18f; - } - - // Draw the property inside the given rect - void DrawEuler(Rect position, SerializedProperty property) - { - Vector3 euler = property.quaternionValue.eulerAngles; - euler = EditorGUI.Vector3Field(position, "Offset", euler); - property.quaternionValue = Quaternion.Euler(euler); - } - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - DrawEuler(position, property.FindPropertyRelative(nameof(VRM10RotationOffset.Rotation))); - } - } -} diff --git a/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs.meta b/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs.meta deleted file mode 100644 index 2f04a1587..000000000 --- a/Assets/VRM10/Editor/VRM10RotationOffsetDrawer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 615a7cbd2c3cd5d42ab2719d6e74c1b8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs index cdb0ada3f..e395506bf 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs @@ -15,9 +15,38 @@ namespace UniVRM10 [Range(0, 10.0f)] public float Weight = 1.0f; + Quaternion _srcRestLocalQuatInverse; + Quaternion _dstRestLocalQuat; + + void Awake() + { + 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_draft/README.ja.md#example-of-implementation-2 + /// + /// srcDeltaQuat = srcRestQuat.inverse * srcQuat + /// targetQuat = Quaternion.slerp( + /// dstRestQuat, + /// dstRestQuat * srcDeltaQuat, + /// weight + /// ) + /// public override void Process() { - throw new System.NotImplementedException(); + if (Source == null) return; + + // local coords + var srcDeltaLocalQuat = _srcRestLocalQuatInverse * Source.localRotation; + transform.localRotation = Quaternion.SlerpUnclamped(_dstRestLocalQuat, _dstRestLocalQuat * srcDeltaLocalQuat, Weight); } } } diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs deleted file mode 100644 index a6382b5f1..000000000 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using UnityEngine; - -namespace UniVRM10 -{ - [Serializable] - public struct VRM10RotationOffset - { - [SerializeField] - public Quaternion Rotation; - - public static VRM10RotationOffset Identity => new VRM10RotationOffset - { - Rotation = Quaternion.identity, - }; - } -} diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs.meta b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs.meta deleted file mode 100644 index 4fc95a462..000000000 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationOffset.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5b8a5228a8756d64684e8dca601ccafc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs index 87d7405f7..433693389 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/Vrm10AimConstraint.cs @@ -1,4 +1,6 @@ -using UnityEngine; +using System; +using UniGLTF.Extensions.VRMC_node_constraint; +using UnityEngine; namespace UniVRM10 { @@ -16,11 +18,61 @@ namespace UniVRM10 public float Weight = 1.0f; [SerializeField] - public UniGLTF.Extensions.VRMC_node_constraint.AimAxis AimAxis; + public AimAxis AimAxis; + Vector3 GetAxisVector() + { + switch (AimAxis) + { + case AimAxis.PositiveX: return Vector3.right; + case AimAxis.NegativeX: return Vector3.left; + case AimAxis.PositiveY: return Vector3.up; + case AimAxis.NegativeY: return Vector3.down; + case AimAxis.PositiveZ: return Vector3.forward; + case AimAxis.NegativeZ: return Vector3.back; + default: throw new NotImplementedException(); + } + } + + Quaternion _dstRestLocalQuat; + + void Awake() + { + if (Source == null) + { + this.enabled = false; + return; + } + + _dstRestLocalQuat = transform.localRotation; + } + /// + /// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_draft/README.ja.md#example-of-implementation-1 + /// + /// fromVec = aimAxis.applyQuaternion( dstParentWorldQuat * dstRestQuat ) + /// toVec = ( srcWorldPos - dstWorldPos ).normalized + /// fromToQuat = Quaternion.fromToRotation( fromVec, toVec ) + /// targetQuat = Quaternion.slerp( + /// dstRestQuat, + /// dstParentWorldQuat.inverse * fromToQuat * dstParentWorldQuat * dstRestQuat, + /// weight + /// ) + /// public override void Process() { - throw new System.NotImplementedException(); + if (Source == null) return; + + // world coords + var dstParentWorldQuat = transform.parent != null ? transform.parent.rotation : Quaternion.identity; + var fromVec = (dstParentWorldQuat * _dstRestLocalQuat) * GetAxisVector(); + var toVec = (Source.position - transform.position).normalized; + var fromToQuat = Quaternion.FromToRotation(fromVec, toVec); + + transform.rotation = Quaternion.SlerpUnclamped( + _dstRestLocalQuat, + Quaternion.Inverse(dstParentWorldQuat) * fromToQuat * dstParentWorldQuat * _dstRestLocalQuat, + Weight + ); } } } diff --git a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs index 199d14a7b..cc75b75e8 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/Vrm10RollConstraint.cs @@ -1,4 +1,6 @@ -using UnityEngine; +using System; +using UniGLTF.Extensions.VRMC_node_constraint; +using UnityEngine; namespace UniVRM10 { @@ -16,11 +18,65 @@ namespace UniVRM10 public float Weight = 1.0f; [SerializeField] - public UniGLTF.Extensions.VRMC_node_constraint.RollAxis RollAxis; + public RollAxis RollAxis; + Vector3 GetRollVector() + { + switch (RollAxis) + { + case RollAxis.X: return Vector3.right; + case RollAxis.Y: return Vector3.up; + case RollAxis.Z: return Vector3.forward; + default: throw new NotImplementedException(); + } + } + Quaternion _srcRestLocalQuat; + Quaternion _dstRestLocalQuat; + + void Awake() + { + if (Source == null) + { + this.enabled = false; + return; + } + + _srcRestLocalQuat = Source.localRotation; + _dstRestLocalQuat = transform.localRotation; + } + /// + /// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_node_constraint-1.0_draft/README.ja.md#example-of-implementation + /// + /// deltaSrcQuat = srcRestQuat.inverse * srcQuat + /// deltaSrcQuatInParent = srcRestQuat * deltaSrcQuat * srcRestQuat.inverse // source to parent + /// deltaSrcQuatInDst = dstRestQuat.inverse * deltaSrcQuatInWorld * dstRestQuat // parent to destination + /// + /// toVec = rollAxis.applyQuaternion( deltaSrcQuatInDst ) + /// fromToQuat = Quaternion.fromToRotation( rollAxis, toVec ) + /// + /// targetQuat = Quaternion.slerp( + /// dstRestQuat, + /// dstRestQuat * fromToQuat.inverse * deltaSrcQuatInDst, + /// weight + /// ) + /// public override void Process() { - throw new System.NotImplementedException(); + 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 rollAxis = GetRollVector(); + var toVec = deltaSrcQuatInDst * rollAxis; + var fromToQuat = Quaternion.FromToRotation(rollAxis, toVec); + + transform.localRotation = Quaternion.SlerpUnclamped( + _dstRestLocalQuat, + _dstRestLocalQuat * Quaternion.Inverse(fromToQuat) * deltaSrcQuatInDst, + Weight + ); } } }