using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 碰撞检测
///
public partial class PhysicsManager : Singleton
{
///
/// circle x,y,radius
///
///
///
///
///
///
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;
}
///
/// intersection是r2对于r1
///
///
///
///
///
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;
}
///
/// box x,y,w,h circle x,y,raduis
///
///
///
///
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;
}
}