This commit is contained in:
ousttrue 2024-11-21 15:25:00 +09:00
parent 77ba330ba5
commit 335beede4b
13 changed files with 338 additions and 229 deletions

View File

@ -113,7 +113,7 @@ namespace UniVRM10.Cloth.Viewer
static bool TryAddGroupChildChild(
Animator animator, HumanBodyBones humanBone,
string[] targets, string[] excludes,
out List<Warp> group)
out List<WarpRoot> group)
{
var bone = animator.GetBoneTransform(humanBone);
if (bone == null)
@ -123,7 +123,7 @@ namespace UniVRM10.Cloth.Viewer
return false;
}
List<Warp> transforms = new();
List<WarpRoot> transforms = new();
foreach (Transform child in bone)
{
foreach (Transform childchild in child)
@ -137,11 +137,10 @@ namespace UniVRM10.Cloth.Viewer
{
if (childchild.name.ToLower().Contains(target.ToLower()))
{
var warp = childchild.gameObject.AddComponent<Warp>();
var warp = childchild.gameObject.AddComponent<WarpRoot>();
// Name = name,
// CollisionMask = mask,
warp.BaseSettings.radius = 0.02f;
warp.AddParticleRecursive();
// Connection = type
transforms.Add(warp);
break;
@ -161,7 +160,7 @@ namespace UniVRM10.Cloth.Viewer
}
static bool TryAddGroup(Animator animator, HumanBodyBones humanBone, string[] targets,
out List<Warp> group)
out List<WarpRoot> group)
{
var bone = animator.GetBoneTransform(humanBone);
if (bone == null)
@ -171,19 +170,18 @@ namespace UniVRM10.Cloth.Viewer
return false;
}
List<Warp> transforms = new();
List<WarpRoot> transforms = new();
foreach (Transform child in bone)
{
foreach (var target in targets)
{
if (child.name.ToLower().Contains(target.ToLower()))
{
var warp = child.gameObject.AddComponent<Warp>();
var warp = child.gameObject.AddComponent<WarpRoot>();
if (warp != null)
{
// CollisionMask = mask,
warp.BaseSettings.radius = 0.02f;
warp.AddParticleRecursive();
// Connection = type
transforms.Add(warp);
}

View File

@ -263,7 +263,6 @@ namespace UniVRM10.Cloth.Viewer
Loaded m_loaded;
RotateParticle.HumanoidPose m_init;
int m_springFrame = 0;
static class ArgumentChecker
{
@ -556,7 +555,7 @@ namespace UniVRM10.Cloth.Viewer
if (vrm.SpringBone.ColliderGroups.Count == 0)
{
HumanoidCollider.AddColliders(animator);
var warps = animator.GetComponentsInChildren<Warp>();
var warps = animator.GetComponentsInChildren<WarpRoot>();
var colliderGroups = animator.GetComponentsInChildren<VRM10SpringBoneColliderGroup>();
foreach (var warp in warps)
{
@ -567,7 +566,7 @@ namespace UniVRM10.Cloth.Viewer
else
{
RotateParticleRuntimeProvider.FromVrm10(vrm,
go => go.AddComponent<Warp>(),
go => go.AddComponent<WarpRoot>(),
o => GameObject.DestroyImmediate(o));
}
}
@ -613,7 +612,6 @@ namespace UniVRM10.Cloth.Viewer
instance.EnableUpdateWhenOffscreen();
m_loaded = new Loaded(instance, m_target.transform);
m_init = new RotateParticle.HumanoidPose(vrm10Instance.GetComponent<Animator>());
m_springFrame = 0;
m_showBoxMan.isOn = false;
}
catch (Exception ex)

View File

@ -39,7 +39,7 @@ namespace RotateParticle.Components
var undo = Undo.GetCurrentGroup();
Undo.RegisterCompleteObjectUndo(instance, "RegisterCompleteObjectUndo");
RotateParticleRuntimeProvider.FromVrm10(instance, Undo.AddComponent<Warp>, Undo.DestroyObjectImmediate);
RotateParticleRuntimeProvider.FromVrm10(instance, Undo.AddComponent<WarpRoot>, Undo.DestroyObjectImmediate);
Undo.RegisterFullObjectHierarchyUndo(instance.gameObject, "RegisterFullObjectHierarchyUndo");
Undo.RegisterCompleteObjectUndo(provider, "RegisterCompleteObjectUndo");

View File

@ -9,12 +9,12 @@ using UniVRM10;
namespace RotateParticle.Components
{
[CustomEditor(typeof(Warp))]
class WarpEditor : Editor
[CustomEditor(typeof(WarpRoot))]
class WarpRootEditor : Editor
{
private Warp m_target;
private WarpRoot m_target;
private Vrm10Instance m_vrm;
private Transform[] m_items;
private MultiColumnTreeView m_treeview;
void OnEnable()
{
@ -23,9 +23,8 @@ namespace RotateParticle.Components
return;
}
m_target = (Warp)target;
m_target = (WarpRoot)target;
m_vrm = m_target.GetComponentInParent<Vrm10Instance>();
m_items = m_target.GetComponentsInChildren<Transform>().Skip(1).ToArray();
}
// public override void OnInspectorGUI()
@ -59,68 +58,89 @@ namespace RotateParticle.Components
s.SetEnabled(false);
root.Add(s);
}
root.Add(new PropertyField { bindingPath = nameof(Warp.BaseSettings) });
root.Add(new PropertyField { bindingPath = nameof(Warp.Center) });
root.Add(new PropertyField { bindingPath = nameof(WarpRoot.BaseSettings) });
root.Add(new PropertyField { bindingPath = nameof(WarpRoot.Center) });
root.Add(new PropertyField { bindingPath = nameof(Warp.Particles) });
root.Add(new PropertyField { bindingPath = nameof(WarpRoot.Particles) });
{
var listview = new MultiColumnListView();
listview.columns.Add(new Column
m_treeview = new MultiColumnTreeView();
m_treeview.columns.Add(new Column
{
title = "Transform",
width = 80,
width = 160,
makeCell = () => new ObjectField(),
bindCell = (v, i) =>
{
v.SetEnabled(false);
(v as ObjectField).value = m_items[i];
(v as ObjectField).value = m_target.GetParticle(i).Transform;
},
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "Mode",
width = 60,
makeCell = () => new EnumField(default(Warp.ParticleMode)),
makeCell = () => new EnumField(default(WarpRoot.ParticleMode)),
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "stiffnessForce",
width = 20,
makeCell = () => new FloatField(),
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "gravityPower",
width = 20,
makeCell = () => new FloatField(),
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "gravityDir",
width = 20,
makeCell = () => new Vector3Field(),
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "dragForce",
width = 20,
makeCell = () => new FloatField(),
});
listview.columns.Add(new Column
m_treeview.columns.Add(new Column
{
title = "radius",
width = 20,
makeCell = () => new FloatField(),
});
listview.itemsSource = m_items;
root.Add(listview);
m_treeview.autoExpand = true;
m_treeview.SetRootItems(m_target.m_rootitems);
root.Add(m_treeview);
}
root.Add(new PropertyField { bindingPath = nameof(Warp.ColliderGroups) });
root.Add(new PropertyField { bindingPath = nameof(WarpRoot.ColliderGroups) });
return root;
}
public void OnSceneGUI()
{
if (m_treeview == null)
{
return;
}
var item = m_treeview.selectedItem;
if (item == null)
{
return;
}
if (item is WarpRoot.Particle p)
{
var t = p.Transform;
Handles.color = Color.green;
Handles.SphereHandleCap(t.GetInstanceID(), t.position, t.rotation, p.Settings.radius * 2, EventType.Repaint);
}
}
}
}

View File

@ -12,63 +12,63 @@ namespace RotateParticle.Components
public bool LoopIsClosed = false;
[SerializeField]
public List<Warp> Warps = new();
public List<WarpRoot> Warps = new();
void Reset()
{
for (int i = 0; i < transform.childCount; ++i)
{
var child = transform.GetChild(i);
if (child.TryGetComponent<Warp>(out var warp))
if (child.TryGetComponent<WarpRoot>(out var warp))
{
Warps.Add(warp);
}
}
}
public void OnDrawGizmosSelected()
{
if (Warps.Count == 0)
{
return;
}
// public void OnDrawGizmosSelected()
// {
// if (Warps.Count == 0)
// {
// return;
// }
// Gizmos.color = Color.red;
Gizmos.color = new Color(1, 0.5f, 0);
for (int i = 0; i < Warps.Count; ++i)
{
if (i + 1 == Warps.Count)
{
if (LoopIsClosed)
{
DrawWeft(Warps[i], Warps[0]);
}
}
else
{
DrawWeft(Warps[i], Warps[i + 1]);
}
}
}
// // Gizmos.color = Color.red;
// Gizmos.color = new Color(1, 0.5f, 0);
// for (int i = 0; i < Warps.Count; ++i)
// {
// if (i + 1 == Warps.Count)
// {
// if (LoopIsClosed)
// {
// DrawWeft(Warps[i], Warps[0]);
// }
// }
// else
// {
// DrawWeft(Warps[i], Warps[i + 1]);
// }
// }
// }
void DrawWeft(Warp w0, Warp w1)
{
if (w0 == null || w1 == null)
{
return;
}
// void DrawWeft(WarpR w0, Warp w1)
// {
// if (w0 == null || w1 == null)
// {
// return;
// }
Gizmos.DrawLine(w0.transform.position, w1.transform.position);
// Gizmos.DrawLine(w0.transform.position, w1.transform.position);
for (int i = 0; i < w0.Particles.Count && i < w1.Particles.Count; ++i)
{
var p0 = w0.Particles[i];
var p1 = w1.Particles[i];
if (p0 != null && p0.Transform != null && p1 != null && p1.Transform != null)
{
Gizmos.DrawLine(p0.Transform.position, p1.Transform.position);
}
}
}
// for (int i = 0; i < w0.Particles.Count && i < w1.Particles.Count; ++i)
// {
// var p0 = w0.Particles[i];
// var p1 = w1.Particles[i];
// if (p0 != null && p0.Transform != null && p1 != null && p1.Transform != null)
// {
// Gizmos.DrawLine(p0.Transform.position, p1.Transform.position);
// }
// }
// }
}
}

View File

@ -11,7 +11,7 @@ namespace RotateParticle.Components
public class RotateParticleRuntimeProvider : MonoBehaviour, IVrm10SpringBoneRuntimeProvider
{
[SerializeField]
public List<Warp> Warps = new();
public List<WarpRoot> Warps = new();
[SerializeField]
public List<RectCloth> Cloths = new();
@ -25,7 +25,7 @@ namespace RotateParticle.Components
public void Reset()
{
Warps = GetComponentsInChildren<Warp>().ToList();
Warps = GetComponentsInChildren<WarpRoot>().ToList();
Cloths = GetComponentsInChildren<RectCloth>().ToList();
}
@ -39,7 +39,7 @@ namespace RotateParticle.Components
}
public static void FromVrm10(Vrm10Instance instance,
Func<GameObject, Warp> addWarp,
Func<GameObject, WarpRoot> addWarp,
Action<UnityEngine.Object> deleteObject)
{
foreach (var spring in instance.SpringBone.Springs)
@ -55,7 +55,7 @@ namespace RotateParticle.Components
continue;
}
var warp = root_joint.GetComponent<Warp>();
var warp = root_joint.GetComponent<WarpRoot>();
if (warp == null)
{
// var warp = Undo.AddComponent<Warp>(root_joint);
@ -82,12 +82,14 @@ namespace RotateParticle.Components
// breaking change from vrm-1.0
settings.radius = joints[i - 1].m_jointRadius;
var useInheritSettings = warp.BaseSettings.Equals(settings);
warp.Particles.Add(new Warp.Particle
if (useInheritSettings)
{
useInheritSettings = useInheritSettings,
OverrideSettings = settings,
Transform = joint.transform,
});
warp.UseBaseSettings(joint.transform);
}
else
{
warp.SetSettings(joint.transform, settings);
}
}
// Undo.DestroyObjectImmediate(joint);
deleteObject(joint);

View File

@ -1,132 +0,0 @@
using System;
using System.Collections.Generic;
using UniGLTF.SpringBoneJobs.Blittables;
using UnityEngine;
using UniVRM10;
namespace RotateParticle.Components
{
[AddComponentMenu("RotateParticle/Warp")]
[DisallowMultipleComponent]
public class Warp : MonoBehaviour
{
public static BlittableJointMutable DefaultSetting()
{
return new BlittableJointMutable
{
stiffnessForce = 1.0f,
gravityPower = 0,
gravityDir = new Vector3(0, -1.0f, 0),
dragForce = 0.4f,
radius = 0.02f,
};
}
public enum ParticleMode
{
/// <summary>
/// Use BaseSettings
/// </summary>
UseBase,
/// <summary>
/// Use specific settings
/// </summary>
Override,
/// <summary>
/// no animation
/// </summary>
Disabled,
}
/// <summary>
/// VRM10SpringBoneJoint に相当する
/// </summary>
[Serializable]
public class Particle
{
public bool useInheritSettings = true;
public BlittableJointMutable OverrideSettings = DefaultSetting();
public Transform Transform;
public BlittableJointMutable GetSettings(BlittableJointMutable baseSettings)
{
return useInheritSettings ? baseSettings : OverrideSettings;
}
}
[SerializeField]
public BlittableJointMutable BaseSettings = DefaultSetting();
/// <summary>
/// null のときは world root ではなく model root で処理
/// </summary>
[SerializeField]
public Transform Center;
/// <summary>
/// 枝分かれ不可
/// </summary>
[SerializeField]
public List<Particle> Particles = new();
[SerializeField]
public List<VRM10SpringBoneColliderGroup> ColliderGroups = new();
void Reset()
{
// Debug.Log("Warp.Reset");
}
public void AddParticleRecursive()
{
if (transform.childCount > 0)
{
AddParticleRecursive(transform.GetChild(0));
}
}
public void AddParticleRecursive(Transform t)
{
Particles.Add(new Particle
{
Transform = t,
});
if (t.childCount > 0)
{
AddParticleRecursive(t.GetChild(0));
}
}
void OnValidate()
{
// TODO: 枝分かれを削除
// Debug.Log("Warp.OnValidate");
}
internal List<Warp> ToList()
{
throw new NotImplementedException();
}
public void OnDrawGizmosSelected()
{
Gizmos.DrawSphere(transform.position, BaseSettings.radius);
Transform prev = transform;
foreach (var p in Particles)
{
if (p != null && p.Transform != null)
{
Gizmos.DrawWireSphere(p.Transform.position, p.GetSettings(BaseSettings).radius);
if (prev != null)
{
Gizmos.DrawLine(prev.position, p.Transform.position);
}
}
prev = p.Transform;
}
}
}
}

View File

@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF.SpringBoneJobs.Blittables;
using UnityEngine;
using UnityEngine.UIElements;
using UniVRM10;
namespace RotateParticle.Components
{
[AddComponentMenu("RotateParticle/WarpRoot")]
[DisallowMultipleComponent]
/// <summary>
/// Warp の root にアタッチする。
/// 子孫の Transform がすべて登録される。
/// </summary>
public class WarpRoot : MonoBehaviour
{
public static BlittableJointMutable DefaultSetting()
{
return new BlittableJointMutable
{
stiffnessForce = 1.0f,
gravityPower = 0,
gravityDir = new Vector3(0, -1.0f, 0),
dragForce = 0.4f,
radius = 0.02f,
};
}
public enum ParticleMode
{
/// <summary>
/// Use BaseSettings
/// </summary>
Base,
/// <summary>
/// Use specific settings
/// </summary>
Override,
/// <summary>
/// no animation
/// </summary>
Disabled,
}
/// <summary>
/// VRM10SpringBoneJoint に相当する
/// </summary>
[Serializable]
public struct Particle
{
public Transform Transform;
public ParticleMode Mode;
public BlittableJointMutable Settings;
public Particle(Transform t, ParticleMode mode, BlittableJointMutable settings)
{
Transform = t;
Mode = mode;
Settings = settings;
}
public Particle(Transform t, BlittableJointMutable settings)
: this(t, ParticleMode.Override, settings)
{
}
public Particle(Transform t)
: this(t, ParticleMode.Base, DefaultSetting())
{
}
}
[SerializeField]
public BlittableJointMutable BaseSettings = DefaultSetting();
/// <summary>
/// null のときは world root ではなく model root で処理
/// </summary>
[SerializeField]
public Transform Center;
/// <summary>
/// 枝分かれ不可
/// </summary>
[SerializeField]
private List<Particle> m_particles = new();
public IReadOnlyList<Particle> Particles => m_particles;
[SerializeField]
public List<VRM10SpringBoneColliderGroup> ColliderGroups = new();
// uitool kit 向け
public List<TreeViewItemData<Particle>> m_rootitems;
// 逆引き
Dictionary<Transform, int> m_map = new();
void Reset()
{
m_particles = GetComponentsInChildren<Transform>().Skip(1).Select(x => new Particle(x)).ToList();
}
void OnValidate()
{
m_map.Clear();
for (int i = 0; i < m_particles.Count; ++i)
{
var p = m_particles[i];
if (p.Mode == ParticleMode.Base)
{
p.Settings = BaseSettings;
m_particles[i] = p;
}
m_map.Add(p.Transform, i);
}
m_rootitems = MakeTree(-1);
}
public List<TreeViewItemData<Particle>> MakeTree(int id)
{
List<TreeViewItemData<Particle>> items = new();
foreach (Transform child_transform in id==-1 ? transform : m_particles[id].Transform)
{
var child_id = m_map[child_transform];
var item = (child_transform.childCount > 0)
? new TreeViewItemData<Particle>(child_id, m_particles[child_id], MakeTree(child_id))
: new TreeViewItemData<Particle>(child_id, m_particles[child_id])
;
items.Add(item);
}
return items;
}
public Particle GetParticle(int id)
{
return m_particles[id];
}
public void UseBaseSettings(Transform t)
{
if (t == null) return;
for (int i = 0; i < m_particles.Count; ++i)
{
var p = m_particles[i];
if (p.Transform == t)
{
p.Mode = ParticleMode.Base;
p.Settings = BaseSettings;
m_particles[i] = p;
break;
}
}
}
public void SetSettings(Transform t, BlittableJointMutable settings)
{
if (t == null) return;
for (int i = 0; i < m_particles.Count; ++i)
{
var p = m_particles[i];
if (p.Transform == t)
{
p.Mode = ParticleMode.Override;
p.Settings = settings;
m_particles[i] = p;
break;
}
}
}
// internal List<Warp> ToList()
// {
// throw new NotImplementedException();
// }
public void OnDrawGizmosSelected()
{
Gizmos.DrawSphere(transform.position, BaseSettings.radius);
foreach (var p in Particles)
{
if (p.Transform == null || p.Mode == ParticleMode.Disabled)
{
continue;
}
Gizmos.DrawWireSphere(p.Transform.position, p.Settings.radius);
if (TryGetClosestParent(p.Transform, out var parent))
{
Gizmos.DrawLine(p.Transform.position, parent.position);
}
}
}
bool TryGetClosestParent(Transform t, out Transform parent)
{
var current = t.parent;
while (current != null)
{
if (current == transform)
{
parent = transform;
return true;
}
var index = m_map[current];
var p = m_particles[index];
if (p.Mode != ParticleMode.Disabled)
{
parent = p.Transform;
return true;
}
}
parent = default;
return false;
}
}
}

View File

@ -98,7 +98,7 @@ namespace RotateParticle.Jobs
List<TransformInfo> info = new();
List<Vector3> positions = new();
List<WarpInfo> warps = new();
var warpSrcs = vrm.GetComponentsInChildren<Warp>();
var warpSrcs = vrm.GetComponentsInChildren<WarpRoot>();
for (int warpIndex = 0; warpIndex < warpSrcs.Length; ++warpIndex)
{
var warp = warpSrcs[warpIndex];
@ -136,7 +136,7 @@ namespace RotateParticle.Jobs
var parentIndex = warpRootTransformIndex.index;
foreach (var particle in warp.Particles)
{
if (particle != null && particle.Transform != null)
if (particle.Transform != null && particle.Mode!=WarpRoot.ParticleMode.Disabled)
{
var outputParticleTransformIndex = GetTransformIndex(particle.Transform, new TransformInfo
{
@ -144,7 +144,7 @@ namespace RotateParticle.Jobs
ParentIndex = parentIndex,
InitLocalPosition = vrm.DefaultTransformStates[particle.Transform].LocalPosition,
InitLocalRotation = vrm.DefaultTransformStates[particle.Transform].LocalRotation,
Settings = particle.GetSettings(warp.BaseSettings),
Settings = particle.Settings,
}, info, positions);
parentIndex = outputParticleTransformIndex.index;
}

View File

@ -12,7 +12,7 @@ namespace RotateParticle
public List<RotateParticle> _particles = new();
public List<Transform> _particleTransforms = new();
public Strand MakeParticleStrand(SimulationEnv env, Warp warp)
public Strand MakeParticleStrand(SimulationEnv env, WarpRoot warp)
{
var strand = new Strand();
@ -24,7 +24,7 @@ namespace RotateParticle
foreach (var particle in warp.Particles)
{
var child_index = _MakeAParticle(joint, env, particle.Transform,
particle.GetSettings(warp.BaseSettings).radius, 1);
particle.Settings.radius, 1);
var child = _particles[child_index];
strand.Particles.Add(child);
joint.Children.Add(child);

View File

@ -20,7 +20,7 @@ namespace RotateParticle
Stiffness = 0.07f,
};
readonly List<Warp> _warps = new();
readonly List<WarpRoot> _warps = new();
readonly List<RectCloth> _cloths = new();
public List<VRM10SpringBoneColliderGroup> _colliderGroups = new();
@ -65,7 +65,7 @@ namespace RotateParticle
RectCloth cloth,
ParticleList list,
List<(SpringConstraint, ClothRectCollision)> clothRects,
Dictionary<Warp, Strand> strandMap)
Dictionary<WarpRoot, Strand> strandMap)
{
for (int i = 1; i < cloth.Warps.Count; ++i)
{
@ -139,8 +139,8 @@ namespace RotateParticle
async Task IRotateParticleSystem.InitializeAsync(Vrm10Instance vrm, IAwaitCaller awaitCaller)
{
var strandMap = new Dictionary<Warp, Strand>();
var warps = vrm.GetComponentsInChildren<Warp>();
var strandMap = new Dictionary<WarpRoot, Strand>();
var warps = vrm.GetComponentsInChildren<WarpRoot>();
foreach (var warp in warps)
{
var strands = new List<Strand>();