Thursday, November 7, 2019

collision detection - Bounding box of a rotated rectangle (2d)


I can see this has been asked before in various ways. I am struggling to work it out though hence asking again.


2d sprite that moves and rotates. I'm looking to contain it in a bounding box as it appears that is the most efficient way to do collision detection.



I had no problems getting it to work without rotation but that is simple! Now the sprite rotates I can't seem to find the right way of writing the code.


To create a bounding box for the sprite, my understanding is I need to work out the 4 corners of the sprite after rotation and use these to work out the width + height of the correctly sized bounding box.


I've used the article here - http://msdn.microsoft.com/en-us/library/dd162943(v=vs.85).aspx - specifically the formula:


x' = (x * cos A) - (y * sin A) 
y' = (x * sin A) + (y * cos A)

The code I'm currently using:


x1 = (positionX * Math.cos(rotation)) - (positionY * Math.sin(rotation));
y1 = (positionX * Math.sin(rotation)) + (positionY * Math.cos(rotation));


x2 = (positionX+width/2 * Math.cos(rotation)) - (positionY+height/2 * Math.sin(rotation));
y2 = (positionX+width/2 * Math.sin(rotation)) + (positionY+height/2 * Math.cos(rotation));

positionX and positionY is the current top left hand corner position of the sprite.


rotation is the radians the sprite has been rotated by (and rotation is from the centre).


width and height are of the sprite.


I thought the code above would give me the co-ordinates of the top left and top right corners of the rectangle, rotated appropriately. However, on my canvas, I'm drawing a line from x1,y1 to x2,y2 and it doesn't follow the sprite at all!


Any suggestions? Sorry for the long post!


Cheers!



Answer




I always try to solve these geometrical problems using transformations instead of trigonometry, because at least for me it's easier to visualize. Here's how I do it on my application in XNA.


Let's say I have a sprite that's been translated, rotated and scaled arbitrarily and I want to fit an AABB to it. I only need to know two things about this sprite:



  • The world matrix containing all three transformations combined

  • The sprite's untransformed extents (i.e. it's original width and height)


(BTW, these two bits of information combined are also all you need in order to represent an OBB)


Knowing that, I proceed to calculate an AABB like this:


// Calculate the position of the four corners in world space by applying
// The world matrix to the four corners in object space (0, 0, width, height)

Vector2 tl = Vector2.Transform(Vector2.Zero, matrix);
Vector2 tr = Vector2.Transform(new Vector2(extents.x, 0), matrix);
Vector2 bl = Vector2.Transform(new Vector2(0, extents.y), matrix);
Vector2 br = Vector2.Transform(extents, matrix);

// Find the minimum and maximum "corners" based on the ones above
float minX = Min(tl.X, Min(tr.X, Min(bl.X, br.X)));
float maxX = Max(tl.X, Max(tr.X, Max(bl.X, br.X)));
float minY = Min(tl.Y, Min(tr.Y, Min(bl.Y, br.Y)));
float maxY = Max(tl.Y, Max(tr.Y, Max(bl.Y, br.Y)));

Vector2 min = new Vector2(minX, minY);
Vector2 max = new Vector2(maxX, maxY);

// And create the AABB
RectangleF aabb = new RectangleF(min, max - min);

Maybe it's longer but at least I understand every step of the process this way.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...