-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbox_circle_overlap.go
More file actions
71 lines (60 loc) · 1.66 KB
/
box_circle_overlap.go
File metadata and controls
71 lines (60 loc) · 1.66 KB
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
package coll
import (
"math"
"github.com/setanarut/v"
)
// BoxCircleOverlap checks whether box and circle overlap.
//
// If h is not nil, the function fills it with:
// - Normal: the surface normal of box
// - Data: penetration depth (distance to move the box)
//
// To resolve the overlap:
//
// newBoxPos = box.Pos.Add(hit.Normal.Neg().Scale(hit.Data))
func BoxCircleOverlap(a *AABB, c *Circle, h *Hit) bool {
// intersection test
diff := c.Pos.Sub(a.Pos)
clamped := v.Vec{
X: max(-a.Half.X, min(diff.X, a.Half.X)),
Y: max(-a.Half.Y, min(diff.Y, a.Half.Y)),
}
closest := a.Pos.Add(clamped)
if !(c.Pos.DistSq(closest) <= c.Radius*c.Radius) {
return false
}
if h == nil {
return true
}
inside := diff.Equals(clamped)
if !inside {
// Box is outside circle - push along the line from closest point to circle center
normal := diff.Sub(clamped)
distSq := normal.MagSq()
dist := math.Sqrt(distSq)
// Normalize the normal vector (direction to push box)
h.Normal = normal.DivS(dist) // Box pushed away from circle
// Penetration depth (how far to move)
penetration := c.Radius - dist
h.Data = penetration
} else {
// Box center is inside circle - push along shortest axis
absD := diff.Abs()
px := a.Half.X - absD.X
py := a.Half.Y - absD.Y
if px < py {
// Push horizontally
sx := math.Copysign(1, diff.X)
pushDistance := px + c.Radius
h.Normal = v.Vec{X: sx, Y: 0} // Box pushed away from circle
h.Data = pushDistance
} else {
// Push vertically
sy := math.Copysign(1, diff.Y)
pushDistance := py + c.Radius
h.Normal = v.Vec{X: 0, Y: sy} // Box pushed away from circle
h.Data = pushDistance
}
}
return true
}