pzach
pzach

Reputation: 153

Improper SpriteBatch Rotation

I'm trying to get a rotated Texture2D to properly fit within/fill the bounds of a rotated Polygon (my own class), but it refuses to work properly. The SpriteBatch method I am using is:

spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, Vector2.Zero, SpriteEffects.None, 1.0f);

However, the only important bits in this are the Rectangle and the origin, which is currently set to Vector2.Zero. When the above is run, it produces this image, where the Texture2D (a filled red square) is offset from the Polygon (the lime wireframe) by a value of (texture.Width / 2, texture.Height / 2). However, the rotation is correct, since both shapes have parallel sides.

I have tried:

spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, new Vector2(Width / 2, Height / 2), SpriteEffects.None, 1.0f);

The only difference in this call is that I changed the origin (the point around which the Texture2D should be rotated) to new Vector2(Width / 2, Height / 2), which results in this image, where the Texture2D is offset from the Polygon by a value of (-Width, -Height), but it still rotates with the Polygon.

Another error that occurs is that when using a different Texture2D with a different width and height from the first-- although it should produce the same result since the destinationRectangle field does not change-- it is different in the program, as shown in this image. Again, this uses the exact same call as the previous, just with a different image (with different dimensions).

Any help on either of these issues would be greatly appreciated. Thanks!

Upvotes: 0

Views: 386

Answers (3)

pzach
pzach

Reputation: 153

The answer to both of my problems lies in one mistake:

SpriteBatch applies the rotation around the origin before applying scale translation.

To explain this, here's an example:

You have a Texture2D of size (16, 16), and want it to fill a (48, 48) size destinationRectangle while rotating around origin point (destinationRectangle.Width / 2, destinationRectangle.Height / 2) (which is equal to (24, 24)). So, you want to end up with a square rotated around its center point.

First, SpriteBatch will rotate the Texture2D around point (24, 24), which, because the Texture2D has not yet been scaled and therefore is of size (16, 16), will result in an improper and unexpected result. After this, it will be scaled, making it just a larger version of the poorly rotated square.

To remedy this problem, use (texture.Width / 2, texture.Height / 2) instead of (destinationRectangle.Width / 2, destinationRectangle.Height / 2) as the origin point.

Example:spriteBatch.Draw(texture, new Rectangle((int)Position.X, (int)Position.Y, Width, Height), null, color, Rotation, new Vector2(texture.Width / 2, texture.Height / 2), SpriteEffects.None, 0f);

Further explanation can be found here and here.

Upvotes: 0

user10316640
user10316640

Reputation:

The origin adjusts the center of the rotation based on the source rectangle. (When passed as null as in your case, the source rectangle is the entire Texture.

Remember that order is important when it comes to Translation, Rotation, and Scale.

The rotation is applied at the translated origin of the source rectangle, allowing the rotation of individual frames of a sprite sheet.

The following code should produce the expected output:

spriteBatch.Draw(texture, new Rectangle((int)Position.Center.X, (int)Position.Center.Y, Width, Height), null, color, Rotation, new Vector2(texture.Width / 2, texture.Height / 2), SpriteEffects.None, 1.0f);

Upvotes: 0

aybe
aybe

Reputation: 16662

http://www.monogame.net/documentation/?page=M_Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw

For proper rotation you need to make sure origin is correct,

Either it'd be 0.5f, 0.5f if it's a normalized value, else it'd be width / 2.0f, height / 2.0f.

Or any other appropriate corner to rotate around in your case.

Upvotes: 0

Related Questions