diff options
author | chai <chaifix@163.com> | 2022-07-08 09:22:29 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2022-07-08 09:22:29 +0800 |
commit | d4bc85c8642cfd0c98ef73710aa9202a7d774852 (patch) | |
tree | f7c17b4c1915a14ed60f2b4a253115452df041d0 /Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs | |
parent | 8110c37b5890035ef73f936b3fc5964bf49bcf11 (diff) |
+ Malenia test
Diffstat (limited to 'Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs')
-rw-r--r-- | Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs b/Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs new file mode 100644 index 00000000..82d41f55 --- /dev/null +++ b/Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs @@ -0,0 +1,235 @@ +using UnityEngine; + +[AddComponentMenu("Dynamic Bone/Dynamic Bone Collider")] +public class DynamicBoneCollider : DynamicBoneColliderBase +{ +#if UNITY_5_3_OR_NEWER + [Tooltip("The radius of the sphere or capsule.")] +#endif + public float m_Radius = 0.5f; + +#if UNITY_5_3_OR_NEWER + [Tooltip("The height of the capsule.")] +#endif + public float m_Height = 0; + + void OnValidate() + { + m_Radius = Mathf.Max(m_Radius, 0); + m_Height = Mathf.Max(m_Height, 0); + } + + public override bool Collide(ref Vector3 particlePosition, float particleRadius) + { + float radius = m_Radius * Mathf.Abs(transform.lossyScale.x); + float h = m_Height * 0.5f - m_Radius; + if (h <= 0) + { + if (m_Bound == Bound.Outside) + return OutsideSphere(ref particlePosition, particleRadius, transform.TransformPoint(m_Center), radius); + else + return InsideSphere(ref particlePosition, particleRadius, transform.TransformPoint(m_Center), radius); + } + else + { + Vector3 c0 = m_Center; + Vector3 c1 = m_Center; + + switch (m_Direction) + { + case Direction.X: + c0.x -= h; + c1.x += h; + break; + case Direction.Y: + c0.y -= h; + c1.y += h; + break; + case Direction.Z: + c0.z -= h; + c1.z += h; + break; + } + if (m_Bound == Bound.Outside) + return OutsideCapsule(ref particlePosition, particleRadius, transform.TransformPoint(c0), transform.TransformPoint(c1), radius); + else + return InsideCapsule(ref particlePosition, particleRadius, transform.TransformPoint(c0), transform.TransformPoint(c1), radius); + } + } + + static bool OutsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius) + { + float r = sphereRadius + particleRadius; + float r2 = r * r; + Vector3 d = particlePosition - sphereCenter; + float len2 = d.sqrMagnitude; + + // if is inside sphere, project onto sphere surface + if (len2 > 0 && len2 < r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = sphereCenter + d * (r / len); + return true; + } + return false; + } + + static bool InsideSphere(ref Vector3 particlePosition, float particleRadius, Vector3 sphereCenter, float sphereRadius) + { + float r = sphereRadius - particleRadius; + float r2 = r * r; + Vector3 d = particlePosition - sphereCenter; + float len2 = d.sqrMagnitude; + + // if is outside sphere, project onto sphere surface + if (len2 > r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = sphereCenter + d * (r / len); + return true; + } + return false; + } + + static bool OutsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius) + { + float r = capsuleRadius + particleRadius; + float r2 = r * r; + Vector3 dir = capsuleP1 - capsuleP0; + Vector3 d = particlePosition - capsuleP0; + float t = Vector3.Dot(d, dir); + + if (t <= 0) + { + // check sphere1 + float len2 = d.sqrMagnitude; + if (len2 > 0 && len2 < r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = capsuleP0 + d * (r / len); + return true; + } + } + else + { + float dl = dir.sqrMagnitude; + if (t >= dl) + { + // check sphere2 + d = particlePosition - capsuleP1; + float len2 = d.sqrMagnitude; + if (len2 > 0 && len2 < r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = capsuleP1 + d * (r / len); + return true; + } + } + else if (dl > 0) + { + // check cylinder + t /= dl; + d -= dir * t; + float len2 = d.sqrMagnitude; + if (len2 > 0 && len2 < r2) + { + float len = Mathf.Sqrt(len2); + particlePosition += d * ((r - len) / len); + return true; + } + } + } + return false; + } + + static bool InsideCapsule(ref Vector3 particlePosition, float particleRadius, Vector3 capsuleP0, Vector3 capsuleP1, float capsuleRadius) + { + float r = capsuleRadius - particleRadius; + float r2 = r * r; + Vector3 dir = capsuleP1 - capsuleP0; + Vector3 d = particlePosition - capsuleP0; + float t = Vector3.Dot(d, dir); + + if (t <= 0) + { + // check sphere1 + float len2 = d.sqrMagnitude; + if (len2 > r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = capsuleP0 + d * (r / len); + return true; + } + } + else + { + float dl = dir.sqrMagnitude; + if (t >= dl) + { + // check sphere2 + d = particlePosition - capsuleP1; + float len2 = d.sqrMagnitude; + if (len2 > r2) + { + float len = Mathf.Sqrt(len2); + particlePosition = capsuleP1 + d * (r / len); + return true; + } + } + else if (dl > 0) + { + // check cylinder + t /= dl; + d -= dir * t; + float len2 = d.sqrMagnitude; + if (len2 > r2) + { + float len = Mathf.Sqrt(len2); + particlePosition += d * ((r - len) / len); + return true; + } + } + } + return false; + } + + void OnDrawGizmosSelected() + { + if (!enabled) + return; + + if (m_Bound == Bound.Outside) + Gizmos.color = Color.yellow; + else + Gizmos.color = Color.magenta; + float radius = m_Radius * Mathf.Abs(transform.lossyScale.x); + float h = m_Height * 0.5f - m_Radius; + if (h <= 0) + { + Gizmos.DrawWireSphere(transform.TransformPoint(m_Center), radius); + } + else + { + Vector3 c0 = m_Center; + Vector3 c1 = m_Center; + + switch (m_Direction) + { + case Direction.X: + c0.x -= h; + c1.x += h; + break; + case Direction.Y: + c0.y -= h; + c1.y += h; + break; + case Direction.Z: + c0.z -= h; + c1.z += h; + break; + } + Gizmos.DrawWireSphere(transform.TransformPoint(c0), radius); + Gizmos.DrawWireSphere(transform.TransformPoint(c1), radius); + } + } +} |