Sometimes we need to translate, rotate, and resize drawings. For example, arcade games are based on the characters moving across the screen.
When we perform drawing using control points, the straightforward solution for translating, rotating, and resizing graphics is in applying desired transformations to control points using corresponding mathematical formulas. Such idea works, but sometimes leads to complicated formulas in the code (especially when we need to rotate graphics). The more elegant solution is in using coordinate system transformations. This is a method of temporarily changing the coordinate system during drawing, which lets you translate, rotate, and resize drawings without changing the drawing algorithm.
The current coordinate system is represented in openFrameworks with a matrix. All coordinate system transformations are made by changing this matrix in some way. When openFrameworks draws something using the changed coordinate system, it performs exactly the same number of computations as with the original matrix. It means that you can apply as many coordinate system transformations as you want without any decrease in the performance of the drawing.
Coordinate system transformations are managed in openFrameworks with the following functions:
ofPushMatrix()
: This function pushes the current coordinate system in a matrix stack. This stack is a special container that holds the coordinate system matrices. It gives you the ability to restore coordinate system transformations when you do not need them.ofPopMatrix()
: This function pops the last added coordinate system from a matrix stack and uses it as the current coordinate system. You should take care to see that the number of ofPopMatrix()
calls don't exceed the number of ofPushMatrix()
calls.ofTranslate( x, y )
or ofTranslate( p )
: This function moves the current coordinate system at the vector (x
, y
) or, equivalently, at the vector p
. If x
and y
are equal to zero, the coordinate system remains unchanged.ofScale( scaleX, scaleY )
: This function scales the current coordinate system at scaleX
in the x axis and at scaleY
in the y axis. If both parameters are equal to 1.0
, the coordinate system remains unchanged. The value -1.0
means inverting the coordinate axis in the opposite direction.ofRotate( angle )
: This function rotates the current coordinate system around its origin at angle
degrees clockwise. If the angle
value is equal to 0
, or k
* 360
with k
as an integer, the coordinate system remains unchanged.All transformations can be applied in any sequence; for example, translating, scaling, rotating, translating again, and so on.
The typical usage of these functions is the following:
ofPushMatrix()
.ofTranslate()
, ofScale()
, or ofRotate()
.ofPopMatrix()
.For example, for moving the origin of the coordinate system to the center of the screen, use the following code in testApp::draw()
:
ofPushMatrix(); ofTranslate( ofGetWidth() / 2, ofGetHeight() / 2 ); //Draw something ofPopMatrix();
If you replace the //Draw something
comment to ofCircle( 0, 0, 100 );
, you will see the circle in the center of the screen.
Now let's use coordinate system transformation for adding triangular petals to the flower.
For further exploring coordinate system transformations, see the example in the Rotating images section in Chapter 4, Images and Textures.
In this example, we draw petals to the flower from the 02-2D/03-FlowerControlPoints
example, described in the Using control points example section.
We want to draw unfilled shapes here, so add the following lines at the beginning of testApp::draw()
:
ofNoFill(); //Draw shapes unfilled
Now add the following code to the end of testApp::draw()
for drawing the petals:
ofPushMatrix(); //Store the coordinate system //Translate the coordinate system center to stem0 ofTranslate( stem0 ); //Rotate the coordinate system depending on the time float angle = ofGetElapsedTimef() * 30; ofRotate( angle ); int petals = 15; //Number of petals for (int i=0; i<petals; i++) { //Rotate the coordinate system ofRotate( 360.0 / petals ); //Draw petal as a triangle ofPoint p1( 0, 20 ); ofPoint p2( 80, 0 ); ofTriangle( p1, -p1, p2 ); } //Restore the coordinate system ofPopMatrix();
This code moves the coordinate system origin to the point stem0
(the blossom's center) and rotates it depending on the current time. Then it rotates the coordinate system on a fixed angle and draws a triangle petals
times. As a result, we obtain a number of triangles that slowly rotate around the point stem0
.