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 }
you are awesome swiftless.. it helped alot for my MCS exam
Thank you again very much Swiftless.
I’m getting a little more time nowadays to go through your tutorials. And I just want to say that I deeply appreciate all your hard work and for sharing your expertise and thoughts with the rest of us.
I don’t think any of us take your time lightly. It is very kind of you.
-kropcke
For some reason The section of code you give is almost completely pushed out of the frame. I noticed this only seems to happen on pages where the ads are actually next to the section of code. I’m not sure if it’s a CSS issue or what but it does make it a little hard to read on some pages. The only browsers I have noticed this on have been Chrome and Explorer, I don’t use firefox anymore so I don’t know if it’s there too.
Hi Andrew,
This is a known problem. It occurred when I transferred the site from manual php to WordPress. The version 2 and newest tutorials don’t suffer from it because they are WordPress friendly. It’s one of those things I still have to get around to fixing.
Thanks,
Swiftless
i cant see anything getting changed
Hi A man,
What do you mean?
Thanks,
Swiftless
the scale functions seems to be applying on both cubes, I tried adding glScalef( 1.0, 1.0, 1.0) before the rotation lines of second cube but both cubes get scaled
Hi Imrn,
Yes, anything you do will be applied to all the following shapes unless you use glPushMatrix and glPopMatrix, which are mentioned in a later tutorial.
Cheers,
Swiftless
Thanks for the feedback.
I have noticed some issues with the code, this is all fixed in the new versions of the tutorials, once I get around to writing them all that is.
Cheers,
Swiftless
Great tutorial! Like the page’s design too 🙂
A minor gripe though: Some of the comments are split up by line breaks. You should use /**/ comments instead.