10. OpenGL Scaling (Version 2.0)

Introduction

Scaling is the process of manipulating the physical dimensions of an object in relation to itself. For example, you can stretch or shrink an object along any of the 3 axis (x, y and z).

Scaling isn’t a difficult process in OpenGL 2.x and prior because you can use inbuilt functions and I won’t go into the matrix operations involved in scaling within a shader based environment as that’s not what this tutorial is for.

There’s not much else I can say to explain scaling. Scaling is stretching and shrinking, that’s it. The terminology comes from vector math, where it relates to the length of a vector and the manipulations you can perform on a vector.

Usage

OpenGL comes with the function glScalef which we call before we draw our object and takes 3 values, X, Y and Z. These are all values between -XYZ and +XYZ with 1.0 being the original size of the object.

If we call glScalef(1.f, 1.f, 1.f); then our object is going to stay the exact same size and nothing is going to look different. However if we call glScalef(0.5f, 0.5f, 0.5f); then our object is going to be half of the original size along every axis.

For such a simple function, it is extremely useful, imagine a power-up in Mario where you get the mushroom and Mario grows. You can simply call glScalef(2.f, 2.f, 2.f); and Mario will be twice his original size while everything else stays the same size.

Coding

Let’s get into it, this no matter how you look at it is a short tutorial.

We’re going to base this tutorial off of the double buffering tutorial as we don’t need the blending functionality.

What we are going to do is take our square as provided by GLUT and we are going to make it half as wide along the x-axis, the same height along the y-axis and twice as deep along the z-axis.

To do this, all we need is the following line of code, right above where we call glutWireCube:

glScalef(0.5f, 1.0f, 2.0f); // Make the shape half as wide, the same height and twice as deep

If you run this you will see the size of the cube has changed and you will get the full effect as it rotates. We started off with a cube and we now have a rectangle thanks to this nifty little call.

It’s important to note that because we call this right before we draw our cube, it is based around the cubes centre of origin, which is why it isn’t narrower on one half. I’ve tried to centre everything in these tutorials around the centre of the screen, to help emphasize this.

If you have any problems at all, email me at swiftless@gmail.com and happy coding!

Tutorial Code

#include <GL/glew.h> // Include the GLEW header file
#include <GL/glut.h> // Include the GLUT header file

bool* keyStates = new bool[256]{0}; // Create an array of boolean values of length 256 (0-255)

bool movingUp = false; // Whether or not we are moving up or down
float yLocation = 0.0f; // Keep track of our position on the y axis.

float yRotationAngle = 0.0f; // The angle of rotation for our object

void keyOperations (void) {
if (keyStates[GLUT_KEY_LEFT]) { // If the left arrow key has been pressed
// Perform left arrow key operations
}
}

void display (void) {
keyOperations();

glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations

glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive

glTranslatef(0.0f, yLocation, 0.0f); // Translate our object along the y axis

glRotatef(yRotationAngle, 0.0f, 1.0f, 0.0f); // Rotate our object around the y axis

glScalef(0.5f, 1.0f, 2.0f); // Make the shape half as wide, the same height and twice as deep
glutWireCube(2.0f); // Render the primitive

glutSwapBuffers(); // Swap our buffers

if (movingUp) // If we are moving up
yLocation -= 0.05f; // Move up along our yLocation
else // Otherwise
yLocation += 0.05f; // Move down along our yLocation

if (yLocation < -3.0f) // If we have gone up too far
movingUp = false; // Reverse our direction so we are moving down
else if (yLocation > 3.0f) // Else if we have gone down too far
movingUp = true; // Reverse our direction so we are moving up

yRotationAngle += 0.1f; // Increment our rotation value

if (yRotationAngle > 360.0f) // If we have rotated beyond 360 degrees (a full rotation)
yRotationAngle -= 360.0f; // Subtract 360 degrees off of our rotation
}

void reshape (int width, int height) {
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)

gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes

glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
}

void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = true; // Set the state of the current key to pressed
}

void keyUp (unsigned char key, int x, int y) {
keyStates[key] = false; // Set the state of the current key to not pressed
}

int main (int argc, char **argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode (GLUT_DOUBLE); // Set up a basic display buffer (now double buffered)
glutInitWindowSize (500, 500); // Set the width and height of the window
glutInitWindowPosition (100, 100); // Set the position of the window
glutCreateWindow ("Your first OpenGL Window"); // Set the title for the window

glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering

glutIdleFunc(display); // Tell GLUT to use the method "display" as our idle method as well

glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping

glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses
glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events

glutMainLoop(); // Enter GLUT's main loop
}
  • March 25, 2010
  • 10