Exercise 3: OpenGL Viewing
This exercise introduces the transformations used by OpenGl
to render a 3D scene
onto the computer screen. The transformation are:
OpenGL Viewing and Modelling transformations are rotation, translation and scaling transforms combined in the 'modelview' matrix. The viewing transformation must be specified before the modelling transform.
The projective transform is represented in the 'projection' matrix. OpenGL support both orthographic projection (all lines are projected parallel to each other) and perspective projection (pin-hole camera). Projective and Viewport transforms can be specified in any order.
The following exercises illustrate the use of these transformations to setup and view a 3D scene.
Copy the directory /vol/www/ee/Teaching/Courses/CGI/exercise3
1. Cube View
The program view_cube.c draws a 3D cube under
orthographic projection. Compile and run the program.
make -f make_view_cube
./view_cube
(i) Draw a set of unit axis at the origin using:
glBegin(GL_LINES);
glColor3f(1,0,0);
glVertex3f(0,0,0);
glVertex3f(0,1,0);
......
glEnd();
Compile and run to view the axis (at the centre of the cube).
(ii) Change the view tranformation specified by
function:
gluLookAt(location,
direction, up);
location - camera position
direction - camera view direction
up - vertical direction for view
The default view is with the camera located at the
origin looking along the negative
z-axis with the y-axis as up.
(iii) The function gluLookAt() is a utility routine which transforms the
camera location
by modifying the 'modelview'
matrix. This utility implements the transformation
using glRotatef() and glTranslatef()
functions. Replace the following
gluLookAt() with the equivalent rotation and
translation:
gluLookAt(0,0,5, 0,0,0, 0,1,0);
gluLookAt(5,0,5, 0,0,0,
0,1,0);
(iv) The modelling transformation is applied to
position objects in the scene,
The modelview matrix
is post multiplied by the modelling transformations
as they are
applied to concatenate them into a single
matrix.
Using functions glTranslatef(), glRotatef() and glScalef()
translate the
cube model to be rotated by 45 degrees about the
y-axis, tranlated to location (0,0,-5)
and scaled such that length in the x-direction
is twice the y and z directions.
Note the order in which transformations are speficied is important. They should be specied
in reverse order to the order:
glTranslatef();
glRotatef();
glScalef();
draw_cube();
First the cube is scaled, then rotated about the origin, then translated.
Adjust the viewing transform to verify that
the cube has been moved to the correct position
and theat the axis
remain at the global origin.
(v) An orthographic projection is specified using glOrtho() to
project the 3D scene to 2D, all
objects appear the same size irrespective of their discance from the camera. OpenGL support
perspective projection to create more realistic images
using a pin-hole camera model where objects
further from the camera appear smaller.
Replace the orthographic projection with a perspective
projection specified using
the function glFrustum() which defines the view frustum for
perspective projection.
The view frustum or viewing volume (part of the scene which
is visible) is a pyramid with its appex
at the camera viewpoint. The visible section of the pyramid
is the volume between the 'near' and
'far' planes which are orthogonal to the view direction.
glFrustum(left,right,bottom,top,near,far);
(left,bottom,-near)
and (right,top,-near) are the lower-left and
upper-right coordinates of the
front plane of the view frustum,. near and far are the distances from the camera centre to the
front and back plane.
Try viewing along the z-axis projection with the
following parameters:
glFrustum(-1.0,1.0,-1.0,1.0,1.5, 20.0);
Change the distance to the near and far planes - what is the effect?
(vi) You can also setup the perspective projection
with the utility function gluPerspective()
as follows:
gluPerspective(fovy,aspect,near,far);
fovy - angle of field of view
aspect -
ratio of frustum width/height
near/far -
distance to near and far cutoff plances
Replace the perspective projection defined in (v) with gluFrustum() to use the equivalent
gluPerspective()
Note: gluPerspective() is limited to creating frustums which are symmetric about the line of sight.
(vii) Add a GLUT keyboard callback function keyboard() to adjust the viewing, modelling and projection transformations in responce to specific keys:
static float distance=5.0;
void keyboard(unsigned char
key, int x, int y)
{
switch
(key) {
case 'd':
distance = distance +5;
glutPostRedisplay();
break;
case 'D':
distance = distance -5;
glutPostRedisplay();
break;
default:
break;
}
}
and in the main function
register the glut callback function:
glutKeyboardFunc(keyboard);
Change the viewing transform to:
glLookAt(0,0,distance, 0,0,0, 0,1,0);
The cube should zoom in and out using the keys 'd' and '-D' by moving the camera
center along the z-axis.
Now try adding keyboard commands to change:
- model rotation/translation
- perspective near/far plane
distance.
2. Planets
This exercise introduces the use of model transformations to manipulate multiple objects
(i) Compile and run the program planets.c
make -f make_planets
./planets
This program shows a single sphere which can be rotated
about its axis using
the 'y' key (year).
Note glPushMatrix()/glPopMatrix() are
used to save and restore the modelview matrix
after transforming the sphere.
(ii) Now add a second sphere which rotates around the first axis according
to the year
and also about its own axis
according to a parameter 'day':
glTranslatef(2.0,0.0,0.0);
glRotatef(day,0.0,1.0,0.0);
glutWireSphere(0.2,10,8);
Note the order the transformations translate/rotate is
such the new sphere is first rotated
about the origin according to angle day. Placing the model transforation after the transformation
of the first sphere will then rotate it about the origin
again.
Add key bindings for 'd' and 'D' to increase and decrease the parameter day.
(iii) Add an third sphere rotating about the new
sphere according to the parameter 'time'.
Use the matrix stack glPushMatrix()/glPopMatrix() to save and restore the modelview
matrix.
(iv) Tilt the axis of the original sphere.
3. Articulation
The matrix stack can also be used to maniputate articulated structures with chains of joints.
(i) The program arm.c
shows a single segment of an articulated arm which is rotated about it end as
the
pivot point by the angle 'shoulder'. Compile and run the
program and interactively control the
shoulder rotation with 's' and 'S'.
Look at the display()
function to understand how the arm segment is implemented
using the matrix stack together with rotation, translation
and scaling transforms.
Applying the transforms in reverse order the following
transforms are perfomed on the
wire cube:
a) glutWireCube() - generate a
cube centered on the origin
b) glScalef()
- scale the cube to a rectangular segment shape
c) glTranslatef()
- translate along the x-axis cube so that the origin is at one end (the pivot
point)
d) glRotatef()
- about the origin by angle 'shouder'
e) glTranslatef()
- translate back to the original origin
Note how glPushMatrix() and glPopMatrix are used to isolate the various transforms.
(ii) Add a second segment to rotate about a pivot point at end of the first
segment using the
following transformation. Here the final
translation is performed to move the pivot point of
the second segment to cooincide
with the first segment.
Make sure you understand how these transformations are concatenated together.
glTranslatef(1.0,0.0,0.0);
glRotatef(elbow,0.0,0.0,1.0);
glTranslatef(1.0,0.0,0.0);
glPushMatrix();
glScalef(2.0,0.4,1.0);
glutWireCube(1.0);
glPopMatrix();
(iii) Now add a third segment of half the size whose angle relative to the
axis of the second segment
is controlled by a parameter 'wrist'.
(iv) Give the arm two fingers segments at the end
of the wrist each with independent angle control.
5. Track Ball
If you have time to spare.....
A convenient way to control the user viewpoint is via a virtual track ball
controlled by holding
down the mouse buttons. See Angel p185. Implement a track ball for any of the
above programs
to allow you to view the 3D models you've created from any direction.