There are three basic transformations in OpenGL:

- Scale (changing the size of an object)
- Translate (moving an object to another location relative to where it started)
- Rotate (rotating an object around a particular axis through the origin of the model)

The actual method calls for each of these transformations is fairly straightforward:

gl.glScaled(double xScale, double yScale, double zScale); gl.glTranslated(double xTranslation, double yTranslation, double zTranslation); gl.glRotated(double degrees, double x, double y, double z); |

It is worth mentioning that in each of these method calls, the method ends in a D not because it is in the past tense, but because there are several variations of each of these methods, and the one we will use expects doubles as parameters (as opposed to glRotatef, which expects floats). Presumably `glScaled()`

and `glTranslated()`

are fairly self-evident: the object is either stretched by a particular factor or shifted by a particular factor along each of the axes — and it could be a different factor for each axis.

`glRotated()`

requires further explanation. glRotated() operates on what is colloquially referred to as the “Right Hand Rule”.

Imagine that your hand is placed with the base of the palm at the origin. The (x, y, z) coordinates specified by `glRotated()`

are at the tip of your thumb. The line from the origin (your palm) to that point (your thumb) defines the axis of rotation — the pole about which the rotation will be performed — nota bene that the axis of rotation will *always* pass through the origin. Your fingers then define the direction of rotation around that axis. And the number of degrees is, well, the number of degrees that you will rotate the object.

The order of transformations is critical. Applying transformations in different orders will have noticeably different effects. The best way to think of the situation that the objects being modeled are passing through a filter, the transformation matrix. Each time a new transformation is applied, the filter is adjusted slightly. A rotation followed by a translation will first rotate the object and then translate it into a new position. A translation followed by a rotation will first move the object into its new position and then rotate the object — *from its new position* — around the axis of rotation at the origin — causing a planet-like orbit about the origin.

Because this filter is adjusted by each transformation applied, all transformations apply to any objects drawn after the transformations apply — the objects always pass through the transformation matrix on their way to being drawn on-screen, and each transformation we apply adjusts the transformation matrix. There is only one transformation matrix. All objects pass through it. The only question is: *when* do they pass through it? Before or after a particular adjustment?

gl.glRotated(90, 0, 1, 0); // rotate 90 degrees around the positive y-axis glut.glutWireTeapot(1.0); // the teapot is rotated gl.glTranslated(10, 0, 0); // translate 10 units along the positive x-axis glut.glutWireTetrahedron; // the tetrahedron is translated and then rotated gl.glScaled(1, 1, 3); // scale, leaving x- and y-axes unchanged, but triple z glut.glutWireIcosahedron(); // the icosahedron is scaled, translated and then rotated |

Note that something strange happens to the order of the transformations — the objects are passed through the most recent transformations first, moving backward in through all of the transformations applied. A quick way to figure out what order the transformations will be applied to a particular object is start at that object and run a finger up the lines of code. The order in which the transformations are encountered is the order in which they will be applied to the object.

Suppose we don’t want every transformation to apply to every object? It would be nice to apply a transformation and then unapply it. We can do this: we save the transformation matrix in its pre-alteration state, apply a new transformation (or two or three…), draw our object, and then revert back to the version that we saved earlier.

gl.glPushMatrix(); // save current state of transformation matrix { gl.glRotated(90, 0, 1, 0); // rotate 90 degrees around the positive y-axis glut.glutWireTeapot(1.0); // the teapot is rotated } gl.glPopMatrix(); // revert to saved version of transformation matrix gl.glPushMatrix(); // save transformation matrix (again) { gl.glTranslated(10, 0, 0); // translate 10 units along the positive x-axis glut.glutWireTetrahedron; // the tetrahedron is ONLY translated } gl.glPopMatrix(); // revert to saved (again) gl.glPushMatrix(); // save the transformation matrix a last time { gl.glScaled(1, 1, 3); // scale, leaving x- and y-axes unchanged, but triple z glut.glutWireIcosahedron(); // the icosahedron is ONLY scaled } gl.glPopMatrix(); // reverto saved a last time // anything that follows will be unaffected by our transformations! |

Seth Battis January 5th, 2011

Posted In: Handouts

Tags: Java, JOGL, OpenGL, programming

Each OpenGL primitive (well, each OpenGL GLUT primitive) can be drawn either as a solid (filled) shape or as a wireframe shape. The two method calls are identical in parameters by differ in their names (as listed below). Each of the methods listed below is a method of the GLUT object, so a primitive would be drawn as a method call of that object:

glut.glutSolidCube(1.0); |

Usually a cube is drawn with unit (1) side length and then scaled to the size desired. This make the cube ideal as the “base shape” for any rectangular shape (since the scaling can be different along each of the x-, y-, and z-axes). |
||

Spheres are not actually spherical, they are approximated with polyhedrons. The slices parameter defines how many slices (like orange wedges — the longitude lines) the sphere is broken into, while stacks defines how many latitude divisions (rings) the sphere is divided into. Obviously more slices and stacks results in a polyhedron more closely approximating a sphere… but also in a larger number of polygons and thus greater load on the computer. (And, remember, the number of polygons is equal to slices × stacks: 10 slices and 10 stacks gets you 100 polygons.) |
||

The cylinder is (surprisingly, at least to this author) drawn along the z-axis — that is, with the eye staring down the barrel of it from a “normal” default viewpoint). It too is divided into slices and stacks, and in the same manner. Often one needs only a single stack (thereby allowing for the maximizing of slices and thus cylindricality). |
||

The cone too is drawn along the z-axis (like the cylinder). It too is broken into slices and stacks. |
||

The torus has two radii because the inner radius is the radius of the rings circling the “donut”, while the outer radius is the radius of the donut itself. The number of sides refers to the number of sides on the inner radius, while the number of rings is the number of inner radius-sized rings. |
||

It pretty much does what it says. Why a teapot? This is no ordinary teapot: this is the Utah Teapot. |
||

Also available:
These all do pretty much what they sound like. |

Seth Battis January 5th, 2011

Posted In: Handouts

Tags: Java, JOGL, OpenGL, programming