2
\$\begingroup\$

i am currently in the process of implementing a render engine that works like flash's. Where a sprite is drawn inside another sprite and reflects all transformation (rotation, scale, etc) on the parent.

I have my transformation setup like so.

    public Matrix transform
    {
        get
        {
            Matrix m_transform =
                Matrix.CreateTranslation(new Vector3(x, y, z)) *
                Matrix.CreateRotationZ(rotation) *
                Matrix.CreateScale(scale)
                ;
            return m_transform;
        }

    }

But i cannot use spritebatch to render the sprite with a matrix. Is there a way to properly do this ?

Thanks alot ;)

\$\endgroup\$
1
  • \$\begingroup\$ Besides what I wrote in my answer, you should invert the order of the transformations, which for a world matrix should be Scale-Rotation-Translation. Also if your scale is just a float value, you'll probably want to change the call to Matrix.CreateScale(scale, scale, 1) because you do not want the Z coordinate to be scaled or it might mess up the SpriteBatch sorting. And you probably should leave the Z component of the translation at 0 too. If you need to change the depth, use the layerDepth SpriteBatch.Draw() parameter. \$\endgroup\$ Aug 5, 2012 at 17:30

2 Answers 2

0
\$\begingroup\$

Use the following helper method which decomposes any Matrix into a set of position, rotation and scale that can be used directly with a SpriteBatch. It's basically a wrapper around the existing Matrix.Decompose method but making it SpriteBatch friendly:

public static void DecomposeMatrix(ref Matrix matrix, out Vector2 position, out float rotation, out Vector2 scale)
{
    Vector3 position3, scale3;
    Quaternion rotationQ;
    matrix.Decompose(out scale3, out rotationQ, out position3);
    Vector2 direction = Vector2.Transform(Vector2.UnitX, rotationQ);
    rotation = (float) Math.Atan2(direction.Y, direction.X);
    position = new Vector2(position3.X, position3.Y);
    scale = new Vector2(scale3.X, scale3.Y);
}

It should be pretty straightforward, but here's an example of how to use the method above:

Matrix transform = /* The transform of your sprite */

Vector2 position, scale;
float rotation;
DecomposeMatrix(ref transform, out position, out rotation, out scale);

spriteBatch.Draw(texture, position, null, Color.White, rotation, Vector2.Zero, scale, SpriteEffects.None, 0.0f);

Notice how the origin parameter is left as Vector2.Zero in the example. This is because I usually already embed the origin transformation into the matrix, so the resulting position already includes it.

For more information on the subject of implementing a sprite hierarchy in XNA, I will simply leave two links to related answers of mine:

\$\endgroup\$
0
\$\begingroup\$

Shawn Hargreaves write this Link article on his blog about it. Create BasicEffect instance, set transforms and draw:

spriteBatch.Begin(0, null, null, null, null, basicEffect);
//draw something
spriteBatch.End();
\$\endgroup\$
1
  • \$\begingroup\$ I think with this approach, you'd need to call Begin/End for each sprite in order to set a new transform, or use Immediate mode, both of which get rid of the benefits of batching. \$\endgroup\$ Aug 5, 2012 at 17:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .