1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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;
}
}
|