diff --git a/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs b/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs index dc4fddaa8..6eb19872c 100644 --- a/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs +++ b/Assets/VRM10_Samples/ClothSample/ClothViewer/ClothViewerUI.cs @@ -567,11 +567,7 @@ namespace UniVRM10.Cloth.Viewer awaitCaller: m_useAsync.enabled ? (IAwaitCaller)new RuntimeOnlyAwaitCaller() : (IAwaitCaller)new ImmediateCaller(), materialGenerator: GetVrmMaterialDescriptorGenerator(true), vrmMetaInformationCallback: m_texts.UpdateMeta, - springboneRuntime: new RotateParticle.RotateParticleSpringboneRuntime((instance) => - { - var autoSetup = instance.transform.gameObject.AddComponent(); - autoSetup.Reset(); - })); + springboneRuntime: new RotateParticle.RotateParticleSpringboneRuntime()); if (cancellationToken.IsCancellationRequested) { UnityObjectDestroyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject); diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs deleted file mode 100644 index 622a34a78..000000000 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using SphereTriangle; -using UnityEngine; - - -namespace RotateParticle -{ - public class HumanoidAutoSetup : MonoBehaviour - { - static (string group, HumanBodyBones head, HumanBodyBones tail, float radius)[] Capsules = new[] - { - ("Leg", HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, 0.06f), - ("Leg", HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, 0.05f), - ("Leg", HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, 0.06f), - ("Leg", HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, 0.05f), - - ("Arm", HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, 0.03f), - ("Arm", HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, 0.03f), - ("Arm", HumanBodyBones.LeftHand, HumanBodyBones.LeftMiddleProximal, 0.02f), - ("Arm", HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, 0.03f), - ("Arm", HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, 0.03f), - ("Arm", HumanBodyBones.RightHand, HumanBodyBones.RightMiddleProximal, 0.02f), - }; - - T GetOrAddComponent() where T : Component - { - var t = GetComponent(); - if (t != null) - { - return t; - } - return gameObject.AddComponent(); - } - - bool TryAddGroup(CollisionGroupMask mask, string name, Animator animator, HumanBodyBones humanBone, string[] targets, StrandConnectionType type, - out StrandGroup group) - { - var bone = animator.GetBoneTransform(humanBone); - if (bone == null) - { - Debug.LogWarning($"{humanBone} not found"); - group = default; - return false; - } - - List transforms = new(); - foreach (Transform child in bone) - { - foreach (var target in targets) - { - if (child.name.ToLower().Contains(target.ToLower())) - { - transforms.Add(child); - break; - } - } - } - if (transforms.Count == 0) - { - Debug.LogWarning($"{string.Join(',', targets)} not found"); - group = default; - return false; - } - - group = new StrandGroup - { - Name = name, - CollisionMask = mask, - DefaultStrandRaius = 0.02f, - Connection = type - }; - group.Roots.AddRange(transforms); - - // sort - group.Roots.Sort(new TransformSort(bone.position)); - return true; - } - - bool TryAddGroupChildChild(CollisionGroupMask mask, string name, Animator animator, HumanBodyBones humanBone, - string[] targets, string[] excludes, - StrandConnectionType type, - bool sort, - out StrandGroup group) - { - var bone = animator.GetBoneTransform(humanBone); - if (bone == null) - { - Debug.LogWarning($"{humanBone} not found"); - group = default; - return false; - } - - List transforms = new(); - foreach (Transform child in bone) - { - foreach (Transform childchild in child) - { - if (excludes.Any(x => childchild.name.ToLower().Contains(x.ToLower()))) - { - continue; - } - - foreach (var target in targets) - { - if (childchild.name.ToLower().Contains(target.ToLower())) - { - transforms.Add(childchild); - break; - } - } - } - } - if (transforms.Count == 0) - { - Debug.LogWarning($"{string.Join(',', targets)} not found"); - group = default; - return false; - } - - group = new StrandGroup - { - Name = name, - CollisionMask = mask, - DefaultStrandRaius = 0.02f, - Connection = type - }; - group.Roots.AddRange(transforms); - - // sort - if (sort) - { - group.Roots.Sort(new TransformSort(bone.position)); - } - return true; - } - - public void Reset() - { - var animator = GetComponent(); - if (animator == null) - { - Debug.LogWarning("no animator"); - return; - } - var avatar = animator.avatar; - if (!avatar.isHuman) - { - Debug.LogWarning("not humanoid"); - return; - } - - var system = GetOrAddComponent(); - system.Env.DragForce = 0.6f; - system.Env.Stiffness = 0.07f; - - foreach (var (group, head, tail, radius) in Capsules) - { - system.AddColliderIfNotExists(group, - animator.GetBoneTransform(head), animator.GetBoneTransform(tail), radius); - } - - // skirt - { - if (TryAddGroup(CollisionGroupMask.Group01, "Skirt", animator, HumanBodyBones.Hips, new[] { "skirt", "スカート", "スカート" }, StrandConnectionType.ClothLoop, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroupChildChild(CollisionGroupMask.Group01, "Skirt", animator, HumanBodyBones.Hips, new[] { "skirt", "スカート", "スカート" }, new string[]{}, StrandConnectionType.ClothLoop, false, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroup(CollisionGroupMask.Group02, "髪", animator, HumanBodyBones.Head, new[] { "髪", "hair" }, StrandConnectionType.Strand, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroup(CollisionGroupMask.Group01, "裾", animator, HumanBodyBones.Hips, new[] { "裾" }, StrandConnectionType.Cloth, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroupChildChild(CollisionGroupMask.Group02, "左袖", animator, HumanBodyBones.LeftUpperArm, new[] { "袖" }, new[] { "ひじ袖" }, StrandConnectionType.ClothLoop, - false, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroupChildChild(CollisionGroupMask.Group02, "左ひじ袖", animator, HumanBodyBones.LeftLowerArm, new[] { "袖" }, new string[] { }, StrandConnectionType.ClothLoop, - false, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroupChildChild(CollisionGroupMask.Group02, "右袖", animator, HumanBodyBones.RightUpperArm, new[] { "袖" }, new[] { "ひじ袖" }, StrandConnectionType.ClothLoop, - false, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroupChildChild(CollisionGroupMask.Group02, "右ひじ袖", animator, HumanBodyBones.RightLowerArm, new[] { "袖" }, new string[] { }, StrandConnectionType.ClothLoop, - false, - out var g)) - { - system._strandGroups.Add(g); - } - } - { - if (TryAddGroup(CollisionGroupMask.Group01 | CollisionGroupMask.Group02, "マント", animator, HumanBodyBones.Chest, new[] { "マント" }, StrandConnectionType.Cloth, - out var g)) - { - system._strandGroups.Add(g); - } - } - } - } -} \ No newline at end of file diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntime.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntime.cs index 24f31a300..88250ecbe 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntime.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntime.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using SphereTriangle; using UniGLTF; using UniGLTF.SpringBoneJobs.Blittables; using UnityEngine; @@ -13,31 +16,246 @@ namespace RotateParticle /// public class RotateParticleSpringboneRuntime : IVrm10SpringBoneRuntime { - Action _setup; - - public RotateParticleSpringboneRuntime(Action setup) - { - _setup = setup; - } + RotateParticleSystem _system; public void Dispose() { } - public Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller) + public async Task InitializeAsync(Vrm10Instance instance, IAwaitCaller awaitCaller) { - if (_setup != null) - { - _setup(instance); - } - var system = instance.GetComponent(); - system.Initialize(); + await awaitCaller.NextFrame(); + // if (_setup != null) + // { + // _setup(instance); + // } - return Task.CompletedTask; + var animator = instance.GetComponent(); + if (animator == null) + { + Debug.LogWarning("no animator"); + return; + } + + var avatar = animator.avatar; + if (!avatar.isHuman) + { + Debug.LogWarning("not humanoid"); + return; + } + + _system = new RotateParticleSystem(); + _system.Env.DragForce = 0.6f; + _system.Env.Stiffness = 0.07f; + + foreach (var (group, head, tail, radius) in Capsules) + { + _system.AddColliderIfNotExists(group, + animator.GetBoneTransform(head), animator.GetBoneTransform(tail), radius); + } + + // skirt + { + if (TryAddGroup(CollisionGroupMask.Group01, "Skirt", animator, HumanBodyBones.Hips, new[] { "skirt", "スカート", "スカート" }, StrandConnectionType.ClothLoop, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroupChildChild(CollisionGroupMask.Group01, "Skirt", animator, HumanBodyBones.Hips, new[] { "skirt", "スカート", "スカート" }, new string[] { }, StrandConnectionType.ClothLoop, false, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroup(CollisionGroupMask.Group02, "髪", animator, HumanBodyBones.Head, new[] { "髪", "hair" }, StrandConnectionType.Strand, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroup(CollisionGroupMask.Group01, "裾", animator, HumanBodyBones.Hips, new[] { "裾" }, StrandConnectionType.Cloth, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroupChildChild(CollisionGroupMask.Group02, "左袖", animator, HumanBodyBones.LeftUpperArm, new[] { "袖" }, new[] { "ひじ袖" }, StrandConnectionType.ClothLoop, + false, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroupChildChild(CollisionGroupMask.Group02, "左ひじ袖", animator, HumanBodyBones.LeftLowerArm, new[] { "袖" }, new string[] { }, StrandConnectionType.ClothLoop, + false, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroupChildChild(CollisionGroupMask.Group02, "右袖", animator, HumanBodyBones.RightUpperArm, new[] { "袖" }, new[] { "ひじ袖" }, StrandConnectionType.ClothLoop, + false, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroupChildChild(CollisionGroupMask.Group02, "右ひじ袖", animator, HumanBodyBones.RightLowerArm, new[] { "袖" }, new string[] { }, StrandConnectionType.ClothLoop, + false, + out var g)) + { + _system._strandGroups.Add(g); + } + } + { + if (TryAddGroup(CollisionGroupMask.Group01 | CollisionGroupMask.Group02, "マント", animator, HumanBodyBones.Chest, new[] { "マント" }, StrandConnectionType.Cloth, + out var g)) + { + _system._strandGroups.Add(g); + } + } + + _system.Initialize(); + } + + static (string group, HumanBodyBones head, HumanBodyBones tail, float radius)[] Capsules = new[] + { + ("Leg", HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, 0.06f), + ("Leg", HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, 0.05f), + ("Leg", HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, 0.06f), + ("Leg", HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, 0.05f), + + ("Arm", HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, 0.03f), + ("Arm", HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, 0.03f), + ("Arm", HumanBodyBones.LeftHand, HumanBodyBones.LeftMiddleProximal, 0.02f), + ("Arm", HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, 0.03f), + ("Arm", HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, 0.03f), + ("Arm", HumanBodyBones.RightHand, HumanBodyBones.RightMiddleProximal, 0.02f), + }; + + // T GetOrAddComponent() where T : Component + // { + // var t = GetComponent(); + // if (t != null) + // { + // return t; + // } + // return gameObject.AddComponent(); + // } + + bool TryAddGroup(CollisionGroupMask mask, string name, Animator animator, HumanBodyBones humanBone, string[] targets, StrandConnectionType type, + out StrandGroup group) + { + var bone = animator.GetBoneTransform(humanBone); + if (bone == null) + { + Debug.LogWarning($"{humanBone} not found"); + group = default; + return false; + } + + List transforms = new(); + foreach (Transform child in bone) + { + foreach (var target in targets) + { + if (child.name.ToLower().Contains(target.ToLower())) + { + transforms.Add(child); + break; + } + } + } + if (transforms.Count == 0) + { + // Debug.LogWarning($"{string.Join(',', targets)} not found"); + group = default; + return false; + } + + group = new StrandGroup + { + Name = name, + CollisionMask = mask, + DefaultStrandRaius = 0.02f, + Connection = type + }; + group.Roots.AddRange(transforms); + + // sort + group.Roots.Sort(new TransformSort(bone.position)); + return true; + } + + bool TryAddGroupChildChild(CollisionGroupMask mask, string name, Animator animator, HumanBodyBones humanBone, + string[] targets, string[] excludes, + StrandConnectionType type, + bool sort, + out StrandGroup group) + { + var bone = animator.GetBoneTransform(humanBone); + if (bone == null) + { + Debug.LogWarning($"{humanBone} not found"); + group = default; + return false; + } + + List transforms = new(); + foreach (Transform child in bone) + { + foreach (Transform childchild in child) + { + if (excludes.Any(x => childchild.name.ToLower().Contains(x.ToLower()))) + { + continue; + } + + foreach (var target in targets) + { + if (childchild.name.ToLower().Contains(target.ToLower())) + { + transforms.Add(childchild); + break; + } + } + } + } + if (transforms.Count == 0) + { + // Debug.LogWarning($"{string.Join(',', targets)} not found"); + group = default; + return false; + } + + group = new StrandGroup + { + Name = name, + CollisionMask = mask, + DefaultStrandRaius = 0.02f, + Connection = type + }; + group.Roots.AddRange(transforms); + + // sort + if (sort) + { + group.Roots.Sort(new TransformSort(bone.position)); + } + return true; } public void Process() { + _system.Process(Time.deltaTime); } public bool ReconstructSpringBone() diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs new file mode 100644 index 000000000..456d245ef --- /dev/null +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs @@ -0,0 +1,13 @@ +using UnityEngine; +using UniVRM10; + +namespace RotateParticle +{ + public class RotateParticleSpringboneRuntimeProvider : MonoBehaviour, IVrm10SpringBoneRuntimeProvider + { + public IVrm10SpringBoneRuntime CreateSpringBoneRuntime() + { + return new RotateParticleSpringboneRuntime(); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs.meta b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs.meta similarity index 83% rename from Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs.meta rename to Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs.meta index 7bc096b42..f1db90b56 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/HumanoidAutoSetup.cs.meta +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSpringboneRuntimeProvider.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f2c23a62e016b3244b286404bc339540 +guid: de8d095eee60f134ebd9ccaa9efcc01e MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSystem.cs b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSystem.cs index e0f8ef2d7..437507c16 100644 --- a/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSystem.cs +++ b/Assets/VRM10_Samples/ClothSample/RotateParticle/Runtime/RotateParticleSystem.cs @@ -7,8 +7,8 @@ using UnityEngine; namespace RotateParticle { - [DisallowMultipleComponent] - public class RotateParticleSystem : MonoBehaviour + [Serializable] + public class RotateParticleSystem { // TODO: param to _strandGroups [SerializeField] @@ -24,7 +24,6 @@ namespace RotateParticle public float _clothFactor = 0.5f; // runtime - bool _initialized = false; List _strands = new List(); public ParticleList _list = new(); public List<(SpringConstraint, ClothRectCollision)> _clothRects = new(); @@ -176,7 +175,6 @@ namespace RotateParticle public void Initialize() { - _initialized = true; foreach (var g in _strandGroups) { if (g.Roots?.Count == 0) @@ -205,14 +203,6 @@ namespace RotateParticle } } - void Start() - { - if (!_initialized) - { - Initialize(); - } - } - /// /// すべての Particle を Init 状態にする。 /// Verlet の Prev を現在地に更新する(速度0)。 @@ -225,15 +215,6 @@ namespace RotateParticle } } - public void Update() - { - if (Time.deltaTime == 0) - { - return; - } - Process(Time.deltaTime); - } - public void Process(float deltaTime) { using var profile = new ProfileSample("RotateParticle"); @@ -345,7 +326,7 @@ namespace RotateParticle } } - void OnDrawGizmos() + public void DrawGizmos() { _list.DrawGizmos();