Skip to content

Commit

Permalink
Implement circle projection and fix circle mtv.
Browse files Browse the repository at this point in the history
  • Loading branch information
d3rped committed Sep 3, 2024
1 parent d608c38 commit 480f1b2
Showing 1 changed file with 44 additions and 4 deletions.
48 changes: 44 additions & 4 deletions shape.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,13 +679,38 @@ func (cp *ConvexPolygon) calculateMTV(contactSet *ContactSet, otherShape IShape)
case *Circle:

verts := append([]Vector{}, cp.Transformed()...)
// The center point of a contact could also be closer than the verts, particularly if we're testing from a Circle to another Shape.
verts = append(verts, contactSet.Center)
center := other.position
sort.Slice(verts, func(i, j int) bool { return verts[i].Sub(center).Magnitude() < verts[j].Sub(center).Magnitude() })

smallest = Vector{center.X - verts[0].X, center.Y - verts[0].Y}
smallest = smallest.Unit().Scale(smallest.Magnitude() - other.radius)
axis := Vector{center.X - verts[0].X, center.Y - verts[0].Y}
pa := cp.Project(axis)
pb := other.Project(axis)
overlap := pa.Overlap(pb)
if overlap <= 0 {
return Vector{}, false
}
smallest = axis.Unit().Scale(overlap)

for _, axis := range cp.SATAxes() {
pa := cp.Project(axis)
pb := other.Project(axis)

overlap := pa.Overlap(pb)

if overlap <= 0 {
return Vector{}, false
}

if smallest.Magnitude() > overlap {
smallest = axis.Scale(overlap)
}

}

// If the direction from target to source points opposite to the separation, invert the separation vector
if cp.Center().Sub(other.position).Dot(smallest) < 0 {
smallest = smallest.Invert()
}

}

Expand Down Expand Up @@ -835,6 +860,21 @@ func (circle *Circle) Bounds() (Vector, Vector) {
return Vector{circle.position.X - circle.radius, circle.position.Y - circle.radius}, Vector{circle.position.X + circle.radius, circle.position.Y + circle.radius}
}

func (circle *Circle) Project(axis Vector) Projection {
axis = axis.Unit()
projectedCenter := axis.Dot(circle.position)
projectedRadius := axis.Magnitude() * circle.radius * circle.scale

min := projectedCenter - projectedRadius
max := projectedCenter + projectedRadius

if min > max {
min, max = max, min
}

return Projection{min, max}
}

// Intersection tests to see if a Circle intersects with the other given Shape. dx and dy are delta movement variables indicating
// movement to be applied before the intersection check (thereby allowing you to see if a Shape would collide with another if it
// were in a different relative location). If an Intersection is found, a ContactSet will be returned, giving information regarding
Expand Down

0 comments on commit 480f1b2

Please sign in to comment.