Question about pixel-perfect collision detection using matrix transforms

I’ve read a lot of tutorials and looked through sample code on how to do pixel-perfect collision with rotated, scaled, moved 2D sprites. I have the code fully working in my game engine, but I found that mine works differently than the tutorials. In the tutorials, this is the recommended way to do the matrix transform:

transform = Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
                        Matrix.CreateScale(Scale) *
                        Matrix.CreateRotationZ(Rotation) *
                        Matrix.CreateTranslation(new Vector3(Position, 0.0f));

However, this does not work in my game. I have to do this:

transform = Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
                        Matrix.CreateScale(Scale) *
                        Matrix.CreateRotationZ(Rotation) *
                        Matrix.CreateTranslation(new Vector3(Origin, 0.0f)) *
                        Matrix.CreateTranslation(new Vector3(Position, 0.0f));

Note the extra CreateTranslation with positive Origin. To me, this makes sense - I translate the sprite such that the rotation origin is at the center of the world (0, 0, 0) since we can’t provide an origin in CreateRotationZ, then I rotate the sprite, then I translate it back to where it was before.

Does the recommended method actually work (the first one that I’m not using)? Or is it bugged? It looks like it translates the matrix to the Origin but never translates it back. I don’t see how that could ever work, but yet this is the method stated in multiple tutorials and videos. I’m worried that although my code works for my current game, I’ve done something wrong somewhere that will bite me later. Thoughts/opinions?

This is because in most systems, the rotation origin of the sprite is also seen as the point that position is set relative to. What you’re doing is using the position as the position of the top-left corner of the sprite’s pre-orientation box, and using the origin solely as the center of the rotation.

It’s just a choice you make to use center vs top-left coordinates, and most people just go with center coordinates for position when rotation comes into play, since the AABB hitbox of the sprite when rotated won’t be positioned at that top-left coordinate anyway.

1 Like