CS 4465 - Lab (6)
More on Transformations, a bit on Views, and push and pop

Our goals in this lab are:
• To create different views of a cube
• To create a rotating cube
• To learn about the push and pop

Preparation
Use the same computer you have used before.  You have some activities that you will finish in the lab and there is a post-lab that you will finish by March 22. This is not an easy program, so please start working on it before you leave for the break.

More on Transformations
Following is a program that creates a cube.

#include <GL/glut.h>
#include <math.h>
typedef GLfloat point3[3];
double PI;
point3 p[8]={
{0,0,0},  //black
{0,0,1},  //blue
{1,0,1},  //magenta
{1,0,0},  //red
{0,1,0},  //green
{0,1,1},  //green+blue
{1,1,1},  //white
{1,1,0}   //yellow
};

void drawPoint(int i){
glVertex3fv(p[i]);
}
void drawFace(int i1,int i2,int i3,int i4){
glBegin(GL_POLYGON);
glColor3fv(p[i1]);
drawPoint(i1);
drawPoint(i2);
drawPoint(i3);
drawPoint(i4);
glEnd();
}

void myinit(void)
{

/* attributes */
glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
glColor3f(0.0, 0.0, 0.0); /* draw in black */
/* set up viewing */
glMatrixMode(GL_PROJECTION);
glOrtho(-1, 1, -1, 1,-10,10);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
PI=3.141592654;
}
void drawCube(){
drawFace(0,3,2,1); //bottom = black,
drawFace(1,2,6,5); //front = blue
drawFace(2,3,7,6); //right side = magenta
drawFace(3,0,4,7); //back side = red
drawFace(4,5,6,7); //top = green
drawFace(5,4,0,1); //left side = green + blue
}

void display( void )
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  /*clear the window */
glMatrixMode(GL_MODELVIEW);
glTranslatef(-.5,-.5,-.5);
drawCube();
glFlush(); /* clear buffers */
}

void main(int argc, char** argv)
{
/* Standard GLUT initialization */
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_SINGLE| GLUT_RGB|GLUT_DEPTH);

glutInitWindowSize(500,500); /* 500 x 500 pixel window */
glutInitWindowPosition(0,0); /* place window top left on display */
glutCreateWindow("Cube"); /* window title */
glutDisplayFunc(display); /* display callback invoked when window opened */
myinit(); /* set attributes */
myinit(); /* set attributes */
glutMainLoop(); /* enter event loop */
}

Activity (1)
Cut and paste the program and run it.  It creates a cube.  The rotation of cube can be done using the glRotatef(theta, x, y, z); where theta is the angle of rotation and x, y, z determine the axis around which you will rotate the cube.  For example:

glRotatef(45, 1, 0, 0);

will rotate the cube by 45 degree around the x axis, because the  y and z  components are set to 0.

Make changes in the program (one rotation at the time) to create the following view of the cube.

Note that this image can be created by rotating the cube about the x axis by 45 and then about the y axis by 45.

Activity (2)
The above view is not an "isogonal view" of the cube.  To create the correct view the rotation about y axis must be 45 but rotation about x axis must be computed.  The angle of rotation around x axis must be:

Tetha = sin-1 (sqrt(3.0)/3)  OR Tetha = cos-1 (sqrt(2.0)/sqrt(3.0) )

Note that this angle must be in Radian.   We will talk about different views in class very soon.  For now, take this from me that the above rotation angle around x axis will produce an isogonal view shown below.  Try to figure out why the angle is Theta not 45.

Make changes in your program to create the correct "isogonal view" of the cube as shown below.

Activity (3)
Make changes so your program such that it creates and spins a color cube in a cumulative direction. In order to do this, you can use the Idle call back function.  Your program should do different things based on the following list:

1) if 'x' or 'X' is pressed, it rotates about x axis
2) if 'y' or 'Y' is pressed, it rotates about y axis
3) if 'z' or 'Z' is pressed, it rotates about z axis
4) if '+' is pressed, it increases the speed of rotation
5) if '-' is pressed, it decreases the speed of rotation
6) if '  ' spacebar is pressed, everything is reset
7) if 'q' or 'Q' is pressed, it terminates
A hint for rotation: Hint

Activity (4)
We discussed the procedure for implementing the cube.Now let's look at scaling and translating of our cube to make "bricks". We'll need to call glPushMatrix() and glPopMatrix() to save and restore the ModelView matrix, so that we can get back to a previous position from which some new offset is desired. Here's a compound example:

#include <GL/glut.h>
typedef GLfloat point3[3];
point3 p[8]={
{0,0,0},  //black
{0,0,1},  //blue
{1,0,1},  //magenta
{1,0,0},  //red
{0,1,0},  //green
{0,1,1},  //green+blue
{1,1,1},  //white
{1,1,0}   //yellow
};

void drawPoint(int i){
glColor3fv(p[i]);
glVertex3fv(p[i]);
}
void drawFace(int i1,int i2,int i3,int i4){
glBegin(GL_POLYGON);
drawPoint(i1);
drawPoint(i2);
drawPoint(i3);
drawPoint(i4);
glEnd();
}

void myinit(void)
{

/* attributes */
glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
glColor3f(0.0, 0.0, 0.0); /* draw in black */
/* set up viewing */
glMatrixMode(GL_PROJECTION);
glOrtho(-1, 1, -1, 1,-10,10);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
}
void drawCube(){
drawFace(0,3,2,1); //bottom = black,
drawFace(1,2,6,5); //front = blue
drawFace(2,3,7,6); //right side = magenta
drawFace(3,0,4,7); //back side = red
drawFace(4,5,6,7); //top = green
drawFace(5,4,0,1); //left side = green + blue
}

void drawBrick(){
glPushMatrix();
glScalef(.5,.125,.25);
glTranslatef(-.5,-.5,-.5);
drawCube();
glPopMatrix();
}

void display( void )
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  /*clear the window */
glMatrixMode(GL_MODELVIEW);
glRotatef(20,1,0,0);
glRotatef(20,0,1,0);
glPushMatrix();

// draw two bricks in same row
drawBrick();
glTranslatef(.6,0,0);
drawBrick();

//return to start of row, go up one brick and over half a brick
glPopMatrix();
glTranslatef(.3,.14,0);
drawBrick();
glFlush(); /* clear buffers */
}

void main(int argc, char** argv)
{
/* Standard GLUT initialization */
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_SINGLE| GLUT_RGB|GLUT_DEPTH);

glutInitWindowSize(500,500); /* 500 x 500 pixel window */
glutInitWindowPosition(0,0); /* place window top left on display */
glutCreateWindow("Test"); /* window title */
glutDisplayFunc(display); /* display callback invoked when window opened */
myinit(); /* set attributes */
glutMainLoop(); /* enter event loop */
}

Here's the image:

Post-Lab - Due March 29