Reputation: 153
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
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
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
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