Joint別パラメーターを実装

This commit is contained in:
ousttrue
2021-01-22 15:31:14 +09:00
parent 79b302ec38
commit 178c51ddec
10 changed files with 129 additions and 163 deletions

View File

@@ -36,8 +36,6 @@ namespace UniVRM10
}
public Vector3 m_boneAxis;
public float Radius { get; set; }
public SpringBoneLogic(Transform center, Transform transform, Vector3 localChildPosition)
{
m_transform = transform;
@@ -73,7 +71,7 @@ namespace UniVRM10
public void Update(Transform center,
float stiffnessForce, float dragForce, Vector3 external,
List<InternalCollider> colliders)
List<InternalCollider> colliders, float jointRadius)
{
var currentTail = center != null
? center.TransformPoint(m_currentTail)
@@ -95,7 +93,7 @@ namespace UniVRM10
nextTail = m_transform.position + (nextTail - m_transform.position).normalized * m_length;
// Collisionで移動
nextTail = Collision(colliders, nextTail);
nextTail = Collision(colliders, nextTail, jointRadius);
m_prevTail = center != null
? center.InverseTransformPoint(currentTail)
@@ -117,14 +115,14 @@ namespace UniVRM10
nextTail - m_transform.position) * rotation;
}
bool TrySphereCollision(Vector3 worldPosition, float radius, ref Vector3 nextTail)
bool TrySphereCollision(Vector3 worldPosition, float radius, ref Vector3 nextTail, float jointRadius)
{
var r = Radius + radius;
var r = jointRadius + radius;
if (Vector3.SqrMagnitude(nextTail - worldPosition) <= (r * r))
{
// ヒット。Colliderの半径方向に押し出す
var normal = (nextTail - worldPosition).normalized;
var posFromCollider = worldPosition + normal * (Radius + radius);
var posFromCollider = worldPosition + normal * (jointRadius + radius);
// 長さをboneLengthに強制
nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * m_length;
return true;
@@ -135,7 +133,7 @@ namespace UniVRM10
}
}
bool TryCapsuleCollision(in InternalCollider collider, ref Vector3 nextTail)
bool TryCapsuleCollision(in InternalCollider collider, ref Vector3 nextTail, float jointRadius)
{
var P = collider.WorldTail - collider.WorldPosition;
var Q = m_transform.position - collider.WorldPosition;
@@ -143,22 +141,22 @@ namespace UniVRM10
if (dot <= 0)
{
// head側半球の球判定
return TrySphereCollision(collider.WorldPosition, collider.Radius, ref nextTail);
return TrySphereCollision(collider.WorldPosition, collider.Radius, ref nextTail, jointRadius);
}
var t = dot / P.magnitude;
if (t >= 1.0f)
{
// tail側半球の球判定
return TrySphereCollision(collider.WorldTail, collider.Radius, ref nextTail);
return TrySphereCollision(collider.WorldTail, collider.Radius, ref nextTail, jointRadius);
}
// head-tail上の m_transform.position との最近点
var p = collider.WorldPosition + P * t;
return TrySphereCollision(p, collider.Radius, ref nextTail);
return TrySphereCollision(p, collider.Radius, ref nextTail, jointRadius);
}
protected virtual Vector3 Collision(List<InternalCollider> colliders, Vector3 nextTail)
protected virtual Vector3 Collision(List<InternalCollider> colliders, Vector3 nextTail, float jointRadius)
{
foreach (var collider in colliders)
{
@@ -166,11 +164,11 @@ namespace UniVRM10
switch (collider.ColliderTypes)
{
case VRM10SpringBoneColliderTypes.Sphere:
TrySphereCollision(collider.WorldPosition, collider.Radius, ref nextTail);
TrySphereCollision(collider.WorldPosition, collider.Radius, ref nextTail, jointRadius);
break;
case VRM10SpringBoneColliderTypes.Capsule:
TryCapsuleCollision(in collider, ref nextTail);
TryCapsuleCollision(in collider, ref nextTail, jointRadius);
break;
default:

View File

@@ -1,111 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
public class SpringBoneProcessor
{
List<SpringBoneLogic> m_logics = new List<SpringBoneLogic>();
Dictionary<Transform, Quaternion> m_initialLocalRotationMap;
public void ResetSpringBone()
{
foreach (var verlet in m_logics)
{
verlet.Head.localRotation = Quaternion.identity;
}
}
public void SetupRecursive(Transform parent, Transform center)
{
if (parent.childCount == 0)
{
// 末端に追加のスプリングを付加する
var delta = parent.position - parent.parent.position;
var childPosition = parent.position + delta.normalized * 0.07f;
m_logics.Add(new SpringBoneLogic(center, parent, parent.worldToLocalMatrix.MultiplyPoint(childPosition)));
}
else
{
// 最初の子ボーンを尻尾としてスプリングを付加する
var firstChild = parent.GetChild(0);
var localPosition = firstChild.localPosition;
var scale = firstChild.lossyScale;
m_logics.Add(new SpringBoneLogic(center, parent,
new Vector3(
localPosition.x * scale.x,
localPosition.y * scale.y,
localPosition.z * scale.z
)))
;
}
foreach (Transform child in parent)
{
SetupRecursive(child, center);
}
}
void Setup(List<Transform> RootBones, Transform m_center, bool force = false)
{
if (force || m_initialLocalRotationMap == null)
{
m_initialLocalRotationMap = new Dictionary<Transform, Quaternion>();
}
else
{
// restore initial rotation
foreach (var kv in m_initialLocalRotationMap)
{
kv.Key.localRotation = kv.Value;
}
m_initialLocalRotationMap.Clear();
}
m_logics.Clear();
foreach (var transform in RootBones)
{
if (transform != null)
{
foreach (var x in transform.Traverse())
{
// backup initial rotation
m_initialLocalRotationMap[x] = x.localRotation;
}
SetupRecursive(transform, m_center);
}
}
}
public void Update(List<Transform> RootBones, List<SpringBoneLogic.InternalCollider> m_colliderList,
float stiffness, float m_dragForce, Vector3 external,
float m_hitRadius, Transform m_center)
{
if (m_logics == null || m_logics.Count == 0)
{
Setup(RootBones, m_center);
}
foreach (var verlet in m_logics)
{
verlet.Radius = m_hitRadius;
verlet.Update(m_center,
stiffness,
m_dragForce,
external,
m_colliderList
);
}
}
public void DrawGizmos(Transform m_center, float m_hitRadius, Color m_gizmoColor)
{
foreach (var verlet in m_logics)
{
verlet.DrawGizmo(m_center, m_hitRadius, m_gizmoColor);
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UniVRM10
@@ -20,25 +21,6 @@ namespace UniVRM10
[SerializeField]
Color m_gizmoColor = Color.yellow;
[Serializable]
public class VRM10SpringJoint
{
[SerializeField, Range(0, 4), Header("Settings")]
public float m_stiffnessForce = 1.0f;
[SerializeField, Range(0, 2)]
public float m_gravityPower = 0;
[SerializeField]
public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0);
[SerializeField, Range(0, 1)]
public float m_dragForce = 0.4f;
[SerializeField, Range(0, 0.5f), Header("Collision")]
public float m_hitRadius = 0.02f;
}
[SerializeField]
public Transform m_center;
@@ -48,12 +30,17 @@ namespace UniVRM10
[SerializeField]
public List<VRM10SpringBoneColliderGroup> ColliderGroups = new List<VRM10SpringBoneColliderGroup>();
SpringBoneProcessor m_processor = new SpringBoneProcessor();
[ContextMenu("Reset bones")]
public void ResetSpringBone()
public void ResetJoints()
{
m_processor.ResetSpringBone();
foreach (var joint in Joints)
{
if (joint != null)
{
joint.Transform.localRotation = Quaternion.identity;
}
}
}
List<SpringBoneLogic.InternalCollider> m_colliderList = new List<SpringBoneLogic.InternalCollider>();
@@ -101,20 +88,30 @@ namespace UniVRM10
}
}
// var stiffness = m_stiffnessForce * Time.deltaTime;
// var external = m_gravityDir * (m_gravityPower * Time.deltaTime);
// m_processor.Update(RootBones, m_colliderList,
// stiffness, m_dragForce, external,
// m_hitRadius, m_center);
{
// udpate joints
VRM10SpringJoint lastJoint = Joints.FirstOrDefault(x => x != null);
foreach (var joint in Joints.Where(x => x != null).Skip(1))
{
lastJoint.Update(m_center, Time.deltaTime, m_colliderList, joint);
lastJoint = joint;
}
lastJoint.Update(m_center, Time.deltaTime, m_colliderList, null);
}
}
private void OnDrawGizmos()
{
// if (m_drawGizmo)
// {
// m_processor.DrawGizmos(m_center, m_hitRadius, m_gizmoColor);
// }
if (m_drawGizmo)
{
foreach (var joint in Joints)
{
if (joint != null)
{
joint.DrawGizmo(m_center, m_gizmoColor);
}
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UniVRM10
{
[Serializable]
public class VRM10SpringJoint
{
[SerializeField]
public Transform Transform;
public VRM10SpringJoint(Transform t)
{
Transform = t;
}
[SerializeField, Range(0, 4), Header("Settings")]
public float m_stiffnessForce = 1.0f;
[SerializeField, Range(0, 2)]
public float m_gravityPower = 0;
[SerializeField]
public Vector3 m_gravityDir = new Vector3(0, -1.0f, 0);
[SerializeField, Range(0, 1)]
public float m_dragForce = 0.4f;
[SerializeField, Range(0, 0.5f), Header("Collision")]
public float m_hitRadius = 0.02f;
SpringBoneLogic m_logic;
public void DrawGizmo(Transform center, Color color)
{
if (m_logic != null)
{
m_logic.DrawGizmo(center, m_hitRadius, color);
}
else
{
// TODO
}
}
public void Update(Transform center, float deltaTime, List<SpringBoneLogic.InternalCollider> colliders, VRM10SpringJoint tail)
{
if (m_logic == null)
{
// Setup(joints, m_center);
// SetupRecursive(joint, m_center);
if (tail == null)
{
// 末端に追加のスプリングを付加する
var delta = Transform.position - Transform.parent.position;
var childPosition = Transform.position + delta.normalized * 0.07f;
m_logic = new SpringBoneLogic(center, Transform, Transform.worldToLocalMatrix.MultiplyPoint(childPosition));
}
else
{
// 最初の子ボーンを尻尾としてスプリングを付加する
var localPosition = tail.Transform.localPosition;
var scale = tail.Transform.lossyScale;
m_logic = new SpringBoneLogic(center, Transform,
new Vector3(
localPosition.x * scale.x,
localPosition.y * scale.y,
localPosition.z * scale.z
));
}
}
m_logic.Update(center, m_stiffnessForce * deltaTime, m_dragForce, m_gravityDir * (m_gravityPower * deltaTime), colliders, m_hitRadius);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: fb0714842bac26b44b774260bbef58c3
guid: 5a7fc353e202e4f44a1025ba6e806262
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -606,7 +606,7 @@ namespace UniVRM10
static void AssignHumanoid(List<Node> nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key)
{
if (humanBone!=null && humanBone.Node.HasValue)
if (humanBone != null && humanBone.Node.HasValue)
{
nodes[humanBone.Node.Value].HumanoidBone = key;
}
@@ -722,7 +722,7 @@ namespace UniVRM10
// joint
foreach (var gltfJoint in gltfSpring.Joints)
{
var joint = new SpringJoint();
var joint = new SpringJoint(nodes[gltfJoint.Node.Value]);
joint.HitRadius = gltfJoint.HitRadius.Value;
joint.DragForce = gltfJoint.DragForce.Value;
joint.GravityDir = gltfJoint.GravityDir.ToVector3();

View File

@@ -606,7 +606,6 @@ namespace UniVRM10
public static void Check(ListTreeNode<JsonValue> vrm0, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone vrm1, List<UniGLTF.glTFNode> nodes)
{
var a = 0;
// Migration.CheckSpringBone(vrm0["secondaryAnimation"], vrm1.sp)
}
#endregion

View File

@@ -300,7 +300,8 @@ namespace UniVRM10
// create joint for the spring
foreach (var vrmJoint in vrmSpring.Joints)
{
var joint = new VRM10SpringBone.VRM10SpringJoint();
var go = asset.Map.Nodes[vrmJoint.Node];
var joint = new VRM10SpringJoint(go.transform);
joint.m_stiffnessForce = vrmJoint.Stiffness;
joint.m_gravityPower = vrmJoint.GravityPower;

View File

@@ -356,7 +356,7 @@ namespace UniVRM10
foreach (var joint in springBone.Joints)
{
vrmSpringBone.Joints.Add(new VrmLib.SpringJoint
vrmSpringBone.Joints.Add(new VrmLib.SpringJoint(Nodes[joint.Transform.gameObject])
{
Stiffness = joint.m_stiffnessForce,
GravityPower = joint.m_gravityPower,

View File

@@ -53,6 +53,11 @@ namespace VrmLib
{
public readonly Node Node;
public SpringJoint(Node node)
{
Node = node;
}
public float DragForce;
public Vector3 GravityDir;