mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-07-01 04:10:17 -05:00
collision
This commit is contained in:
parent
ee68e48f0f
commit
2cc166f193
|
|
@ -14,5 +14,20 @@ namespace VRM.SpringBone
|
|||
var scale = Mathf.Max(Mathf.Max(ls.x, ls.y), ls.z);
|
||||
Radius = scale * collider.Radius;
|
||||
}
|
||||
|
||||
public Vector3 Collide(SpringBoneSettings settings, Transform m_transform, SpringBoneJointInit init, Vector3 nextTail)
|
||||
{
|
||||
var m_radius = settings.HitRadius * m_transform.UniformedLossyScale();
|
||||
var r = m_radius + Radius;
|
||||
if (Vector3.SqrMagnitude(nextTail - Position) <= (r * r))
|
||||
{
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
var normal = (nextTail - Position).normalized;
|
||||
var posFromCollider = Position + normal * (m_radius + Radius);
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * init.Length;
|
||||
}
|
||||
return nextTail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +1,57 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM.SpringBone
|
||||
{
|
||||
struct JointState
|
||||
/// <summary>
|
||||
/// original from
|
||||
/// http://rocketjump.skr.jp/unity3d/109/
|
||||
///
|
||||
/// この型のフィールドはSpringBoneのライフサイクルを通じて不変。
|
||||
/// </summary>
|
||||
struct SpringBoneJointInit
|
||||
{
|
||||
public Vector3 CurrentTail;
|
||||
public Vector3 PrevTail;
|
||||
public Vector3 BoneAxis;
|
||||
public float Length;
|
||||
public Quaternion LocalRotation;
|
||||
|
||||
public static JointState Init(Transform center, Transform transform, Vector3 localChildPosition)
|
||||
public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail)
|
||||
{
|
||||
var worldChildPosition = transform.TransformPoint(localChildPosition);
|
||||
var tail = center != null
|
||||
? center.InverseTransformPoint(worldChildPosition)
|
||||
: worldChildPosition;
|
||||
return new JointState
|
||||
{
|
||||
CurrentTail = tail,
|
||||
PrevTail = tail,
|
||||
};
|
||||
var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation;
|
||||
return Quaternion.FromToRotation(rotation * BoneAxis,
|
||||
nextTail - m_transform.position) * rotation;
|
||||
}
|
||||
|
||||
public static JointState Make(Transform center, Vector3 currentTail, Vector3 nextTail)
|
||||
public Vector3 CalcNextTail(float deltaTime, Transform center, Transform m_transform,
|
||||
SpringBoneSettings settings, SpringBoneJointState _state)
|
||||
{
|
||||
return new JointState
|
||||
{
|
||||
PrevTail = center != null
|
||||
? center.InverseTransformPoint(currentTail)
|
||||
: currentTail,
|
||||
CurrentTail = center != null
|
||||
? center.InverseTransformPoint(nextTail)
|
||||
: nextTail,
|
||||
};
|
||||
var state = _state.ToWorld(center);
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
var nextTail = state.CurrentTail
|
||||
+ (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標
|
||||
+ settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
var position = m_transform.position;
|
||||
nextTail = position + (nextTail - position).normalized * Length;
|
||||
return nextTail;
|
||||
}
|
||||
|
||||
public JointState ToWorld(Transform center)
|
||||
public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color, SpringBoneJointState m_state)
|
||||
{
|
||||
return new JointState
|
||||
{
|
||||
CurrentTail = center != null
|
||||
? center.TransformPoint(CurrentTail)
|
||||
: CurrentTail,
|
||||
PrevTail = center != null
|
||||
? center.TransformPoint(PrevTail)
|
||||
: PrevTail,
|
||||
};
|
||||
var state = m_state.ToWorld(center);
|
||||
var m_radius = settings.HitRadius * m_transform.UniformedLossyScale();
|
||||
|
||||
Gizmos.color = Color.gray;
|
||||
Gizmos.DrawLine(state.CurrentTail, state.PrevTail);
|
||||
Gizmos.DrawWireSphere(state.PrevTail, m_radius);
|
||||
|
||||
Gizmos.color = color;
|
||||
Gizmos.DrawLine(state.CurrentTail, m_transform.position);
|
||||
Gizmos.DrawWireSphere(state.CurrentTail, m_radius);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3bbcafd66c035184b8aa868b65c01c1d
|
||||
guid: 2602939771f9eb2428b140e10fa899f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,80 +1,52 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM.SpringBone
|
||||
{
|
||||
/// <summary>
|
||||
/// original from
|
||||
/// http://rocketjump.skr.jp/unity3d/109/
|
||||
///
|
||||
/// Joint 状態(初期・フレーム)を管理する
|
||||
/// 毎フレーム更新される Verlet 積分の位置状態
|
||||
/// </summary>
|
||||
struct SpringBoneJointInit
|
||||
struct SpringBoneJointState
|
||||
{
|
||||
public Vector3 BoneAxis;
|
||||
public float Length;
|
||||
public Quaternion LocalRotation;
|
||||
public Vector3 CurrentTail;
|
||||
public Vector3 PrevTail;
|
||||
|
||||
public Quaternion CalcRotation(Transform m_transform, Vector3 nextTail)
|
||||
public static SpringBoneJointState Init(Transform center, Transform transform, Vector3 localChildPosition)
|
||||
{
|
||||
var rotation = (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation;
|
||||
return Quaternion.FromToRotation(rotation * BoneAxis,
|
||||
nextTail - m_transform.position) * rotation;
|
||||
}
|
||||
|
||||
public JointState Update(float deltaTime, Transform center, Transform m_transform,
|
||||
SpringBoneSettings settings,
|
||||
List<SphereCollider> colliders, JointState _state)
|
||||
{
|
||||
var state = _state.ToWorld(center);
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
var nextTail = state.CurrentTail
|
||||
+ (state.CurrentTail - state.PrevTail) * (1.0f - settings.DragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ (m_transform.parent != null ? m_transform.parent.rotation : Quaternion.identity) * LocalRotation * BoneAxis * settings.StiffnessForce * deltaTime // 親の回転による子ボーンの移動目標
|
||||
+ settings.GravityDir * (settings.GravityPower * deltaTime); // 外力による移動量
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
var position = m_transform.position;
|
||||
nextTail = position + (nextTail - position).normalized * Length;
|
||||
|
||||
// Collisionで移動
|
||||
nextTail = Collision(m_transform, settings, colliders, nextTail);
|
||||
|
||||
return JointState.Make(center, currentTail: state.CurrentTail, nextTail: nextTail);
|
||||
}
|
||||
|
||||
Vector3 Collision(Transform m_transform, SpringBoneSettings settings, List<SphereCollider> colliders, Vector3 nextTail)
|
||||
{
|
||||
foreach (var collider in colliders)
|
||||
var worldChildPosition = transform.TransformPoint(localChildPosition);
|
||||
var tail = center != null
|
||||
? center.InverseTransformPoint(worldChildPosition)
|
||||
: worldChildPosition;
|
||||
return new SpringBoneJointState
|
||||
{
|
||||
var m_radius = settings.HitRadius * m_transform.UniformedLossyScale();
|
||||
var r = m_radius + collider.Radius;
|
||||
if (Vector3.SqrMagnitude(nextTail - collider.Position) <= (r * r))
|
||||
{
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
var normal = (nextTail - collider.Position).normalized;
|
||||
var posFromCollider = collider.Position + normal * (m_radius + collider.Radius);
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = m_transform.position + (posFromCollider - m_transform.position).normalized * Length;
|
||||
}
|
||||
}
|
||||
return nextTail;
|
||||
CurrentTail = tail,
|
||||
PrevTail = tail,
|
||||
};
|
||||
}
|
||||
|
||||
public void DrawGizmo(Transform center, Transform m_transform, SpringBoneSettings settings, Color color, JointState m_state)
|
||||
public static SpringBoneJointState Make(Transform center, Vector3 currentTail, Vector3 nextTail)
|
||||
{
|
||||
var state = m_state.ToWorld(center);
|
||||
var m_radius = settings.HitRadius * m_transform.UniformedLossyScale();
|
||||
|
||||
Gizmos.color = Color.gray;
|
||||
Gizmos.DrawLine(state.CurrentTail, state.PrevTail);
|
||||
Gizmos.DrawWireSphere(state.PrevTail, m_radius);
|
||||
|
||||
Gizmos.color = color;
|
||||
Gizmos.DrawLine(state.CurrentTail, m_transform.position);
|
||||
Gizmos.DrawWireSphere(state.CurrentTail, m_radius);
|
||||
return new SpringBoneJointState
|
||||
{
|
||||
PrevTail = center != null
|
||||
? center.InverseTransformPoint(currentTail)
|
||||
: currentTail,
|
||||
CurrentTail = center != null
|
||||
? center.InverseTransformPoint(nextTail)
|
||||
: nextTail,
|
||||
};
|
||||
}
|
||||
|
||||
public SpringBoneJointState ToWorld(Transform center)
|
||||
{
|
||||
return new SpringBoneJointState
|
||||
{
|
||||
CurrentTail = center != null
|
||||
? center.TransformPoint(CurrentTail)
|
||||
: CurrentTail,
|
||||
PrevTail = center != null
|
||||
? center.TransformPoint(PrevTail)
|
||||
: PrevTail,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2602939771f9eb2428b140e10fa899f2
|
||||
guid: 3bbcafd66c035184b8aa868b65c01c1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -4,18 +4,10 @@ using UnityEngine;
|
|||
|
||||
namespace VRM.SpringBone
|
||||
{
|
||||
/// <summary>
|
||||
/// 同じ設定のスプリングをまとめて処理する。
|
||||
///
|
||||
/// root o-o-o-x tail
|
||||
///
|
||||
/// [vrm0] tail は 7cm 遠にダミーの joint があるようにふるまう。
|
||||
///
|
||||
/// </summary>
|
||||
class SpringBoneSystem
|
||||
{
|
||||
Dictionary<Transform, Quaternion> m_initialLocalRotationMap;
|
||||
List<(Transform, SpringBoneJointInit, JointState)> m_joints = new();
|
||||
List<(Transform, SpringBoneJointInit, SpringBoneJointState)> m_joints = new();
|
||||
List<SphereCollider> m_colliders = new();
|
||||
|
||||
public void Setup(SceneInfo scene, bool force)
|
||||
|
|
@ -79,7 +71,7 @@ namespace VRM.SpringBone
|
|||
BoneAxis = localChildPosition.normalized,
|
||||
Length = localChildPosition.magnitude,
|
||||
},
|
||||
JointState.Init(center, parent, localChildPosition)));
|
||||
SpringBoneJointState.Init(center, parent, localChildPosition)));
|
||||
|
||||
foreach (Transform child in parent) SetupRecursive(center, child);
|
||||
}
|
||||
|
|
@ -95,6 +87,7 @@ namespace VRM.SpringBone
|
|||
Setup(scene, false);
|
||||
}
|
||||
|
||||
// collider の収集
|
||||
m_colliders.Clear();
|
||||
if (scene.ColliderGroups != null)
|
||||
{
|
||||
|
|
@ -113,11 +106,21 @@ namespace VRM.SpringBone
|
|||
for (int i = 0; i < m_joints.Count; ++i)
|
||||
{
|
||||
var (transform, init, state) = m_joints[i];
|
||||
var nextState = init.Update(deltaTime, scene.Center, transform, settings, m_colliders, state);
|
||||
m_joints[i] = (transform, init, nextState);
|
||||
|
||||
// Spring処理
|
||||
var nextTail = init.CalcNextTail(deltaTime, scene.Center, transform, settings, state);
|
||||
|
||||
// Collision
|
||||
foreach (var collider in m_colliders)
|
||||
{
|
||||
nextTail = collider.Collide(settings, transform, init, nextTail);
|
||||
}
|
||||
|
||||
// 状態更新
|
||||
m_joints[i] = (transform, init, SpringBoneJointState.Make(scene.Center, currentTail: state.CurrentTail, nextTail: nextTail));
|
||||
|
||||
//回転を適用
|
||||
var r = init.CalcRotation(transform, nextState.CurrentTail);
|
||||
var r = init.CalcRotation(transform, nextTail);
|
||||
transform.rotation = r;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user