Transformations

Sometimes it’s necessary to transform a specific group of 2D objects (or even all of them) without manually modifying their positions, rotations and sizes.

A transformation matrix allows you to do just that. It encompasses a certain order of transformations that are applied to your objects relative to their default transformation.

Imagine drawing a 2D scene and wanting to scale the entirety of it by a specific factor, e.g. 1.5. You could draw all objects of that scene by offset their positions and scaling their sizes accordingly, for each drawSprite() call.

Or you could construct a matrix using cer::scale({1.5f, 1.5f}) and apply that to all of them. We can apply a transformation using the cer::setTransformation() function.

Applying a transformation
setTransformation(scale({1.5f, 1.5f}));

drawSprite(myImage, {200, 200});
drawSprite(myImage, {400, 300});
drawSprite(myImage, {600, 400});

This would scale everything by a factor of 1.5 across both the X- and Y-axis. As an example, {-1.5f, 2.0f} would mirror the objects along the Y-axis, and also scale them by a factor of 2.0 along the Y-axis. In other words, negative factors allow mirroring effects.

Another example would be if you wanted to first rotate the objects, then scale them, and finally offset their positions by a specific amount. This is done by multiplying such matrices in a specific order:

// Rotation by 45 degrees.
auto rotation    = rotate(Radians(45.0_deg));

// Scale by 1.5 along x-axis, and 3.5 along y-axis.
auto scale       = scale({1.5f, 3.5f});

// Move by 100 along x-axis, and -100 along y-axis.
auto translation = translate({100, -100});

// Combine all transformations into one.
auto transform   = rotation * scale * translation;

// Apply to all subsequent drawings.
setTransformation(transform);

Transformation matrices are often used to implement 2D cameras, since they typically require movement (cer::translate()) as well as a zoom (cer::scale()). A camera’s transformation is therefore a combination of both matrices.

As with all states, the transformation is remembered by cerlib until it’s changed again. To restore the default transformation, which is an identity matrix, simply set a default-constructed matrix:

setTransformation({});

If you wish to set a transformation temporarily and restore the previously set transformation afterwards, you can obtain the active transformation before setting yours.

Temporary transformations
auto previousTransformation = currentTransformation();
setTransformation(myTransformation);

// Draw your objects
// ...

// Restore the previous transformation
setTransformation(previousTransformation);