Rotating, scaling, and translating

In this recipe, we will learn how to transform our graphics using OpenGL transformations.

We will draw a unit cube at [0,0,0] coordinates and then we will translate it to the center of the window, apply rotation, and scale it to a more visible size.

Getting ready

Include the necessary files to draw with OpenGL and add the helpful using statements. Add the following code to the top of the source file:

#include "cinder/gl/gl.h"
using namespace ci;
using namespace ci::app;
using namespace std;

How to do it…

We will apply rotation, translation, and scaling to alter the way our cube is rendered. We will use Cinder's wrappers for OpenGL.

  1. Let's declare variables to store our values for the translation, rotation, and scale transformations:
        Vec3f mTranslation;
        Vec3f mScale;
        Vec3f mRotation;
  2. To define the translation amount, let's translate half the window's width on the x axis and half the window's height on the y axis. This will bring anything we draw at [0,0,0] to the center of the window. Add the following code in the setup method:
    mTranslation.x = getWindowWidth() / 2;
    mTranslation.y = getWindowHeight() / 2;
    mTranslation.z = 0.0f;
  3. Let's set the scale factor to be 100 on the x axis, 200 on the y axis, and 100 on the z axis. Anything we draw will be 100 times bigger on the x and z axes and 200 times bigger on the y axis. Add the following code in the setup method:
    mScale.x = 100.0f;
    mScale.y = 200.0f;
    mScale.z = 100.0f;
  4. In the update method, we will animate the rotation values by incrementing the rotation on the x and y axes.
    mRotation.x += 1.0f;
    mRotation.y += 1.0f;
  5. In the draw method, let's begin by clearing the background with black, setting the windows matrices to allow for drawing in 3D, and enabling OpenGL to read and write the depth buffer:
    gl::clear( Color( 0, 0, 0 ) ); 
    gl::setMatricesWindowPersp( getWindowWidth(), getWindowHeight() );
    gl::enableDepthRead();
    gl::enableDepthWrite();
  6. Let's add a new matrix to the stack and translate, scale, and rotate using the previously defined variables:
    gl::pushMatrices();
    gl::translate( mTranslation );
    gl::scale( mScale );
    gl::rotate( mRotation );
  7. Draw a unit quad at the origin [0,0,0] with a white fill and black stroke:
    gl::color( Color::white() );
    gl::drawCube( Vec3f(), Vec3f( 1.0f, 1.0f, 1.0f ) );
    gl::color( Color::black() );
    gl::drawStrokedCube( Vec3f(), Vec3f( 1.0f, 1.0f, 1.0f ) );
  8. Finally, remove the previously added matrix:
    gl::popMatrices();
    How to do it…

How it works…

The calls to ci::gl::enableDepthRead and ci::gl::enableDepthWrite respectively, enable reading and writing to the depth buffer. The depth buffer is where the depth information is stored.

When reading and writing to the depth buffer is enabled, OpenGL will sort objects so that closer objects are drawn in front of farther objects. When reading and writing to the depth buffer, the disabled objects will be drawn in the order they where created.

The methods ci::gl::translate, ci::gl::rotate, and ci::gl::scale are wrappers of OpenGL commands for translating, rotating, and scaling, which allow you to pass Cinder types as parameters.

Transformations in OpenGL are applied by multiplying vertex coordinates with transformation matrices. When we call the method ci::gl::pushMatrices, we add a copy of the current transformation matrix to the matrix stack. Calls to ci::gl::translate, ci::gl::rotate, or ci::gl::scale will apply the correspondent transformations to the last matrix in the stack, which will be applied to whatever geometry is created after calling the transformation methods. A call to ci::gl::popMatrix will remove the last transformation matrix in the stack so that transformations added to the last matrix will no longer affect our geometry.

..................Content has been hidden....................

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