Coordinate system transformations

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.

Note

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.

    Tip

    Though the coordinate system is restored before testApp::draw() is called, we recommend that the number of ofPushMatrix() and ofPopMatrix() callings in your project should be exactly the same. It will simplify the project's debugging and further development.

  • 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:

  1. Store the current transformation matrix using ofPushMatrix().
  2. Change the coordinate system by calling any of these functions: ofTranslate(), ofScale(), or ofRotate().
  3. Draw something.
  4. Restore the original transformation matrix using ofPopMatrix().

Note

Step 3 can include steps 1 to 4 again.

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.

Tip

This transformation significantly simplifies coding the drawings that should be located at the center of the screen.

Now let's use coordinate system transformation for adding triangular petals to the flower.

Tip

For further exploring coordinate system transformations, see the example in the Rotating images section in Chapter 4, Images and Textures.

Flower with petals example

In this example, we draw petals to the flower from the 02-2D/03-FlowerControlPoints example, described in the Using control points example section.

Note

This is example 02-2D/04-FlowerWithPetals.

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.

Flower with petals example
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset