Check for collision between two rotated rectangles
Monkey Forums/Monkey Code/Check for collision between two rotated rectangles
| ||
| Hi all, here comes a piece of code to perform a collision check between two rotated rectangles:
Strict
Class Vector2D
Field x:Float
Field y:Float
End Class
Class RotRect
Field C:Vector2D
Field S:Vector2D
Field ang:Float
End Class
Function AddVectors2D:Void( v1:Vector2D, v2:Vector2D )
v1.x += v2.x
v1.y += v2.y
End Function
Function SubVectors2D:Void( v1:Vector2D, v2:Vector2D )
v1.x -= v2.x
v1.y -= v2.y
End Function
Function RotateVector2DClockwise:Void( v:Vector2D, ang:Float )
Local t:Float
Local cosa:Float = Cos( ang )
Local sina:Float = Sin( ang )
t = v.x
v.x = t * cosa + v.y * sina
v.y = -t * sina + v.y * cosa
End Function
' Rotated Rectangles Collision Detection, Oren Becker, 2001
Function RotRectsCollision:Bool( rr1:RotRect, rr2:RotRect )
Local A:Vector2D
Local B:Vector2D ' vertices of the rotated rr2
Local C:Vector2D ' center of rr2
Local BL:Vector2D
Local TR:Vector2D ' vertices of rr2 (bottom-left, top-right)
Local ang:Float = rr1.ang - rr2.ang ' orientation of rotated rr1
Local cosa:Float = Cos( ang ) ' precalculated trigonometic -
Local sina:Float = Sin( ang ) ' - values for repeated use
Local t:Float, x:Float, a:Float ' temporary variables for various uses
Local dx:Float ' deltaX for linear equations
Local ext1:Float, ext2:Float ' min/max vertical values
' move rr2 to make rr1 cannonic
C = rr2.C
SubVectors2D( C, rr1.C )
' rotate rr2 clockwise by rr2->ang to make rr2 axis-aligned
RotateVector2DClockwise( C, rr2.ang )
' calculate vertices of (moved and axis-aligned := 'ma') rr2
BL = TR = C
SubVectors2D( BL, rr2.S )
AddVectors2D( TR, rr2.S )
' calculate vertices of (rotated := 'r') rr1
A.x = -rr1.S.y * sina
B.x = A.x
t = rr1.S.x * cosa
A.x += t
B.x -= t
A.y = rr1.S.y * cosa
B.y = A.y
t = rr1.S.x * sina
A.y += t
B.y -= t
t = sina * cosa;
' verify that A is vertical min/max, B is horizontal min/max
If( t < 0.0 )
t = A.x
A.x = B.x
B.x = t
t = A.y
A.y = B.y
B.y = t
End If
' verify that B is horizontal minimum (leftest-vertex)
If( sina < 0.0 )
B.x = -B.x
B.y = -B.y
End If
' if rr2(ma) isn't in the horizontal range of
' colliding with rr1(r), collision is impossible
If( B.x > TR.x Or B.x > -BL.x ) Then Return False
' if rr1(r) is axis-aligned, vertical min/max are easy to get
If( t = 0 )
ext1 = A.y
ext2 = -ext1
' else, find vertical min/max in the range [BL.x, TR.x]
Else
x = BL.x - A.x
a = TR.x - A.x
ext1 = A.y
' if the first vertical min/max isn't in (BL.x, TR.x), then
' find the vertical min/max on BL.x or on TR.x
If( a * x > 0.0 )
dx = A.x
If( x < 0.0 )
dx -= B.x
ext1 -= B.y
x = a
Else
dx += B.x
ext1 += B.y
End If
ext1 *= x
ext1 /= dx
ext1 += A.y
End If
x = BL.x + A.x
a = TR.x + A.x
ext2 = -A.y
' if the second vertical min/max isn't in (BL.x, TR.x), then
' find the local vertical min/max on BL.x or on TR.x
If( a * x > 0.0 )
dx = -A.x
If( x < 0.0 )
dx -= B.x
ext2 -= B.y
x = a
Else
dx += B.x
ext2 += B.y
End If
ext2 *= x
ext2 /= dx
ext2 -= A.y
End If
End If
' check whether rr2(ma) is in the vertical range of colliding with rr1(r)
' (for the horizontal range of rr2)
Return Not ( ( ext1 < BL.y And ext2 < BL.y ) Or ( ext1 > TR.y And ext2 > TR.y ) )
End Function
|
| ||
| Hi Xaron, Thanks - this is exactly what I'm looking for.. but being stupid, I can't get it to work. Presumably the way to use it is simply to call the RotRectsCollision function? I'm getting a compilation error "Cannot convert from bool to Vector2D" at the part of the code which reads: ' calculate vertices of (moved and axis-aligned := 'ma') rr2 BL = TR = C But I'm probably doing something stupid. Any chance of an example code snippit which calls the RotRectsCollision function? |