diff --git a/collision.go b/collision.go new file mode 100644 index 0000000..eb914da --- /dev/null +++ b/collision.go @@ -0,0 +1,72 @@ +package govector + +func Intersection(p1, p2 Point2d, v1, v2 Vector2d) (bool, Point2d) { + t := p2.Sub(p1).Cross(v2) / v1.Cross(v2) + s := p2.Sub(p1).Cross(v1) / v1.Cross(v2) + if t > 0 && t < 1 && s > 0 && s < 1 { + return true, p1.Add(v1.Scale(t)) + } + + return false, Point2d{0, 0} +} + +func RectRectIntersection(r1 AABB2d, r2 AABB2d) bool { + return (r1.A.X < r2.B.X && r1.B.X > r2.A.X && + r1.A.Y < r2.B.Y && r1.B.Y > r2.A.Y) +} + +func RectIntersection(r AABB2d, p Point2d, v Vector2d) (bool, bool, Point2d) { + collision := false + inside := false + start_inside := PointInRect(p, r) + end_inside := PointInRect(p.Add(v), r) + if start_inside && end_inside { + inside = true + return collision, inside, p + } else { + wall_left, col1 := Intersection(p, r.A, v, Vector2d{X: 0, Y: r.B.Y - r.A.Y}) + if wall_left { + return wall_left, inside, col1 + } + wall_top, col2 := Intersection(p, r.A, v, Vector2d{X: r.B.X - r.A.X, Y: 0}) + if wall_top { + return wall_top, inside, col2 + } + wall_right, col3 := Intersection(p, r.B, v, Vector2d{X: 0, Y: -r.B.Y + r.A.Y}) + if wall_right { + return wall_right, inside, col3 + } + wall_bottom, col4 := Intersection(p, r.B, v, Vector2d{X: -r.B.X + r.A.X, Y: 0}) + if wall_bottom { + return wall_bottom, inside, col4 + } + + return false, false, p + } +} + +func ProjectPolygon(axis Vector2d, p Polygon2d) (min float32, max float32) { + min = axis.Dot(p.Points[0]) + max = min + for _, point := range p.Points { + d := axis.Dot(point) + if d < min { + min = d + } else { + if d > max { + max = d + } + } + } + return min, max +} + +func PolygonIntersection(r Polygon2d, p Point2d, v Vector2d) (bool, bool, Point2d) { + // TBD + return false, false, Point2d{} +} + +func PolyPolyIntersection(p1 Polygon2d, v1 Vector2d, p2 Polygon2d, v2 Vector2d) bool { + + return false +} diff --git a/govector_test.go b/govector_test.go index 8d4e38c..73ef614 100644 --- a/govector_test.go +++ b/govector_test.go @@ -182,7 +182,7 @@ func TestPtInRect(t *testing.T) { pA := Point2d{5, 5} pB := Point2d{15, 15} - r := Rect2d{ + r := AABB2d{ A: pA, B: pB, } @@ -212,7 +212,7 @@ func TestRectIntersect(t *testing.T) { pA := Point2d{5, 5} pB := Point2d{15, 15} - r := Rect2d{ + r := AABB2d{ A: pA, B: pB, } diff --git a/vectorpoint.go b/vectorpoint.go index f9a45f0..e559d15 100644 --- a/vectorpoint.go +++ b/vectorpoint.go @@ -4,11 +4,17 @@ import ( "math" ) -type Rect2d struct { +type AABB2d struct { A Point2d `json:A` B Point2d `json:B` } +type Polygon2d struct { + Points []Vector2d `json:"points"` + Normals []Vector2d `json:"normals"` + Origin Point2d `json:"origin"` +} + type Vector2d struct { X float32 `json:"x"` Y float32 `json:"y"` @@ -57,54 +63,19 @@ func (v1 Vector2d) Rotate(a float32) Vector2d { return Vector2d{float32(x), float32(y)} } -func Intersection(p1, p2 Point2d, v1, v2 Vector2d) (bool, Point2d) { - t := p2.Sub(p1).Cross(v2) / v1.Cross(v2) - s := p2.Sub(p1).Cross(v1) / v1.Cross(v2) - if t >= 0 && t <= 1 && s >= 0 && s <= 1 { - return true, p1.Add(v1.Scale(t)) - } - - return false, Point2d{0, 0} -} - -func PointInRect(p Point2d, r Rect2d) bool { +func PointInRect(p Point2d, r AABB2d) bool { return (p.X > r.A.X) && (p.X < r.B.X) && (p.Y > r.A.Y) && (p.Y < r.B.Y) } -func RectFromPoint(p Point2d, size float32) Rect2d { - return Rect2d{ +func RectFromPoint(p Point2d, size float32) AABB2d { + return AABB2d{ A: Point2d{X: p.X - size, Y: p.Y - size}, B: Point2d{X: p.X + size, Y: p.Y + size}} } -func RectIntersection(r Rect2d, p Point2d, v Vector2d) (bool, bool, Point2d) { - collision := false - inside := false - start_inside := PointInRect(p, r) - end_inside := PointInRect(p.Add(v), r) - if start_inside && end_inside { - inside = true - return collision, inside, Point2d{X: 0, Y: 0} - } else { - wall_left, col1 := Intersection(p, r.A, v, Vector2d{X: 0, Y: r.B.Y - r.A.Y}) - if wall_left { - return wall_left, inside, col1 - } - wall_top, col2 := Intersection(p, r.A, v, Vector2d{X: r.B.X - r.A.X, Y: 0}) - if wall_top { - return wall_top, inside, col2 - } - wall_right, col3 := Intersection(p, r.B, v, Vector2d{X: 0, Y: -r.B.Y + r.A.Y}) - if wall_right { - return wall_right, inside, col3 - } - wall_bottom, col4 := Intersection(p, r.B, v, Vector2d{X: -r.B.X + r.A.X, Y: 0}) - if wall_bottom { - return wall_bottom, inside, col4 - } - - return false, false, Point2d{X: 0, Y: 0} - } +func PolygonFromAABB(r AABB2d) Polygon2d { + // TBD + return Polygon2d{} } func (v Vector2d) Normalize() Vector2d {