41. Viewing
Dated: 08-07-2025
Overview: the Camera Analogy
The viewing transformations
must precede the modeling transformations
in our code, but we can specify the projection
and viewport transformations
at any point before drawing occurs.
Stages of Vertex Transformation
To specify the following transformations
- viewing
- modeling
- projection
we construct \(4 \times 4\) matrix
1 \(M\) such that
Where \(\vec v\) are the coordinates of a vertex
.
Modelview matrix
1 is combination of viewing
and modeling
transformations.
We can manipulate the dimensions of the viewport
to cause the final image to be enlarged, shrunk, or stretched.
A Simple Example: Drawing a Cube
The viewing transformation
, gluLookAt()
, positions and aims the camera towards where the cube is drawn.
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity(); // clear the matrix
// viewing transformation
gluLookAt(
0.0, 0.0, 5.0, // eye position
0.0, 0.0, 0.0, // look-at point
0.0, 1.0, 0.0 // up vector
);
glScalef(1.0, 2.0, 1.0); // modeling transformation
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Transformed Cube
The Viewing Transformation
Recall that the viewing transformation
is analogous to positioning and aiming a camera.
Setting the current matrix
1 to \(I\) by calling glLoadIdentity()
is important because most of the transformation commands multiply the current matrix
1 by the specified matrix
1 then set the result to be the current matrix
.1
The gluLookAt()
indicates where the camera is placed and if it is not defined, the camera is situated at the origin, points down the \(z^-\) axis. The up vector
2 defines a unique orientation for the camera.
The Modeling Transformation
We use the modeling transformation to position and orient the model.
The Projection Transformation
Specifying the projection transformation is like choosing a lens for a camera
. Two basic types of projections are provided for us by OpenGL
.
Perspective
projection specified byglFrustum()
Orthographic
projection (used by architects to reflect the real measurements of the viewed object).
glMatrixMode()
changes which matrix
1 we are dealing with
Thinking about Transformations
All viewing and modeling transformations are represented as \(4 \times 4\) matrices
.1 Each successive call to glMultMatrix()
or transformation
command multiplies a new \(4 \times 4\) matrix
1 \(M\) by current modelview matrix
1 \(C\) to yield \(CM\). Finally, vertices
\(v\) are multiplied by the current modelview matrix
.1
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf(N); // apply transformation N
glMultMatrixf(M); // apply transformation M
glMultMatrixf(L); // apply transformation L
glBegin(GL_POINTS);
glVertex3fv(v); // draw transformed vertex v
glEnd();
In this code, the modelview matrix
1 successively contains
- \(I\)
- \(N\)
- \(NM\)
- \(NML\)
The transformed vertex
\(v\) is \(NMLv\).
Moving a Local Coordinate System
A local coordinate system
is tied relative to the object and the transformation matrices
1 appear in their natural order in the code. Only problem with this approach is that a non uniform transformation (which changes the shape of the object) can cause the local coordinate system
to be non perpendicular, hence making things confusing and tougher to deal with.
If there is no viewing transformation
if camera should be left at its default position and there is no modeling transformation
if the model isn't moved.
Modeling Transformations
OpenGL
provides
glTranslate()
glRotate()
glScale()
Each matrix
1 multiplication is described in terms of what it does to the vertices
of a geometric object using the fixed coordinate system
approach, and in terms of what it does to the local coordinate system
that's attached to an object.
Translate
void glTranslatef(float x, float y, float z)
void glTranslated(double x, double y, double z)
Moves the local coordinate system
by \((x, y, z)\).
Rotate
void glRotatef(float angle, float x, float y, float z)
void glRotated(float angle, double x, double y, double z)
Let \(O\) be the origin
and \(\vec R = \langle x, y, z \rangle\) then these functions
rotate the local coordinate system
about \(\vec{OR}\) by angle
amount in counter clockwise direction.
Scale
glScalef(float x, float y, float z)
glScaled(double x, double y, double z)
The \(x, y, z\) coordinates of each point of the object are multiplied by x
, y
and z
.
Code Example
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
draw_triangle(); /* solid lines */
glEnable(GL_LINE_STIPPLE); /* dashed lines */
glLineStipple(1, 0xF0F0);
glLoadIdentity();
glTranslatef(-20.0, 0.0, 0.0);
draw_triangle();
glLineStipple(1, 0xF00F); /*long dashed lines */
glLoadIdentity();
glScalef(1.5, 0.5, 1.0);
draw_triangle();
glLineStipple(1, 0x8888); /* dotted lines */
glLoadIdentity();
glRotatef (90.0, 0.0, 0.0, 1.0);
draw_triangle ();
glDisable (GL_LINE_STIPPLE);
Viewing Transformations
A viewing transformation
changes the position and orientation of the viewpoint
.
Keep in mind that the viewing transformation
commands must be called before any modeling transformations
are performed, so that the modeling transformations
take effect on the objects first.
Emulating Viewing Transformations
through Modeling Transformations
When we use modeling transformation
commands to emulate viewing transformations
, we're trying to move the viewpoint
in a desired way while keeping the objects in the world stationary.
To put \(5\) units of distance between the viewpoint
and the objects by moving the viewpoint
, use glTranslatef(0.0, 0.0, -5.0);
This routine moves the objects in the scene \(-5\) units along the \(z\) axis. This is also equivalent to moving the camera \(+5\) units along the \(z\) axis.
Comparisons
Imagine both camera and an object at the origin
. We want to see the side of the object but how do we achieve it?
Fixed Coordinate System
Approach
We could rotate the object first and then translate it but we know that in fixed coordinate system
approach, the code has to have transformation matrices
1 in the reverse order. Therefore, in the code, we have translate first, followed by rotation commands.
Local Coordinate System
Approach
In this approach, the object may be translated first and then rotated using its local coordinate system
. Also, the transformation matrices
1 appear in the natural order in the code.
glTranslatef(0.0, 0.0, -5.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
Using the gluLookAt()
Utility Routine
Sometimes, we want to construct the scene around the origin
and then orient the camera (viewpoint
) to look at a certain position in the scene.
void gluLookAt(
GLdouble eye_x, GLdouble eye_y, GLdouble eye_z,
GLdouble center_x, GLdouble center_y, GLdouble center_z,
GLdouble up_x, GLdouble up_y, GLdouble up_z,
);
The camera is positioned at eye
, it looks at center
and the up
vector
2 defines which direction is up relative to the scene.
Manipulating the Matrix
1 Stacks
ModelView matrix
1 stacks \(32\) matrices
1 meanwhile projection matrix
1 stacks \(2\) matrices
.1 These matrices
1 are \(4 \times 4\) in dimension.
draw_wheel_and_bolts() {
long i;
draw_wheel();
for(i = 0; i < 5; i++) {
glPushMatrix();
glRotatef(72.0 * i, 0.0, 0.0, 1.0);
glTranslatef(3.0, 0.0, 0.0);
draw_bolt();
glPopMatrix();
}
}
draw_body_and_wheel_and_bolts() {
draw_car_body();
glPushMatrix();
glTranslatef(40,0,30); /*move to first wheel position*/
draw_wheel_and_bolts();
glPopMatrix();
glPushMatrix();
glTranslatef(40,0,-30); /*move to 2nd wheel position*/
draw_wheel_and_bolts();
glPopMatrix();
...
/*draw last two wheels similarly*/
}
This code assumes the wheel and bolt axes are coincident with the \(z\) axis, that the bolts are evenly spaced every \(72\) degrees, \(3\) units (maybe inches) from the center of the wheel, and that the front wheels are \(40\) units in front of and \(30\) units to the right and left of the car's origin.