diff options
Diffstat (limited to 'WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs')
-rw-r--r-- | WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs b/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs new file mode 100644 index 0000000..d5fd913 --- /dev/null +++ b/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs @@ -0,0 +1,183 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +/// <summary> +/// 碰撞检测 +/// </summary> +public partial class PhysicsManager : Singleton<PhysicsManager> +{ + + /// <summary> + /// circle x,y,radius + /// </summary> + /// <param name="pos1"></param> + /// <param name="r1"></param> + /// <param name="pos2"></param> + /// <param name="r2"></param> + /// <returns></returns> + public static bool CircleVsCircle(Vector2 pos1, float r1, Vector2 pos2, float r2) + { + return (pos1 - pos2).magnitude <= r1 + r2; + } + + public static bool CircleVsCircle(Vector3 c1, Vector3 c2) + { + return (c1.xy() - c2.xy()).magnitude <= c1.z + c2.z; + } + + /// <summary> + /// intersection是r2对于r1 + /// </summary> + /// <param name="b1"></param> + /// <param name="b2"></param> + /// <param name="intersection"></param> + /// <returns></returns> + public static bool BoxVsBox(Vector4 b1, Vector4 b2, out Vector2 intersection) + { + float b1w = b1.z / 2f, b1h = b1.w / 2f, b2w = b2.z / 2f, b2h = b2.w / 2f; + float distX = b2.x - b1.x; + float distY = b2.y - b1.y; + if(Mathf.Abs(distX) < b1w + b2w && Mathf.Abs(distY) < b1h +b2h) + { + intersection = new Vector2(); + intersection.x = Mathf.Sign(distX) * (b1w + b2w - Mathf.Abs(distX)); + intersection.y = Mathf.Sign(distY) * (b1h + b2h - Mathf.Abs(distY)); + return true; + } + intersection = Vector2.zero; + return false; + } + + public static bool BoxVsBox(Vector4 b1, Vector4 b2) + { + float b1w = b1.z / 2f, b1h = b1.w / 2f, b2w = b2.z / 2f, b2h = b2.w / 2f; + float distX = b2.x - b1.x; + float distY = b2.y - b1.y; + if (Mathf.Abs(distX) < b1w + b2w && Mathf.Abs(distY) < b1h + b2h) + { + return true; + } + return false; + } + + public static bool BoxVsCircle(Vector4 box, Vector2 pos, float radius) + { + Vector4 boxScaled = box; + boxScaled.z = box.z + radius * 2; + boxScaled.w = box.w + radius * 2; + if (!IsPointInsideBox(boxScaled, pos)) + return false; + Vector2 v = MathUtils.Abs(pos - box.xy()); + Vector2 u = MathUtils.Max(v - box.zw(), 0); + return Vector2.Dot(u, u) < radius * radius; + } + + public static bool RayVsCircle(Vector4 ray, Vector3 circle) + { + Vector4 seg = GetRaySegment(ray); + Vector2 dir = ray.zw().normalized; + Vector2 center = circle.xy(); + float u = Vector2.Dot(center - seg.xy(), dir); + Vector2 near = new Vector2(); + if(u <= 0) + { + near = seg.xy(); + } + else if(u >= ray.zw().magnitude) + { + near = seg.zw(); + } + else + { + near = seg.xy() + dir * u; + } + return (near - center).sqrMagnitude <= circle.z * circle.z; + } + + + // From Real-time Collision Detection, p179 + // box2d + public static bool RayVsBox(Vector4 ray, Vector4 box) + { + float tmin = float.MinValue; + float tmax = float.MaxValue; + Vector2 dir = ray.zw().normalized; + Vector4 range = GetBoxRange(box); //lowerx,higherx,lowery,highery + Vector2 lowerBound = new Vector2(range.x, range.z); + Vector2 upperBound = new Vector2(range.y, range.w); + //Vector2 normal = new Vector2(); + Vector2 p = ray.xy(); + + for (int i = 0; i < 2; ++i) + { + + if (dir[i] < float.Epsilon) // 和x-slab平行 + { + if (p[i] < lowerBound[i] || p[i] > upperBound[i]) + { + return false; + } + } + else + { + float inv_d = 1f / dir[i]; + float t1 = (lowerBound[i] - p[i]) * inv_d; + float t2 = (upperBound[i] - p[i]) * inv_d; + float s = -1f; + if (t1 > t2) + { + MathUtils.Swap(ref t1, ref t2); + s = 1f; + } + if (t1 > tmin) + { + //normal = Vector2.zero; + //normal[i] = s; + tmin = t1; + } + + tmax = Mathf.Min(tmax, t2); + + if (tmin > tmax) + { + return false; + } + } + } + + // Does the ray start inside the box? + // Does the ray intersect beyond the max fraction? + if (tmin < 0 || ray.zw().magnitude < tmin) + { + if (IsPointInsideBox(box, p)) + return true; + return false; + } + //// Intersection. + //output->fraction = tmin; + //output->normal = normal; + + return true; + } + + /// <summary> + /// box x,y,w,h circle x,y,raduis + /// </summary> + /// <param name="box"></param> + /// <param name="circle"></param> + /// <returns></returns> + public static bool BoxVsCircle(Vector4 box, Vector3 circle) + { + return BoxVsCircle(box, circle.xy(), circle.z); + } + + public static bool IsPointInsideBox(Vector4 box, Vector2 point) + { + return point.x >= box.x - box.z / 2f + && point.x <= box.x + box.z / 2f + && point.y >= box.y - box.w / 2f + && point.y <= box.y + box.w / 2f; + } + +} |