11

Say I have a sprite. Its axis-aligned bounding box (AABB) is easy to find since I know the width and height. Say I rotate it 45 degrees, I don't think the AABB would be big enough to cover it, so I need a new AABB. How can I calculate the bounding rectangle of a rotated rectangle? (given a center point, an angle, and its width and height).

Note that OpenGL does the rotation so I do not have access to the vertex information.

What I'm trying to do is get AABBs so I can do 2D culling for rendering.

Is there possibly a greedy way of finding the AABB that satisfies any angle?

Thanks

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
jmasterx
  • 52,639
  • 96
  • 311
  • 557

3 Answers3

36

enter image description here

Gareth Rees
  • 64,967
  • 9
  • 133
  • 163
  • If you go this route, make sure to remember the original AABB and the current rotation angle, because otherwise as you apply more and more rotations the corrected box will get bigger and bigger (making it less useful). The other idea in your post (finding an AABB that works for all angles) is easy enough too (see my answer). – Sumudu Fernando Jul 19 '11 at 16:51
  • 1
    note that the rotated AABB will not be an optimal bound in general unless the sprite is itself a rectangle; i mean, your AABB will be strictly speaking a "bounding box" (i.e: it is guaranteed to be inside) but there might be a smaller rotated AABB that fits the sprite. (for instance, if there sprite does not have points near the corners of the AABB) – lurscher Jul 19 '11 at 17:04
  • Also make note of whether your language expects theta in radians or degrees for sin / cos. (I lost a good two days translating this into Python because of that.) – Hammer Bro. Nov 14 '13 at 22:55
  • 2
    Make sure to take the abs of the trig functions, otherwise you could get degenerate sizes. – Beefster Nov 23 '19 at 18:13
1

If you want a single box that covers all angles, just take the half-diagonal of your existing box as the radius of a circle. The new box has to contain this circle, so it should be a square with side-length equal to twice the radius (equiv. the diagonal of the original AABB) and with the same center as the original.

In general the object will be rotated around an arbitrary point, so you have to compute the new location of the center and translate this box to the right place.

Sumudu Fernando
  • 1,763
  • 2
  • 11
  • 17
0

I don't know if this is the most efficient method, but I would just calculate the new positions of the vertices and based on that data find out the AABB. So for example,

Vertex v0, v1, v2, v3;
// in the local coordinates of the rectangle
// so for example v0 is always 0,0 and width and height define the others
// put some values to v0..v3

glLoadIdentity();
glTranslatef(the position of the rectangle);
glTranslatef(center_point);
glRotatef(angle, 0,0,1);
glTranslatef(-center_point);

GLfloat matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);

v0 = multiply_matrix_by_vector(matrix, v0);
v1 = multiply_matrix_by_vector(matrix, v1);
v2 = multiply_matrix_by_vector(matrix, v2);
v3 = multiply_matrix_by_vector(matrix, v3);

AABB = find_the_minimums_and_maximums(v0, v1, v2, v3);

If you don't know how to multiply a matrix by vector, try googling it.

Also note that since the matrix dimensions are 4x4, the vectors for the vertices also need to be 4-dimensional. You can convert a 2D vector to a 4D vector by adding a third component 0 (zero) and a fourth component 1 (one). After the multiplication has been done, you can convert the resulting 4D vector back to 2D by dividing the x and y components by the fourth component and simply by ignoring the third component because you don't need a third dimension.

Since matrix multiplications might be a quite processor-heavy operation, this approach might be good only, if you don't need to update a lot of AABBs very often.

kynnysmatto
  • 3,665
  • 23
  • 29
  • 1
    OpenGL has `glMultMatrix`, so you might as well use that. – Gareth Rees Jul 11 '11 at 23:20
  • yes. except that glMultMatrix probably does some extra work because it multiplies matrices by matrices instead of matrices by vectors. but that's probably ok since this method is probably slow anyway. – kynnysmatto Jul 11 '11 at 23:26
  • You're multiplying four vectors by the same 4×4 matrix, so you could do them all at once... – Gareth Rees Jul 11 '11 at 23:39