Swiftless Game Programming Site
Home Tutorials Contact
Home
News
OpenGL
GLSL
OpenCL
Maths
Misc
Work in Progress
Resume
 
 

How to pop and push matrices in OpenGL

If you would like to see this site updated, please help out and

You may notice that when you assign a colour to an object, that colour will also
attach itself to every object you draw after the colour statement. Or the same for
rotations and translations. This is because OpenGL is based on a state machine.

If you want to really understand what these following commands do, then you need
to know about stacks and state machines, but if you only want to use these commands,
then read on. The core ingredient behind OpenGL, and any 3D rendering engine infact, is a transformation matrix.

Now every time you perform an action such as glTranslate or glRotate, then you are
modifying the transformation matrix, and once something has been done, it cannot be
easily undone, so OpenGL makes use of states and says, OK, you are in this state, so
we will apply these transformations and all previous transformations. States still means
that once an operation has been performed, it will affect everything to come, but it means
we can go back to a previous state and forget about our current one.

To do this, we only need to make use of two commands.
They are:
    glPushMatrix(); //set where to start the current object transformations
and:
    glPopMatrix(); //end the current object transformations

The first call, glPushMatrix(), tells OpenGL to store the current state that we are in.
This then allows us to perform a bunch of different effects.

Then when we want to go back to our previous state, we call glPopMatrix().

This works fine for rotations and translations, but OpenGL allows for many other commands,
so it gives us the ability to store attributes with glPushAttrib() and glPopAttrib(). Some of the attributes that we can store include, GL_LIGHT and GL_COLOUR. Of course there are many
more, but they are out of the scope of this tutorial.


If you have any queries, feel free to email me at swiftless@gmail.com

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
  // when you set the glPushMatrix(); it distinguishes where 
to start the transformations for an object

// to set where to stop these transformations you would call 
glPopMatrix();


// for instance, if you take the push and pop matrix code out of
 this file

// cube1 would act normal, but cube2 would be rotating it's 
own way as well

// as including the rotation from cube1

#include <GL/gl.h>
#include <GL/glut.h>

GLfloat angle = 0.0; //angle for cube1
GLfloat tangle = 0.0; //angle for cube2

void cube (void) {
    glPushMatrix(); //set where to start the current object transformations
    glTranslatef(1, 0, 0); //move cube1 to the right
    glRotatef(angle, 1.0, 0.0, 0.0);
    glRotatef(angle, 0.0, 1.0, 0.0);
    glRotatef(angle, 0.0, 0.0, 1.0);
    glColor3f(1.0, 0.0, 0.0); //change cube1 to red
    glutWireCube(2);
    glPopMatrix(); //end the current object transformations
}

void cube2 (void) {
    glPushMatrix(); //set where to start the current object 
transformations

    glTranslatef(-1, 0, 0); //move cube2 to the left
    glRotatef(tangle, 1.0, 0.0, 0.0);
    glRotatef(tangle, 0.0, 1.0, 0.0);
    glRotatef(tangle, 0.0, 0.0, 1.0);
    glColor3f(0.0, 1.0, 0.0); //change cube2 to green
    glutWireCube(2);
    glPopMatrix(); //end the current object transformations
}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();  
    gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    cube();
    cube2();
    glutSwapBuffers();
    angle+= 1.0;
    tangle+= 2.0;
}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow ("A basic OpenGL Window");
    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);
    glutMainLoop ();
    return 0;
}


Download C++ Source Code for this Tutorial

Download Visual Basic Source Code for this Tutorial


Comments:

Name: Baby Stuey
Date: 2010-03-02 18:24:49
Comment:
/*
Here's an extension of the pop_and_push_matrices.cpp that spins three
overlapping cubes of different colours, pushed and popped accordingly.
With blending and transparency turned on, the cubes overlap and show
the resulting colours.

Press '+' for RGB mode
Notice the areas where two primary colours overlap show the three
secondary colours, while the area in the centre where all three
secondary colours overlap is black (K).

C = G + B = -R
M = R + B = -G
Y = R + G = -B
and
K = C + M + Y = -R -G -B

Think of the CMY colours as filters that block the associated primary
colour. If we filter all three primaries, we are left with black.

Press '-' for CMY mode
Notice the areas where two secondary colours overlap show the three
primary colours, while the area in the centre where all three primary
colours overlap is white (W).

M + Y = -G -B = R
C + Y = -R -B = G
C + M = -R -G = B
and
R + G + B = W
*/

#include

#include
#include

#define ALPHA 0.2 // tweak this to your liking

#define colourRed 1.0, 0.0, 0.0, ALPHA
#define colourGrn 0.0, 1.0, 0.0, ALPHA
#define colourBlu 0.0, 0.0, 1.0, ALPHA
#define colourCyn 0.0, 1.0, 1.0, ALPHA
#define colourYel 1.0, 1.0, 0.0, ALPHA
#define colourMag 1.0, 0.0, 1.0, ALPHA
#define colourBlk 0.0, 0.0, 0.0, 1.00
#define colourWht 0.9, 0.9, 0.9, 1.00

GLfloat angle1 = 0.0; // angle for cube1
GLfloat angle2 = 0.0; // angle for cube2
GLfloat angle3 = 0.0; // angle for cube3

int colourToggle = 0;

void cube1(void)
{ glPushMatrix(); // set where to start the current object transformations
glTranslatef(0.8, -0.6, 0.0); // move cube1 to the right down
glRotatef(angle1, 1.0, 0.0, 0.0);
glRotatef(angle1, 0.0, 1.0, 0.0);
glRotatef(angle1, 0.0, 0.0, 1.0);
if(colourToggle) glColor4f(colourRed); // change cube1 fill to red
else glColor4f(colourCyn); // change cube1 fill to cyan
glutSolidCube(2);
if(colourToggle) glColor4f(colourWht); // outline cube in white
else glColor4f(colourBlk); // outline cube in black
glutWireCube(2);
glPopMatrix(); // end the current object transformations
}

void cube2(void)
{ glPushMatrix(); // set where to start the current object transformations
glTranslatef(-0.8, -0.6, 0.0); // move cube2 to the left & down
glRotatef(angle2, 1.0, 0.0, 0.0);
glRotatef(angle2, 0.0, 1.0, 0.0);
glRotatef(angle2, 0.0, 0.0, 1.0);
if(colourToggle) glColor4f(colourGrn); // change cube2 fill to green
else glColor4f(colourMag); // change cube2 fill to magenta
glutSolidCube(2);
if(colourToggle) glColor4f(colourWht); // outline cube in white
else glColor4f(colourBlk); // outline cube in black
glutWireCube(2);
glPopMatrix(); // end the current object transformations
}

void cube3(void)
{ glPushMatrix(); // set where to start the current object transformations
glTranslatef(0.0, 1.0, 0.0); // move cube3 up
glRotatef(angle3, 1.0, 0.0, 0.0);
glRotatef(angle3, 0.0, 1.0, 0.0);
glRotatef(angle3, 0.0, 0.0, 1.0);
if(colourToggle) glColor4f(colourBlu); // change cube3 fill to green
else glColor4f(colourYel); // change cube3 fill to magenta
glutSolidCube(2);
if(colourToggle) glColor4f(colourWht); // outline cube in white
else glColor4f(colourBlk); // outline cube in black
glutWireCube(2);
glPopMatrix(); // end the current object transformations
}


void display(void)
{ glClearColor(0.0, 0.0, 0.0, 0.0);

glClear (GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //set the blend function

glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
cube1();
cube2();
cube3();
glutSwapBuffers();
angle1 += 0.03; // spin each cube slowly, but at different speeds
angle2 += 0.05;
angle3 += 0.01;
}

void reshape (int w, int h)
{ glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{ if(key == 27) // 27 is the ASCII code for the ESC key
{ exit (0); // end the program
} else if(key == '+') // set colours to RGB, outline to white
{ colourToggle = 1;
} else if(key == '-') // set colours to CMY, outline to black
{ colourToggle = 0;
}
}

int main (int argc, char **argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("A basic OpenGL Window");
glutDisplayFunc (display);
glutIdleFunc (display);
glutReshapeFunc (reshape);
glutKeyboardFunc(keyboard); // the call for the keyboard function.

glutMainLoop ();
return 0;
}
Name   Email


Reload Image

 
     

 

Copyright 2009, Donald Urquhart AKA Swiftless
Check out: http://www.cdadc.com