Joseph Blank
Joseph Blank

Reputation: 13

Rotation Matrix causing sprite position to change

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

Answers (1)

Gusman
Gusman

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

Related Questions