From 744d0e54bc7a66c068d814f80d1177e47fe95e8c Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 23 Apr 2021 14:16:44 +0900 Subject: [PATCH 1/5] add constraints selector --- .../SpringBone/VRM10SelectorWindow.cs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs index fa1de5c9d..508b7dc26 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs @@ -70,6 +70,9 @@ namespace UniVRM10 static bool s_foldColliders = true; public VRM10SpringBoneColliderGroup[] m_colliderGroups; + static bool s_foldConstraints = true; + public VRM10Constraint[] m_constraints; + void Reload() { var backup = Root; @@ -83,13 +86,14 @@ namespace UniVRM10 { Root = (Transform)EditorGUILayout.ObjectField("vrm1 root", m_root, typeof(Transform), true); - if (m_springs != null && m_springs.Length > 0 && m_springs[0] == null) + if (m_springs != null && m_springs.Length > 0 && m_springs.Any(x => x == null)) { Reload(); } m_scrollPosition = EditorGUILayout.BeginScrollView(m_scrollPosition); + // mouse wheel scroll part 1 var isScroll = Event.current.isScrollWheel; if (isScroll) { @@ -99,7 +103,10 @@ namespace UniVRM10 m_scrollPosition = Vector2.zero; } } + DrawContent(); + + // mouse wheel scroll part 2 var bottom = EditorGUILayout.GetControlRect(); if (isScroll) { @@ -111,6 +118,7 @@ namespace UniVRM10 } Repaint(); } + EditorGUILayout.EndScrollView(); } @@ -155,10 +163,14 @@ namespace UniVRM10 { m_colliderGroups = m_root.GetComponentsInChildren(); } + if (m_constraints == null) + { + m_constraints = m_root.GetComponentsInChildren(); + } } GUI.enabled = false; - s_foldHumanoidBones = EditorGUILayout.Foldout(s_foldHumanoidBones, "human bones"); + s_foldHumanoidBones = EditorGUILayout.Foldout(s_foldHumanoidBones, "humanoid bones"); if (s_foldHumanoidBones) { if (m_boneMap != null) @@ -197,6 +209,18 @@ namespace UniVRM10 } } } + + s_foldConstraints = EditorGUILayout.Foldout(s_foldConstraints, "constraints"); + if (s_foldConstraints) + { + if (m_constraints != null) + { + foreach (var c in m_constraints) + { + EditorGUILayout.ObjectField(c, typeof(VRM10Constraint), true); + } + } + } } } } From abafd14ff2c4db4ff0f86cf37114d8e50b80ac6a Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 23 Apr 2021 14:17:05 +0900 Subject: [PATCH 2/5] WIP ObjectSpace.model --- .../Components/Constraint/ConstraintDestination.cs | 12 ++++++++++-- Assets/VRM10/Runtime/Components/Constraint/TRS.cs | 10 ++++++++++ .../Constraint/VRM10PositionConstraint.cs | 12 +++++++++++- .../Constraint/VRM10RotationConstraint.cs | 14 ++++++++++++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs b/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs index 54dbb4525..505c387d8 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs @@ -11,7 +11,7 @@ namespace UniVRM10 readonly TRS m_initial; - public ConstraintDestination(Transform t, ObjectSpace coords) + public ConstraintDestination(Transform t, ObjectSpace coords, Transform modelRoot = null) { m_transform = t; m_coords = coords; @@ -26,6 +26,10 @@ namespace UniVRM10 m_initial = TRS.GetLocal(t); break; + case ObjectSpace.model: + m_initial = TRS.GetRelative(t, modelRoot.worldToLocalMatrix); + break; + default: throw new NotImplementedException(); } @@ -49,7 +53,7 @@ namespace UniVRM10 } } - public void ApplyRotation(Quaternion delta, float weight) + public void ApplyRotation(Quaternion delta, float weight, Transform modelRoot = null) { // 0~1 で clamp しない slerp var value = Quaternion.LerpUnclamped(Quaternion.identity, delta, weight) * m_initial.Rotation; @@ -63,6 +67,10 @@ namespace UniVRM10 m_transform.localRotation = value; break; + case ObjectSpace.model: + m_transform.rotation = modelRoot.rotation * value; + break; + default: throw new NotImplementedException(); } diff --git a/Assets/VRM10/Runtime/Components/Constraint/TRS.cs b/Assets/VRM10/Runtime/Components/Constraint/TRS.cs index 1881b77ac..fffdf7c55 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/TRS.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/TRS.cs @@ -27,5 +27,15 @@ namespace UniVRM10 Scale = t.localScale, }; } + + public static TRS GetRelative(Transform t, Matrix4x4 toRelative) + { + return new TRS + { + Translation = toRelative.MultiplyPoint(t.position), + Rotation = toRelative.rotation * t.rotation, + Scale = toRelative.MultiplyVector(t.lossyScale), + }; + } } } diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs index 614b69d1d..a8b9e1b6d 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs @@ -42,6 +42,16 @@ namespace UniVRM10 m_dst = null; } + void Reset() + { + var current = transform; + while (current.parent != null) + { + current = current.parent; + } + ModelRoot = current; + } + public override void Process() { if (Source == null) @@ -56,7 +66,7 @@ namespace UniVRM10 } if (m_dst == null) { - m_dst = new ConstraintDestination(transform, DestinationCoordinate); + m_dst = new ConstraintDestination(transform, DestinationCoordinate, ModelRoot); } var delta = FreezeAxes.Freeze(m_src.TranslationDelta); diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs index b747417bd..0263fbbec 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10RotationConstraint.cs @@ -43,6 +43,16 @@ namespace UniVRM10 m_dst = null; } + void Reset() + { + var current = transform; + while (current.parent != null) + { + current = current.parent; + } + ModelRoot = current; + } + /// /// SourceのUpdateよりも先か後かはその時による。 /// 厳密に制御するのは無理。 @@ -61,7 +71,7 @@ namespace UniVRM10 } if (m_dst == null) { - m_dst = new ConstraintDestination(transform, DestinationCoordinate); + m_dst = new ConstraintDestination(transform, DestinationCoordinate, ModelRoot); } // 軸制限をしたオイラー角 @@ -70,7 +80,7 @@ namespace UniVRM10 var rotation = Quaternion.Euler(fleezed); // Debug.Log($"{delta} => {rotation}"); // オイラー角を再度Quaternionへ。weight を加味してSlerpする - m_dst.ApplyRotation(rotation, Weight); + m_dst.ApplyRotation(rotation, Weight, ModelRoot); } } } From 440a8f0e6f5f34a5700ea154148b578d4186eedb Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 23 Apr 2021 14:43:34 +0900 Subject: [PATCH 3/5] VrmExporter.ExportConstraints --- Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 85 +++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 6b94a4926..272f52dfc 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -198,7 +198,20 @@ namespace UniVRM10 } } - (UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone, int? thumbnailIndex) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta) + /// + /// VRMコンポーネントのエクスポート + /// + /// + /// + /// + /// + /// + /// + /// + /// + (UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, + UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone, + int? thumbnailIndex) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta) { var vrmController = root?.GetComponent(); @@ -245,6 +258,7 @@ namespace UniVRM10 ExportFirstPerson(vrm, vrmController, model, converter); vrmSpringBone = ExportSpringBone(vrmController, model, converter); + ExportConstraints(vrmController, model, converter); } return (vrm, vrmSpringBone, thumbnailTextureIndex); @@ -339,6 +353,75 @@ namespace UniVRM10 return springBone; } + void ExportConstraints(VRM10Controller vrmController, Model model, RuntimeVrmConverter converter) + { + var constraints = vrmController.GetComponentsInChildren(); + foreach (var constraint in constraints) + { + switch (constraint) + { + case VRM10PositionConstraint positionConstraint: + ExportPostionConstraint(positionConstraint, model, converter); + break; + + case VRM10RotationConstraint rotationConstraint: + ExportRotationConstraint(rotationConstraint, model, converter); + break; + + case VRM10AimConstraint aimConstraint: + ExportAimConstraint(aimConstraint, model, converter); + break; + + default: + throw new NotImplementedException(); + } + } + } + + void ExportPostionConstraint(VRM10PositionConstraint c, Model model, RuntimeVrmConverter converter) + { + throw new NotImplementedException(); + } + + static bool[] ToArray(AxisMask mask) + { + return new bool[] + { + mask.HasFlag(AxisMask.X), + mask.HasFlag(AxisMask.Y), + mask.HasFlag(AxisMask.Z), + }; + } + + void ExportRotationConstraint(VRM10RotationConstraint c, Model model, RuntimeVrmConverter converter) + { + var vrmConstraint = new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint + { + Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint + { + Rotation = new UniGLTF.Extensions.VRMC_node_constraint.RotationConstraint + { + Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]), + SourceSpace = c.SourceCoordinate, + DestinationSpace = c.DestinationCoordinate, + FreezeAxes = ToArray(c.FreezeAxes), + Weight = c.Weight, + }, + }, + }; + + // serialize to gltfNode + var node = converter.Nodes[c.gameObject]; + var nodeIndex = model.Nodes.IndexOf(node); + var gltfNode = Storage.Gltf.nodes[nodeIndex]; + UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint); + } + + static void ExportAimConstraint(VRM10AimConstraint c, Model model, RuntimeVrmConverter converter) + { + throw new NotImplementedException(); + } + static UniGLTF.Extensions.VRMC_vrm.MeshAnnotation ExportMeshAnnotation(RendererFirstPersonFlags flags, Func getIndex) { return new UniGLTF.Extensions.VRMC_vrm.MeshAnnotation From fde77865f7bd76217de80c650c085a00172d8ee1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 23 Apr 2021 14:54:45 +0900 Subject: [PATCH 4/5] clear m_constraints --- .../VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs index 508b7dc26..3b96ce8df 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SelectorWindow.cs @@ -54,9 +54,10 @@ namespace UniVRM10 } m_root = value; + m_boneMap = null; m_springs = null; m_colliderGroups = null; - m_boneMap = null; + m_constraints = null; } } From e9c94de242cd0c341288d0e95a9bf353775bfca1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 23 Apr 2021 17:40:23 +0900 Subject: [PATCH 5/5] export position constraint --- .../Constraint/ConstraintDestination.cs | 6 +- .../Constraint/VRM10AimConstraint.cs | 6 +- .../Constraint/VRM10PositionConstraint.cs | 2 +- .../VRM10/Runtime/IO/RuntimeVrmConverter.cs | 5 +- Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 62 +++++++++++++------ 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs b/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs index 505c387d8..21cf3b0f2 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/ConstraintDestination.cs @@ -35,7 +35,7 @@ namespace UniVRM10 } } - public void ApplyTranslation(Vector3 delta, float weight) + public void ApplyTranslation(Vector3 delta, float weight, Transform modelRoot = null) { var value = m_initial.Translation + delta * weight; switch (m_coords) @@ -48,6 +48,10 @@ namespace UniVRM10 m_transform.localPosition = value; break; + case ObjectSpace.model: + m_transform.position = modelRoot.localToWorldMatrix.MultiplyPoint(value); + break; + default: throw new NotImplementedException(); } diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs index 5f2529c48..eba3d3f5b 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10AimConstraint.cs @@ -16,9 +16,9 @@ namespace UniVRM10 [SerializeField] public Transform Source = default; - // [SerializeField] - // [Range(0, 10.0f)] - // float Weight = 1.0f; + [SerializeField] + [Range(0, 10.0f)] + public float Weight = 1.0f; /// /// Forward diff --git a/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs b/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs index a8b9e1b6d..103cbb535 100644 --- a/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs +++ b/Assets/VRM10/Runtime/Components/Constraint/VRM10PositionConstraint.cs @@ -70,7 +70,7 @@ namespace UniVRM10 } var delta = FreezeAxes.Freeze(m_src.TranslationDelta); - m_dst.ApplyTranslation(delta, Weight); + m_dst.ApplyTranslation(delta, Weight, ModelRoot); } } } diff --git a/Assets/VRM10/Runtime/IO/RuntimeVrmConverter.cs b/Assets/VRM10/Runtime/IO/RuntimeVrmConverter.cs index a1cc905f2..afe1b3369 100644 --- a/Assets/VRM10/Runtime/IO/RuntimeVrmConverter.cs +++ b/Assets/VRM10/Runtime/IO/RuntimeVrmConverter.cs @@ -112,7 +112,10 @@ namespace UniVRM10 var mesh = CreateMesh(filter.sharedMesh, meshRenderer, Materials); Model.MeshGroups.Add(mesh); Nodes[renderer.gameObject].MeshGroup = mesh; - Meshes.Add(filter.sharedMesh, mesh); + if (!Meshes.ContainsKey(filter.sharedMesh)) + { + Meshes.Add(filter.sharedMesh, mesh); + } } } } diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 272f52dfc..8b308a8da 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -358,29 +358,31 @@ namespace UniVRM10 var constraints = vrmController.GetComponentsInChildren(); foreach (var constraint in constraints) { + UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint vrmConstraint = default; switch (constraint) { case VRM10PositionConstraint positionConstraint: - ExportPostionConstraint(positionConstraint, model, converter); + vrmConstraint = ExportPostionConstraint(positionConstraint, model, converter); break; case VRM10RotationConstraint rotationConstraint: - ExportRotationConstraint(rotationConstraint, model, converter); + vrmConstraint = ExportRotationConstraint(rotationConstraint, model, converter); break; case VRM10AimConstraint aimConstraint: - ExportAimConstraint(aimConstraint, model, converter); + vrmConstraint = ExportAimConstraint(aimConstraint, model, converter); break; default: throw new NotImplementedException(); } - } - } - void ExportPostionConstraint(VRM10PositionConstraint c, Model model, RuntimeVrmConverter converter) - { - throw new NotImplementedException(); + // serialize to gltfNode + var node = converter.Nodes[constraint.gameObject]; + var nodeIndex = model.Nodes.IndexOf(node); + var gltfNode = Storage.Gltf.nodes[nodeIndex]; + UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint); + } } static bool[] ToArray(AxisMask mask) @@ -393,9 +395,27 @@ namespace UniVRM10 }; } - void ExportRotationConstraint(VRM10RotationConstraint c, Model model, RuntimeVrmConverter converter) + static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportPostionConstraint(VRM10PositionConstraint c, Model model, RuntimeVrmConverter converter) { - var vrmConstraint = new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint + return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint + { + Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint + { + Position = new UniGLTF.Extensions.VRMC_node_constraint.PositionConstraint + { + Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]), + SourceSpace = c.SourceCoordinate, + DestinationSpace = c.DestinationCoordinate, + FreezeAxes = ToArray(c.FreezeAxes), + Weight = c.Weight, + } + }, + }; + } + + static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportRotationConstraint(VRM10RotationConstraint c, Model model, RuntimeVrmConverter converter) + { + return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint { Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint { @@ -409,17 +429,23 @@ namespace UniVRM10 }, }, }; - - // serialize to gltfNode - var node = converter.Nodes[c.gameObject]; - var nodeIndex = model.Nodes.IndexOf(node); - var gltfNode = Storage.Gltf.nodes[nodeIndex]; - UniGLTF.Extensions.VRMC_node_constraint.GltfSerializer.SerializeTo(ref gltfNode.extensions, vrmConstraint); } - static void ExportAimConstraint(VRM10AimConstraint c, Model model, RuntimeVrmConverter converter) + static UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint ExportAimConstraint(VRM10AimConstraint c, Model model, RuntimeVrmConverter converter) { - throw new NotImplementedException(); + return new UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint + { + Constraint = new UniGLTF.Extensions.VRMC_node_constraint.Constraint + { + Aim = new UniGLTF.Extensions.VRMC_node_constraint.AimConstraint + { + Source = model.Nodes.IndexOf(converter.Nodes[c.Source.gameObject]), + AimVector = ReverseX(c.AimVector), + UpVector = ReverseX(c.UpVector), + Weight = c.Weight, + }, + }, + }; } static UniGLTF.Extensions.VRMC_vrm.MeshAnnotation ExportMeshAnnotation(RendererFirstPersonFlags flags, Func getIndex)