A plot twist – or, that thing with muhammad and the mountain.

My faithful readers – that is, those who have read my one previous post – will remember how I showed that a surface can be first rotated, then stretched and then correctly positioned by doing a few vector operations..
Well, I was lying.
The thing is, while mathematically the idea is perfectly sound, in practice there is a problem.
Well, two.

Problem one: we’d be doing that with integers.
This means that a. we have single pixel accuracy (which, at best, would mean nearest neighbour) b. we have rounding errors building up.
We need subpixel accuracy for this.

Problem two: I mentioned a magic rotating function that would rotate sprites for me.
Well, we do have one, and it’s called SDL_rotozoom.cpp.
It only has one teensy-weensy problem.
It is not as precise as we’d want when it comes to the bounding box around the rotated sprite.
Basically, what you’d normally expect is this: a different corner of the original sprite ‘pushing’ the edges and causing the resulting sprite to be larger.
Look at this drawing I made for my reference and posted behind my monitor (I can never remember for which range I must use which corner):

This (possibly suboptimal but working) code would give you the exact amount of offset thus produced:

https://github.com/tobiatesan/scummvm/blob/d98529c5aa108488399d41ce7125dc1b421c6a14/engines/wintermute/graphics/transform_tools.cpp

Now, look at this instead:

See that?
Yep.
There is a 1px offset on top and a 2x offset pushing the sprite right.

Those are probably due to rounding errors and various stuff going on in the fixed point calculations done in SDL_rotozoom.cpp (home to the magic function I’ve been talking about till now).
It is exceedingly difficult to compensate for those errors on a case by case basis, to the point that, I realized, the code is practically useless, only good for really low-end devices which benefit from some rather lightweight code.

Could I be completely wrong?

Possibly. I often am.
At the suggestion of my mentor I looked into how the same feature is done in WME:Lite.
Turns out they use SDL to do it – they specify the hotspot and the positioning, and SDL draws “around” the hotspot using fixed point and possibly hardware rendering.

We can’t afford this luxury, though; the code being as it is, we cannot draw “around” the origin.
All pixels for a sprite must be below and right of the origin.

What I’m gonna attempt next will thus be:

1. Calculate the boundaries of the box first and place it firmly where it will end up in the end.
2. In a single pass do an (interpolating?) transform.

This should save me from all the issues above.

Stay tune, more to come.