Vote for a change in SpriteBatch behaviour!

So, i’m currently working on a very small module that will allow me to do screen resolution independent animation of sprites and texts. I will use it to bootstrap all my UI work as i don’t have any fancy requirements (yet). In the process of designing the module i came to the conclusion that SpriteBatch’s current behaviour is a bit inconsistent. Let me explain.

SpriteBatch usually works in a cartesian pixel coordinate system that spans the whole screen with origin in the bottom left of the screen, the positive x-axis pointing to the right and the positive y-axis pointing upwards. This deviates from the coordinate systems you usually find in other libraries that allow 2D rendering. These usually have the y-axis point upwards. Being used to OpenGL so much i prefer libgdx way (hint you can change the behaviour by supplying your own projection or transformation matrix).

SpriteBatch has a couple of draw() methods to render a rectangular sprite to the screen. Let’s ignore the texture related parameters of this methods and focus on the other properties of the sprite, namely it’s position, origin, width, height, scale in x and y and rotation angle. We can also ignore the scale and rotation angle of a sprite for this discussion. Just let us remember that they are applied with respect to the origin of the sprite (it scales and rotates around it’s origin in this order). Here’s a picture illustrating a simple scenario of an unscaled, non-rotated sprite.

So, the position of a sprite is given relative to the coordinate system’s origin. The origin of the sprite is given relative to the top left corner of the sprite which is always co-incident with the sprites position. And that is the problem. Why on hell is the position of a sprite co-incident with the top left corner instead of the bottom left corner? This makes for some awkwardness when trying to create hierarchies of sprites, say in a simple scene graph.

In any case, the behaviour is extremely inconsistent. The same is true for the drawText() method. I therefore want to change the semantics of the position attribute of a Sprite to mean its lower left corner when rotation and scaling are not applied. What do you think? I added a poll to the sidebar on the right. Please vote! The poll is closed, thanks!

3 thoughts on “Vote for a change in SpriteBatch behaviour!

  1. Hm, with a 2×2 matrix plus a translation vektor you can not specify a different origin (or pivot as it is usually called). You need a 3×3 matrix for that so you can concatenate the operations:

    translate(-originX, -originY)
    scale(scaleX, scaleY )
    rotate( angle )
    translate(originX, originY)
    translate(posX, posY)

    If you do the above with a 3×3 matrix all is well. With a 2×2 matrix you are more or less borked as you can only specify rotation and scale.

    I just implemented a 3×3 matrix for that exact use case. However, SpriteBatch does the same operations but without matrix multiplications which is significantly faster. I also think that it’s harder to understand for most people out there (and i don’t blame them).

    Hm, now i’m torn. I’ll think about it. Thanks for the input!

  2. Just looked over SpriteBatch again. There’s a few methods which are specialized to ignore rotation and scale to speed up the mesh construction, e.g. SpriteBatch.draw( Texture, x, y, width, height, srcX, srcY, srcWidth, srcHeight).

    If i change or rather remove those and replace them with a Matrix3 version i’d have a lot of computational overhead in the case that a user wants to draw a non-rotated, non-scaled sprite.

    Also, the full blown rotate/scale/translate draw() method has 50% less multiplications than an equivalent Matrix version

    Would you agree that those are valid reasons to not go the matrix route?

Leave a Reply

Your email address will not be published.