## CS424 Notes, 5 March 2012

- Some functions from gl-matrix.js
- mat4 functions that return a 4-by-4 matrix (and have an optional "destination" parameter):
**mat4.identity()**, (returns a matrix representing the identity transform, which represents no change at all)**mat4.create(mat)**, for a 4-by-4 matrix*mat*(creates a new matrix that is a copy of*mat*)**mat4.translate(mat, vec)**, for a 4-by-4 matrix*mat*and a 3-vector*vec***mat4.scale(mat, vec)**, for a 4-by-4 matrix*mat*and a 3-vector*vec***mat4.translate(mat, vec)**, for a 4-by-4 matrix*mat*and a 3-vector*vec***mat4.rotate(mat, radians, axis)**, for a 4-by-4 matrix*mat*and a 3-vector*axis***mat4.rotateX(mat, radians)**, rotation about the x-axis**mat4.rotateY(mat, radians)**, rotation about the y-axis**mat4.rotateZ(mat, radians)**, rotation about the z-axis**mat4.inverse(mat)**, for a 4-by-4 matrix*mat*(returns the inverse matrix, that "undoes"*mat*); returns null if no inverse exists

- More mat4 functions, which create commonly used mat4 viewing and projection matrices [see below].
**mat4.lookAt(eye,center,up)**, where*eye*,*center*, and*up*are 3-vectors (creates a viewing transform matrix the puts the camera/viewer at*eye*, looking in the direction of*center*, and oriented so that*up*appears to point upwards in the view)**mat4.ortho(left,right,bottom,top,near,far)**, where the parameters are numbers (creates an orthogonal projection matrix)**mat4.frustum(left,right,bottom,top,near,far)**, where the parameters are numbers (creates a perspective projection matrix)**mat4.perspective(fovy, aspect, near, far)**, where the parameters are numbers (creates a perspective projection matrix in a more convenient way)

- Note:
*gl.lookAt*is covered in last Friday's notes. We will look at the general idea of projection today, and we'll get to the gl-matrix.js projection functions on Wednesday.

- mat4 functions that return a 4-by-4 matrix (and have an optional "destination" parameter):
- Modeling and Viewing Example
- When setting up the view with
*gl.lookAt*, the*gl.lookAt*is the first function called. It creates a transform matrix that represents the viewing transformation, with no modeling transform. Any modeling transforms are then applied to the viewing transform matrix, before objects are drawn. Remember that the objects will then be*first*transformed by the modeling transform, to place then in the world. The the viewing transform is applied to show the world from the point of view of the camera/viewer. - Here is an example that uses some very simple hierarchical graphics:
/** * Draws one frame; time is the time in milliseconds since the animation * started. The picture shows two rotating cubes on the ends of a * rotating rod (which is itself just a scaled cube). Note that the * function, cube(), draws a cube including applying the modelview matrix; * popMatrix() and pushMatrix() save and restore the modelview transform. */ function draw(time) { gl.clearColor(0,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.uniformMatrix4fv(projectionUniformLocation, false, projection ); modelview = mat4.lookAt( [5,5,10], [0,0,0], [0,1,0] ); if (time > 5000) { // (start this rotation after 5 seconds) mat4.rotateY(modelview, ((time-5000)/1000)*(Math.PI/3) ); } pushMatrix(); mat4.translate(modelview, [-1.5,0,0] ); mat4.rotateX(modelview, (time/1000)*(Math.PI/1.13) ); mat4.scale(modelview, [0.5,0.5,0.5]); cube(); popMatrix(); pushMatrix(); mat4.translate(modelview, [1.5,0,0] ); mat4.rotateX(modelview, -(time/1000)*(Math.PI/.873) ); mat4.rotateY(modelview, Math.PI); mat4.scale(modelview, [0.5,0.5,0.5]); cube(); popMatrix(); mat4.scale(modelview, [1.1, 0.1, 0.1]); cube(); }

The picture produced by this draw function looks like this: The live program is at http://math.hws.edu/eck/cs424/s12/notes/mar5/gl-matrix-cube.html.

- When setting up the view with
- Projection.
**Note:**WebGL, like OpenGL ES 2.0, does not actually have any notion of projection! You are responsible for setting up and applying a projection transformation. OpenGL with the fixed-function pipeline, on the other hand, had several standard ways to set up projection transformations. The*gl-matrix.js*library includes some functions that create projection matrixes in the same standard way that traditional OpenGL programmers are used to, and that's what I will discuss here- "Projection" usually refers to projecting a 3-dimensional scene down to a 2-dimensional image (although that's not quite what it means in OpenGL).
- There are two basic types of projection:
*orthogonal*and*perspective*. - Perspective projection gives a realistic view. That is, it shows what you would see if the OpenGL display rectangle on your computer screen were a window into an actual 3D world (one that could extend in front of the screen as well as behind it). It shows a view that you could get by taking a picture of a 3D world with a camera. In a perspective view, the apparent size of an object depends on how far it is away from the viewer. Only things that are in front of the viewer can be seen. In fact, the part of the world that should in view is an infinite pyramid, with the viewer at the apex of the pyramid.
- However, OpenGL can't actually show everything in this pyramid, because of
its use of the depth buffer to solve the hidden surface problem. Since the
depth buffer can only store a finite range of depth values, it can't
represent the entire range of depth values for the infinite pyramid that
is theoretically in view. Only objects in a certain range of distances from
the viewer are shown in the image that OpenGL produces. That range of distances
is specified by two values,
*near*and*far*. Both of these values must be positive numbers, and*far*must be greater than*near*. Anything that is closer to the viewer than the*near*distance or farther away than the*far*distance is discarded and does not appear in the rendered image. The volume of space that is represented in the image is thus a "truncated pyramid." This pyramid is the*view volume*: The view volume is bounded by six planes -- the sides, top, and bottom of the pyramid. These planes are called clipping planes because anything that lies on the wrong side of each plane is clipped away. - Orthographic projections are comparatively easy to understand: A 3D world is projected onto a 2D image by discarding the z-coordinate of the eye-coordinate system. This type of projection is unrealistic in that it is not what a viewer would see. For example, the apparent size of an object does not depend on its distance from the viewer. Objects in back of the viewer as well as in front of the viewer are visible in the image. Orthographic projections are still useful, however, especially in interactive modeling programs where it is useful to see true sizes and angles, unmodified by perspective.
- In fact, it's not really clear what
it means to say that there is a viewer in the case of orthographic projection.
Nevertheless, in OpenGL there is a viewer, which is located at the eye-coordinate
origin, facing in the direction of the negative z-axis. Theoretically, a rectangular corridor
extending infinitely in both directions, in front of the viewer and in back, would be in view.
However, as with perspective projection, only a finite segment of this infinite corridor can
actually be shown in an OpenGL image. This finite view volume is a parallelepiped -- a rectangular
solid -- that is cut out of the infinite corridor by a
*near*clipping plane and a*far*clipping plane. The value of*far*must be greater than*near*, but for an orthographic projection, the value of*near*is allowed to be negative, putting the "near" clipping plane behind the viewer, as it is in this illustration: Note that a negative value for*near*puts the near clipping plane on the**positive**z-axis, which is behind the viewer.