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? |