Reputation: 13
I am not well versed in matrix math so any help would be appreciated. So I have a simple ship sprite that rotates and moves. In order to calculate the bounding rectangle I tried using a rotation matrix and the code I got off of these tutorials:
http://xbox.create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel
But whenever the sprite rotates it's X and Y position of the bounding rectangle change drastically, by like 100s of pixels. The method for calculating the new bounding rectangle is as follows:
public static Rectangle CalculateBoundingRectangle(Rectangle rectangle, Matrix transform)
{
// Get all four corners in local space
Vector2 leftTop = new Vector2(rectangle.Left, rectangle.Top);
Vector2 rightTop = new Vector2(rectangle.Right, rectangle.Top);
Vector2 leftBottom = new Vector2(rectangle.Left, rectangle.Bottom);
Vector2 rightBottom = new Vector2(rectangle.Right, rectangle.Bottom);
// Transform all four corners into work space
Vector2.Transform(ref leftTop, ref transform, out leftTop);
Vector2.Transform(ref rightTop, ref transform, out rightTop);
Vector2.Transform(ref leftBottom, ref transform, out leftBottom);
Vector2.Transform(ref rightBottom, ref transform, out rightBottom);
// Find the minimum and maximum extents of the rectangle in world space
Vector2 min = Vector2.Min(Vector2.Min(leftTop, rightTop),
Vector2.Min(leftBottom, rightBottom));
Vector2 max = Vector2.Max(Vector2.Max(leftTop, rightTop),
Vector2.Max(leftBottom, rightBottom));
// Return as a rectangle
return new Rectangle((int)min.X, (int)min.Y,
(int)(max.X - min.X), (int)(max.Y - min.Y));
}
I am assuming this works since it comes from the Microsoft site and all. So I think the problem is with my matrices. I thought that If I only used a rotation matrix it would only spin the thing; not change its X and Y coordinates drastically. right now this is what I have:
// calculate transformation
Matrix transformation = Matrix.CreateRotationZ((float)rotation) * Matrix.CreateRotationZ((float)rotation);;
//update bounding rectangle
rectangle = new Rectangle((int)(position.X - origin.X), (int)(position.Y - origin.Y), texture.Width, texture.Height);
rectangle = BoundingAndCollision.CalculateBoundingRectangle(rectangle, transformation);
I tried a variety of other things including without the origin matrix and different orders of them. I also tried what a tutorial said was a general one that would work for anything, but that yielded the basically the same results:
Matrix transformation = Matrix.CreateTranslation(new Vector3(origin, 0.0f)) *
Matrix.CreateRotationZ((float)rotation) *
Matrix.CreateScale(scale) *
Matrix.CreateTranslation(position.X, position.Y, 0);
If that is not clear enough I can post screenshots, just let me know.Thank you in advance for the help!
Upvotes: 1
Views: 241
Reputation: 15151
A rotation matrix rotates around 0,0 and your rectangle is already placed in the world.
To solve first subtract the rectangle's center from each vertex (translate the rectangle to be centered at 0,0) and then add it again after rotating (place again on original location). In the code im assuming Y goes from top to bottom:
public static Rectangle CalculateBoundingRectangle(Rectangle rectangle, Matrix transform)
{
Vector2 center = new Vector2(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2);
// Get all four corners in local space
Vector2 leftTop = new Vector2(rectangle.Left, rectangle.Top) - center;
Vector2 rightTop = new Vector2(rectangle.Right, rectangle.Top) - center;
Vector2 leftBottom = new Vector2(rectangle.Left, rectangle.Bottom) - center;
Vector2 rightBottom = new Vector2(rectangle.Right, rectangle.Bottom) - center;
// Transform all four corners into work space
Vector2.Transform(ref leftTop, ref transform, out leftTop);
Vector2.Transform(ref rightTop, ref transform, out rightTop);
Vector2.Transform(ref leftBottom, ref transform, out leftBottom);
Vector2.Transform(ref rightBottom, ref transform, out rightBottom);
leftTop += center;
rightTop += center;
leftBottom += center;
rightBottom += center;
// Find the minimum and maximum extents of the rectangle in world space
Vector2 min = Vector2.Min(Vector2.Min(leftTop, rightTop),
Vector2.Min(leftBottom, rightBottom));
Vector2 max = Vector2.Max(Vector2.Max(leftTop, rightTop),
Vector2.Max(leftBottom, rightBottom));
// Return as a rectangle
return new Rectangle((int)min.X, (int)min.Y,
(int)(max.X - min.X), (int)(max.Y - min.Y));
}
Upvotes: 1