summaryrefslogtreecommitdiff
path: root/Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs')
-rw-r--r--Other/Malenia/Assets/DynamicBone/Scripts/DynamicBoneCollider.cs235
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);
+ }
+ }
+}