Transformation Order

I think I understand the problem now.

When you type A * B and both variables are instances of playdate.geometry.affineTransform, we have a custom * operator that does the multiplication. There's also a custom operator for A * v where A is an affineTransform and v is a playdate.geometry.vector2d (or another geometric element). There is no corresponding operator for v * A — you'll get a runtime error if you try that.

We do use pre-multiplication when composing transforms via functions like affineTransform:translate() or translatedBy(). But our transform * transform operator appears to post-multiply, so the expression a * b is computed as if you're right-multiplying b by a. As a result, these two expressions are not equivalent:

v1 = transform1 * (transform2 * vector)
v2 = (transform1 * transform2) * vector
v1 == v2  -- false!

which violates associativity. This seems worth fixing, though I worry that existing games are relying on the current behavior, so it might not be feasible. We'll look into it. Thanks!

2 Likes