# Views

Classify each of the following as parallel or perspective, and as dimetric, isometric, 1-point, 2-point, or 3-point projections:

 1 2 3 4 5

1. 2-point perspective
2. dimetric parallel
3. 1-point perspective
4. isometric parallel
5. 3-point perspective

We categorize projections as parallel or perspective depending on whether we specify a view direction (with a viewer "infinitely far away") or a fixed view position. In the parallel case, we call the projection orthographic if the projection plane is orthogonal to the view direction, and oblique otherwise. Common architectural orthographic projections are the front, side and plan views. Other orthographic views are called axonometric. The special case in which the three axis directions make the same angle with the projection direction is called isometric. If only two axes make the same angle, the projection is called dimetric. The general case in which no principal face is parallel to the projection plane is called an axonometric orthographic projection (which includes both the dimetric and isometric as special cases).

We classify pespective projections as one-point, two-point, or three-point depending on the number of "vanishing points". In a one-point projection, only one of the principal axes intersects the projection plane. In a 2-point projection, two axes intersect the projection plane. The general case (most likely if a rectangular solid is rotated to a random position) is the 3-point projection in which all principal axes intersect the projection plane.

In OpenGL we can use glOrtho to fix parallel orthographic projection, and glFrustum to determine a perspective projection. (There are alternatives in OpenGL as well.) Both functions should be proceeded by

`	glMatrixMode(GL_PROJECTION);	glLoadIdentity();`

This is because any matrix operations in OpenGL will affect either the MODELVIEW or PROJECTION matrices (which ultimately get multiplied to determine the final projection), and it is important to be in the right mode when changing a matrix.

glOrtho and glFrustum each take six parameters specifying the x-, y- and z-ranges. glOrtho just defines a box; the z-coordinates of points within this box are discarded to obtain the projection. glOrtho is different: the first four parameters determine the front rectangle of a frustum (a truncated pyramid) associated with the smaller of the two z-values. The corresponding x- and y-bounds for the back face are larger in proportion to the distance of the back plane from the eye position.

Let's look at a cube from a variety of positions. The cube is blue on front, purple on the right, and green on top. Here's a not-very-interesting head-on view:

Here's the code that generated it:

`#include <GL/glut.h>typedef GLfloat point3[3];// List all vertices in array and reference later by indexpoint3 p[8]={	{0,0,0},	{0,0,1},	{1,0,1},	{1,0,0},	{0,1,0},	{0,1,1},	{1,1,1},	{1,1,0}};point3 p2[8]; //a copy of the first cube centered at the originvoid drawPoint(int i){// Draw point i 	glVertex3fv(p2[i]);}void drawFace(int i1,int i2,int i3,int i4){// draw a face of the cube// use color of first point for entire face	glBegin(GL_POLYGON);	glColor3fv(p[i1]);	drawPoint(i1);	drawPoint(i2);	drawPoint(i3);	drawPoint(i4);	glEnd();}void drawCube(){	drawFace(0,3,2,1); //bottom	drawFace(1,2,6,5); //front	drawFace(2,3,7,6); //right side	drawFace(0,1,5,4); //left 		drawFace(3,0,4,7); //back side	drawFace(4,5,6,7); //top}void myinit(void){	int i,j;	for(i=0;i<8;i++)for(j=0;j<3;j++)p2[i][j]=p[i][j]-.5;	/* attributes */	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background *//* set up viewing */	glMatrixMode(GL_PROJECTION);	glLoadIdentity();// The z-range can be crude, just so it includes area of interest// The x- and y-ranges need to be "tighter"	glOrtho(-1,1,-1,1,-10,10);  }void display( void ){	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window */	glTranslatef(0,0,-2);  //pull back from the cube	drawCube();	glFlush(); /* clear buffers */}void main(int argc, char** argv){/* Standard GLUT initialization */	glutInit(&argc,argv);	glutInitDisplayMode (GLUT_RGB|GLUT_DEPTH); /* default, not needed */	glutInitWindowSize(250,250); /* 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 */	glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */	glutMainLoop(); /* enter event loop */}`

If I change the bold-face code to

`	glTranslatef(0,0,-2);	glRotatef(-45,0,1,0);`

we get this image of two faces:

To see three faces we need to add another transformation:

`	glTranslatef(0,0,-2);	glRotatef(34,1,0,0);	glRotatef(-45,0,1,0);`

we get:

Now let's see if we can cook up one-point, two-point and three-point perspective projections. The following program gives the same front view as the first orthographic projection above:

`#include <GL/glut.h>typedef GLfloat point3[3];GLfloat w=.3; //x- and y- bounds for frustum// List all vertices in array and reference later by indexpoint3 p[8]={	{0,0,0},	{0,0,1},	{1,0,1},	{1,0,0},	{0,1,0},	{0,1,1},	{1,1,1},	{1,1,0}};point3 p2[8]; //a copy of the first cube centered at the originvoid drawPoint(int i){// Draw point i 	glVertex3fv(p2[i]);}void drawFace(int i1,int i2,int i3,int i4){// draw a face of the cube// use color of first point for entire face	glBegin(GL_POLYGON);	glColor3fv(p[i1]);	drawPoint(i1);	drawPoint(i2);	drawPoint(i3);	drawPoint(i4);	glEnd();}void drawCube(){	drawFace(0,3,2,1); //bottom	drawFace(1,2,6,5); //front	drawFace(2,3,7,6); //right side	drawFace(0,1,5,4); //left 		drawFace(3,0,4,7); //back side	drawFace(4,5,6,7); //top}void myinit(void){	int i,j;	for(i=0;i<8;i++)for(j=0;j<3;j++)p2[i][j]=p[i][j]-.5;	/* attributes */	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background *//* set up viewing */	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	glFrustum(-w,w,-w,w,.4,8);}void display( void ){	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	glTranslatef(0,0,-2);	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*clear the window */	drawCube();	glFlush(); /* clear buffers */}void main(int argc, char** argv){/* Standard GLUT initialization */	glutInit(&argc,argv);	glutInitDisplayMode (GLUT_RGB|GLUT_DEPTH); /* default, not needed */	glutInitWindowSize(250,250); /* 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 */	glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */	glutMainLoop(); /* enter event loop */}`

If we change

`	glColor3fv(p[i1]);`

in drawFace to

`	glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);	glBegin(GL_POLYGON);	glColor3f(0,0,0);`

we obtain an image which shows that this is a one-point projection. (Only one set of edges converges to a point).

Now let's move around the corner to get a two point projection:

Here's the code which replaces the code in bold:

`	glTranslatef(0,0,-2);	glRotatef(-45,0,1,0);`

Finally, let's add one more transformation to obtain a view from above:

`	glTranslatef(0,0,-2);	glRotatef(34,1,0,0);	glRotatef(-45,0,1,0);`

Here's the wire frame:

and here's the full-color version:

If you want a good source of detailed information in "positioning the camera" in OpenGL, see Chapter 3 of the Red Book.